mirror of
https://github.com/dream-num/univer.git
synced 2026-09-24 15:32:18 +08:00
feat: doc quick insert placeholder (#4841)
This commit is contained in:
@@ -70,6 +70,7 @@
|
||||
"@univerjs/design": "workspace:*",
|
||||
"@univerjs/docs": "workspace:*",
|
||||
"@univerjs/docs-drawing": "workspace:*",
|
||||
"@univerjs/docs-drawing-ui": "workspace:*",
|
||||
"@univerjs/docs-ui": "workspace:*",
|
||||
"@univerjs/drawing": "workspace:*",
|
||||
"@univerjs/drawing-ui": "workspace:*",
|
||||
|
||||
@@ -23,6 +23,7 @@ import { of } from 'rxjs';
|
||||
import { DeleteSearchKeyCommand } from '../commands/commands/doc-quick-insert.command';
|
||||
import { CloseQuickInsertPopupOperation, ShowQuickInsertPopupOperation } from '../commands/operations/quick-insert-popup.operation';
|
||||
import { DocQuickInsertPopupService } from '../services/doc-quick-insert-popup.service';
|
||||
import { KeywordInputPlaceholder } from '../views/KeywordInputPlaceholder';
|
||||
import { QuickInsertPopup } from '../views/QuickInsertPopup';
|
||||
import { builtInMenus } from './built-in-menus';
|
||||
|
||||
@@ -52,6 +53,7 @@ export class DocQuickInsertUIController extends Disposable {
|
||||
|
||||
private _initComponents() {
|
||||
this.disposeWithMe(this._componentManager.register(QuickInsertPopup.componentKey, QuickInsertPopup));
|
||||
this.disposeWithMe(this._componentManager.register(KeywordInputPlaceholder.componentKey, KeywordInputPlaceholder));
|
||||
this.disposeWithMe(this._componentManager.register('DividerSingle', DividerSingle));
|
||||
this.disposeWithMe(this._componentManager.register('TextSingle', TextSingle));
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ const locale: typeof zhCN = {
|
||||
group: {
|
||||
basics: 'Basics',
|
||||
},
|
||||
placeholder: 'No results found',
|
||||
keywordInputPlaceholder: 'Enter keywords',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ const locale: typeof zhCN = {
|
||||
group: {
|
||||
basics: 'بنیادی',
|
||||
},
|
||||
placeholder: 'هیچ نتیجهای یافت نشد',
|
||||
keywordInputPlaceholder: 'وارد کلمات کلیدی',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ const locale: typeof enUS = {
|
||||
group: {
|
||||
basics: 'Basiques',
|
||||
},
|
||||
placeholder: 'Aucun résultat',
|
||||
keywordInputPlaceholder: 'Entrez des mots clés',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ const locale: typeof zhCN = {
|
||||
group: {
|
||||
basics: 'Основные',
|
||||
},
|
||||
placeholder: 'Нет результатов',
|
||||
keywordInputPlaceholder: 'Введите ключевые слова',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ const locale: typeof zhCN = {
|
||||
group: {
|
||||
basics: 'Cơ bản',
|
||||
},
|
||||
placeholder: 'Không có kết quả',
|
||||
keywordInputPlaceholder: 'Nhập từ khóa',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,8 @@ const locale = {
|
||||
group: {
|
||||
basics: '基础',
|
||||
},
|
||||
placeholder: '暂无结果',
|
||||
keywordInputPlaceholder: '输入关键词',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ const locale: typeof zhCN = {
|
||||
group: {
|
||||
basics: '基礎',
|
||||
},
|
||||
placeholder: '無結果',
|
||||
keywordInputPlaceholder: '輸入關鍵詞',
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -18,9 +18,11 @@ import type { DocumentDataModel, IDisposable, Nullable } from '@univerjs/core';
|
||||
import type { IInsertCommandParams } from '@univerjs/docs-ui';
|
||||
import type { Observable } from 'rxjs';
|
||||
import { Disposable, ICommandService, Inject, IUniverInstanceService, UniverInstanceType } from '@univerjs/core';
|
||||
import { DocFloatDomController } from '@univerjs/docs-drawing-ui';
|
||||
import { DocCanvasPopManagerService } from '@univerjs/docs-ui';
|
||||
import { BehaviorSubject, distinctUntilChanged, map } from 'rxjs';
|
||||
import { BehaviorSubject, combineLatest, distinctUntilChanged, map, tap } from 'rxjs';
|
||||
import { DeleteSearchKeyCommand } from '../commands/commands/doc-quick-insert.command';
|
||||
import { KeywordInputPlaceholder } from '../views/KeywordInputPlaceholder';
|
||||
import { QuickInsertPopup } from '../views/QuickInsertPopup';
|
||||
|
||||
export interface IDocPopupGroupItem {
|
||||
@@ -42,7 +44,7 @@ export type DocPopupMenu = IDocPopupGroupItem | IDocPopupMenuItem;
|
||||
export interface IDocPopup {
|
||||
keyword: string;
|
||||
menus$: Observable<DocPopupMenu[]>;
|
||||
placeholder?: React.ReactNode;
|
||||
Placeholder?: React.ComponentType;
|
||||
preconditions?: (params: IInsertCommandParams) => boolean;
|
||||
}
|
||||
|
||||
@@ -75,10 +77,16 @@ export class DocQuickInsertPopupService extends Disposable {
|
||||
|
||||
private _menuSelectedCallbacks: Set<(menu: IDocPopupMenuItem) => void> = new Set();
|
||||
|
||||
private _inputPlaceholderRenderRoot: {
|
||||
unmount?: IDisposable;
|
||||
mount: () => void;
|
||||
} | null = null;
|
||||
|
||||
constructor(
|
||||
@Inject(DocCanvasPopManagerService) private readonly _docCanvasPopupManagerService: DocCanvasPopManagerService,
|
||||
@Inject(IUniverInstanceService) private readonly _univerInstanceService: IUniverInstanceService,
|
||||
@Inject(ICommandService) private readonly _commandService: ICommandService
|
||||
@Inject(ICommandService) private readonly _commandService: ICommandService,
|
||||
@Inject(DocFloatDomController) private readonly _docFloatDomController: DocFloatDomController
|
||||
) {
|
||||
super();
|
||||
|
||||
@@ -94,6 +102,21 @@ export class DocQuickInsertPopupService extends Disposable {
|
||||
}),
|
||||
distinctUntilChanged()
|
||||
);
|
||||
|
||||
this.disposeWithMe(combineLatest([
|
||||
this.filterKeyword$.pipe(tap((filterKeyword) => {
|
||||
if (filterKeyword.length > 0) {
|
||||
this._inputPlaceholderRenderRoot?.unmount?.dispose();
|
||||
} else {
|
||||
this._inputPlaceholderRenderRoot?.mount();
|
||||
}
|
||||
})),
|
||||
this.editPopup$.pipe(tap((popup) => {
|
||||
if (!popup) {
|
||||
this._inputPlaceholderRenderRoot?.unmount?.dispose();
|
||||
}
|
||||
})),
|
||||
]).subscribe());
|
||||
}
|
||||
|
||||
resolvePopup(keyword: string) {
|
||||
@@ -108,6 +131,19 @@ export class DocQuickInsertPopupService extends Disposable {
|
||||
};
|
||||
}
|
||||
|
||||
private _createInputPlaceholderRenderRoot(mount: () => IDisposable) {
|
||||
const renderRoot: {
|
||||
unmount?: IDisposable;
|
||||
mount: () => void;
|
||||
} = {
|
||||
mount() {
|
||||
this.unmount = mount();
|
||||
},
|
||||
};
|
||||
|
||||
return renderRoot;
|
||||
}
|
||||
|
||||
showPopup(options: { popup: IDocPopup; index: number; unitId: string }) {
|
||||
const { popup, index, unitId } = options;
|
||||
|
||||
@@ -125,6 +161,23 @@ export class DocQuickInsertPopupService extends Disposable {
|
||||
unitId
|
||||
);
|
||||
|
||||
this._inputPlaceholderRenderRoot = this._createInputPlaceholderRenderRoot(() => {
|
||||
const disposable = this._docCanvasPopupManagerService.attachPopupToRange(
|
||||
{ startOffset: index + 1, endOffset: index + 1, collapsed: false },
|
||||
{
|
||||
componentKey: KeywordInputPlaceholder.componentKey,
|
||||
onClickOutside: () => {
|
||||
disposable.dispose();
|
||||
},
|
||||
direction: 'horizontal',
|
||||
},
|
||||
unitId
|
||||
);
|
||||
|
||||
return disposable;
|
||||
});
|
||||
this._inputPlaceholderRenderRoot.mount();
|
||||
|
||||
this._editPopup$.next({ disposable, popup, anchor: index, unitId });
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { LocaleService } from '@univerjs/core';
|
||||
import { useDependency } from '@univerjs/ui';
|
||||
|
||||
const KeywordInputPlaceholder = () => {
|
||||
const localeService = useDependency(LocaleService);
|
||||
// TODO: 需要根据fontSize来计算高度跟偏移
|
||||
return <div className="univer-translate-y-1.5 univer-text-sm univer-text-gray-500">{localeService.t('docQuickInsert.keywordInputPlaceholder')}</div>;
|
||||
};
|
||||
|
||||
KeywordInputPlaceholder.componentKey = 'KeywordInputPlaceholder';
|
||||
|
||||
export { KeywordInputPlaceholder };
|
||||
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Copyright 2023-present DreamNum Co., Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { LocaleService } from '@univerjs/core';
|
||||
import { useDependency } from '@univerjs/ui';
|
||||
|
||||
export const QuickInsertPlaceholder = () => {
|
||||
const localeService = useDependency(LocaleService);
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
univer-flex univer-h-full univer-items-center univer-justify-center univer-rounded-lg univer-bg-white
|
||||
univer-px-12 univer-py-6 univer-text-gray-400
|
||||
`}
|
||||
>
|
||||
<span>{localeService.t('docQuickInsert.placeholder')}</span>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -21,6 +21,7 @@ import { ComponentManager, IShortcutService, KeyCode, useDependency, useObservab
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { CloseQuickInsertPopupOperation } from '../commands/operations/quick-insert-popup.operation';
|
||||
import { DocQuickInsertPopupService } from '../services/doc-quick-insert-popup.service';
|
||||
import { QuickInsertPlaceholder } from './QuickInsertPlaceholder';
|
||||
|
||||
function filterMenusByKeyword(menus: DocPopupMenu[], keyword: string) {
|
||||
return menus
|
||||
@@ -251,6 +252,8 @@ const QuickInsertPopup = () => {
|
||||
|
||||
const hasMenus = filteredMenus.length > 0;
|
||||
|
||||
const Placeholder = currentPopup?.popup.Placeholder || QuickInsertPlaceholder;
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(`
|
||||
@@ -266,7 +269,7 @@ const QuickInsertPopup = () => {
|
||||
</Menu>
|
||||
</div>
|
||||
)
|
||||
: currentPopup?.popup.placeholder}
|
||||
: <Placeholder />}
|
||||
</div>
|
||||
|
||||
);
|
||||
|
||||
@@ -279,6 +279,7 @@ export class DocCanvasPopManagerService extends Disposable {
|
||||
|
||||
const { positions: bounds, positions$: bounds$, disposable } = this._createRangePositionObserver(range, currentRender);
|
||||
const position$ = bounds$.pipe(map((bounds) => direction.includes('top') ? bounds[0] : bounds[bounds.length - 1]));
|
||||
|
||||
const id = this._globalPopupManagerService.addPopup({
|
||||
...popup,
|
||||
unitId,
|
||||
@@ -287,10 +288,9 @@ export class DocCanvasPopManagerService extends Disposable {
|
||||
anchorRect$: position$,
|
||||
excludeRects: bounds,
|
||||
excludeRects$: bounds$,
|
||||
direction:
|
||||
(direction.includes('top') || direction.includes('bottom')) ?
|
||||
bounds.length > 1 ? multipleDirection ?? direction : direction
|
||||
: 'bottom',
|
||||
direction: (['top', 'bottom', 'horizontal'].includes(direction)) ?
|
||||
bounds.length > 1 ? multipleDirection ?? direction : direction
|
||||
: 'bottom',
|
||||
canvasElement: currentRender.engine.getCanvasElement(),
|
||||
});
|
||||
|
||||
|
||||
Generated
+3
@@ -1459,6 +1459,9 @@ importers:
|
||||
'@univerjs/docs-drawing':
|
||||
specifier: workspace:*
|
||||
version: link:../docs-drawing
|
||||
'@univerjs/docs-drawing-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../docs-drawing-ui
|
||||
'@univerjs/docs-ui':
|
||||
specifier: workspace:*
|
||||
version: link:../docs-ui
|
||||
|
||||
Reference in New Issue
Block a user