From 063fd290659e55ede747a07cc27fdb02f15864c4 Mon Sep 17 00:00:00 2001 From: "Gpound.liu" <141617023+Gggpound@users.noreply.github.com> Date: Wed, 30 Oct 2024 21:30:05 +0800 Subject: [PATCH] refactor(formula-editor): init (#3833) Co-authored-by: zhangw --- .../doc-editor-bridge.controller.ts | 5 + .../services/editor/editor-manager.service.ts | 75 +++++- .../components/panel/rule-edit/colorScale.tsx | 55 ++-- .../components/panel/rule-edit/dataBar.tsx | 52 ++-- .../components/panel/rule-edit/formula.tsx | 67 +++-- .../components/panel/rule-edit/iconSet.tsx | 94 ++++--- .../panel/rule-edit/index.module.less | 2 +- .../src/components/panel/rule-edit/index.tsx | 22 +- .../src/views/components/detail/index.tsx | 12 +- .../formula-input/custom-formula-input.tsx | 47 ++-- .../formula-input/list-formula-input.tsx | 43 +-- .../src/controllers/prompt.controller.ts | 156 ++++++----- packages/sheets-formula-ui/src/index.ts | 1 + .../src/sheets-formula-ui.plugin.ts | 4 +- .../help-function/HelpFunction.tsx | 198 ++++++++++++++ .../help-function/index.module.less | 129 +++++++++ .../hooks/useFormulaDescribe.ts | 87 ++++++ .../formula-editor/hooks/useFormulaSearch.ts | 107 ++++++++ .../formula-editor/hooks/useHighlight.ts | 176 +++++++++++++ .../hooks/useResizeScrollObserver.ts | 47 ++++ .../formula-editor/hooks/useSelectionAdd.ts | 185 +++++++++++++ .../hooks/useSheetSelectionChange.ts | 237 +++++++++++++++++ .../views/formula-editor/hooks/useStateRef.ts | 23 ++ .../views/formula-editor/hooks/useVerify.ts | 46 ++++ .../views/formula-editor/index.module.less | 37 +++ .../src/views/formula-editor/index.tsx | 248 ++++++++++++++++++ .../search-function/SearchFunction.tsx | 233 ++++++++++++++++ .../search-function/index.module.less | 55 ++++ .../formula-editor/utils/getFormulaText.tsx | 24 ++ .../views/range-selector/hooks/useFocus.ts | 40 +++ .../range-selector/hooks/useFormulaToken.ts | 3 +- .../range-selector/hooks/useHighlight.ts | 13 +- .../hooks/useLeftAndRightArrow.ts | 82 ++++++ .../range-selector/hooks/useOnlyOneRange.ts | 37 +++ .../range-selector/hooks/useRefactorEffect.ts | 39 +-- .../views/range-selector/hooks/useRefocus.ts | 28 ++ .../range-selector/hooks/useResetSelection.ts | 43 +++ .../hooks/useSheetSelectionChange.ts | 34 +-- .../views/range-selector/hooks/useVerify.ts | 18 +- .../views/range-selector/index.module.less | 2 +- .../src/views/range-selector/index.tsx | 138 ++++++---- .../utils/findIndexFromSequenceNodes.ts | 2 +- .../utils/getOffsetFromSequenceNodes.ts | 2 +- .../src/views/CellLinkEdit/index.tsx | 14 +- packages/sheets-ui/src/common/keys.ts | 2 + .../editor/utils/isEmbeddingFormulaEditor.ts | 22 ++ .../editor/utils/isRangeSelector.ts | 2 +- packages/sheets-ui/src/index.ts | 3 +- .../views/defined-name/DefinedNameInput.tsx | 103 ++++---- .../views/permission/panel-detail/index.tsx | 1 + packages/ui/src/index.ts | 1 + .../sidebar/desktop-sidebar.service.ts | 16 +- .../services/sidebar/hooks/useSidebarClick.ts | 35 +++ .../src/services/sidebar/sidebar.service.ts | 7 +- .../src/views/components/sidebar/Sidebar.tsx | 14 +- 55 files changed, 2758 insertions(+), 410 deletions(-) create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/help-function/HelpFunction.tsx create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/help-function/index.module.less create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/hooks/useFormulaDescribe.ts create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/hooks/useFormulaSearch.ts create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/hooks/useHighlight.ts create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/hooks/useResizeScrollObserver.ts create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/hooks/useSelectionAdd.ts create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/hooks/useSheetSelectionChange.ts create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/hooks/useStateRef.ts create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/hooks/useVerify.ts create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/index.module.less create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/index.tsx create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/search-function/SearchFunction.tsx create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/search-function/index.module.less create mode 100644 packages/sheets-formula-ui/src/views/formula-editor/utils/getFormulaText.tsx create mode 100644 packages/sheets-formula-ui/src/views/range-selector/hooks/useFocus.ts create mode 100644 packages/sheets-formula-ui/src/views/range-selector/hooks/useLeftAndRightArrow.ts create mode 100644 packages/sheets-formula-ui/src/views/range-selector/hooks/useOnlyOneRange.ts create mode 100644 packages/sheets-formula-ui/src/views/range-selector/hooks/useRefocus.ts create mode 100644 packages/sheets-formula-ui/src/views/range-selector/hooks/useResetSelection.ts create mode 100644 packages/sheets-ui/src/controllers/editor/utils/isEmbeddingFormulaEditor.ts create mode 100644 packages/ui/src/services/sidebar/hooks/useSidebarClick.ts diff --git a/packages/docs-ui/src/controllers/render-controllers/doc-editor-bridge.controller.ts b/packages/docs-ui/src/controllers/render-controllers/doc-editor-bridge.controller.ts index 1081db4cd9c..a4d8584162a 100644 --- a/packages/docs-ui/src/controllers/render-controllers/doc-editor-bridge.controller.ts +++ b/packages/docs-ui/src/controllers/render-controllers/doc-editor-bridge.controller.ts @@ -194,6 +194,11 @@ export class DocEditorBridgeController extends Disposable implements IRenderModu return; } + // TODO:@ggg: Docs-ui should not rely on sheet-ui stuff, and the code needs to be removed after the editor is refactored. + if (unitId.includes('range_selector') || unitId.includes('embedding_formula_editor')) { + return; + } + this._editorService.blur(); }) ); diff --git a/packages/docs-ui/src/services/editor/editor-manager.service.ts b/packages/docs-ui/src/services/editor/editor-manager.service.ts index 4166919f4c4..ec65a3bb0d8 100644 --- a/packages/docs-ui/src/services/editor/editor-manager.service.ts +++ b/packages/docs-ui/src/services/editor/editor-manager.service.ts @@ -18,7 +18,7 @@ import type { DocumentDataModel, IDisposable, IDocumentBody, IDocumentData, Null import type { ISuccinctDocRangeParam, Scene } from '@univerjs/engine-render'; import type { Observable } from 'rxjs'; import type { IEditorConfigParams, IEditorStateParams } from './editor'; -import { createIdentifier, DEFAULT_EMPTY_DOCUMENT_VALUE, Disposable, EDITOR_ACTIVATED, FOCUSING_EDITOR_INPUT_FORMULA, FOCUSING_EDITOR_STANDALONE, FOCUSING_UNIVER_EDITOR_STANDALONE_SINGLE_MODE, HorizontalAlign, ICommandService, IContextService, Inject, IUndoRedoService, IUniverInstanceService, toDisposable, UniverInstanceType, VerticalAlign } from '@univerjs/core'; +import { createIdentifier, DEFAULT_EMPTY_DOCUMENT_VALUE, Disposable, EDITOR_ACTIVATED, FOCUSING_EDITOR_INPUT_FORMULA, FOCUSING_EDITOR_STANDALONE, FOCUSING_UNIVER_EDITOR_STANDALONE_SINGLE_MODE, HorizontalAlign, ICommandService, IContextService, Inject, isInternalEditorID, IUndoRedoService, IUniverInstanceService, toDisposable, UniverInstanceType, VerticalAlign } from '@univerjs/core'; import { DocSelectionManagerService } from '@univerjs/docs'; import { isReferenceStrings, LexerTreeBuilder, operatorToken } from '@univerjs/engine-formula'; import { IRenderManagerService } from '@univerjs/engine-render'; @@ -46,20 +46,35 @@ export interface IEditorInputFormulaParam { formulaString: string; } +/** + * @deprecated + */ export interface IEditorService { getEditor(id?: string): Readonly>; register(config: IEditorConfigParams, container: HTMLDivElement): IDisposable; + /** + * @deprecated + */ isVisible(id: string): Nullable; inputFormula$: Observable; + /** + * @deprecated + */ setFormula(formulaString: string): void; resize$: Observable; + /** + * @deprecated + */ resize(id: string): void; + /** + * @deprecated + */ getAllEditor(): Map; /** @@ -80,43 +95,91 @@ export interface IEditorService { isSheetEditor(editorUnitId: string): boolean; closeRangePrompt$: Observable; + /** + * @deprecated + */ closeRangePrompt(): void; blur$: Observable; + /** + * @deprecated + */ blur(): void; focus$: Observable; + /** + * @deprecated + */ focus(editorUnitId?: string): void; setValue$: Observable; valueChange$: Observable>; + /** + * @deprecated + */ setValue(val: string, editorUnitId?: string): void; + /** + * @deprecated + */ setValueNoRefresh(val: string, editorUnitId?: string): void; + /** + * @deprecated + */ setRichValue(body: IDocumentBody, editorUnitId?: string): void; + /** + * @deprecated + */ getFirstEditor(): Editor; focusStyle$: Observable>; + /** + * @deprecated + */ focusStyle(editorUnitId: Nullable): void; + /** + * @deprecated + */ refreshValueChange(editorId: string): void; + /** + * @deprecated + */ checkValueLegality(editorId: string): boolean; + /** + * @deprecated + */ getValue(id: string): Nullable; + /** + * @deprecated + */ getRichValue(id: string): Nullable; + /** + * @deprecated + */ changeSpreadsheetFocusState(state: boolean): void; + /** + * @deprecated + */ getSpreadsheetFocusState(): boolean; + /** + * @deprecated + */ selectionChangingState(): boolean; singleSelection$: Observable; + /** + * @deprecated + */ singleSelection(state: boolean): void; setFocusId(id: Nullable): void; @@ -273,9 +336,11 @@ export class EditorService extends Disposable implements IEditorService, IDispos editor.setFocus(true); this._contextService.setContextValue(EDITOR_ACTIVATED, true); - this._contextService.setContextValue(FOCUSING_EDITOR_STANDALONE, true); - this._contextService.setContextValue(FOCUSING_UNIVER_EDITOR_STANDALONE_SINGLE_MODE, editor.isSingle()); + if (!isInternalEditorID(editorUnitId)) { + this._contextService.setContextValue(FOCUSING_EDITOR_STANDALONE, true); + this._contextService.setContextValue(FOCUSING_UNIVER_EDITOR_STANDALONE_SINGLE_MODE, editor.isSingle()); + } if (!this._spreadsheetFocusState) { this.singleSelection(!!editor.isSingleChoice()); @@ -353,8 +418,8 @@ export class EditorService extends Disposable implements IEditorService, IDispos this.focusStyle(editorUnitId); this._focus$.next({ - startOffset: valueCount - 2, - endOffset: valueCount - 2, + startOffset: valueCount, + endOffset: valueCount, }); } diff --git a/packages/sheets-conditional-formatting-ui/src/components/panel/rule-edit/colorScale.tsx b/packages/sheets-conditional-formatting-ui/src/components/panel/rule-edit/colorScale.tsx index 81ad9b0c737..04777dd51be 100644 --- a/packages/sheets-conditional-formatting-ui/src/components/panel/rule-edit/colorScale.tsx +++ b/packages/sheets-conditional-formatting-ui/src/components/panel/rule-edit/colorScale.tsx @@ -14,22 +14,24 @@ * limitations under the License. */ -import { createInternalEditorID, IUniverInstanceService, LocaleService, UniverInstanceType, useDependency } from '@univerjs/core'; -import { InputNumber, Select } from '@univerjs/design'; -import { TextEditor } from '@univerjs/docs-ui'; -import { CFRuleType, CFValueType, createDefaultValueByValueType, SHEET_CONDITIONAL_FORMATTING_PLUGIN } from '@univerjs/sheets-conditional-formatting'; -import React, { useEffect, useMemo, useState } from 'react'; import type { Workbook } from '@univerjs/core'; import type { IColorScale, IConditionalFormattingRuleConfig } from '@univerjs/sheets-conditional-formatting'; +import type { IStyleEditorProps } from './type'; + +import { IUniverInstanceService, LocaleService, UniverInstanceType, useDependency } from '@univerjs/core'; +import { InputNumber, Select } from '@univerjs/design'; +import { CFRuleType, CFValueType, createDefaultValueByValueType } from '@univerjs/sheets-conditional-formatting'; +import { FormulaEditor } from '@univerjs/sheets-formula-ui'; +import { useSidebarClick } from '@univerjs/ui'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import { ColorPicker } from '../../color-picker'; import { Preview } from '../../preview'; import stylesBase from '../index.module.less'; import styles from './index.module.less'; -import type { IStyleEditorProps } from './type'; const createOptionItem = (text: string, localeService: LocaleService) => ({ label: localeService.t(`sheet.cf.valueType.${text}`), value: text }); -const TextInput = (props: { id: string; type: CFValueType | 'none';value: number | string;onChange: (v: number | string) => void; className: string }) => { +const TextInput = (props: { id: string; type: CFValueType | 'none'; value: number | string; onChange: (v: number | string) => void; className: string }) => { const { type, className, onChange, id, value } = props; const univerInstanceService = useDependency(IUniverInstanceService); const unitId = univerInstanceService.getCurrentUnitForType(UniverInstanceType.UNIVER_SHEET)!.getUnitId(); @@ -50,21 +52,31 @@ const TextInput = (props: { id: string; type: CFValueType | 'none';value: number min: Number.MIN_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER, }; }, [type]); + + const formulaEditorActionsRef = useRef[0]['actions']>({}); + const [isFocusFormulaEditor, isFocusFormulaEditorSet] = useState(false); + + useSidebarClick((e: MouseEvent) => { + const handleOutClick = formulaEditorActionsRef.current?.handleOutClick; + handleOutClick && handleOutClick(e, () => isFocusFormulaEditorSet(false)); + }); + if (type === CFValueType.formula) { return ( - { - const formula = v || ''; - onChange(formula); - }} - /> +
+ { + const formula = v || ''; + onChange(formula); + }} + onFocus={() => isFocusFormulaEditorSet(true)} + actions={formulaEditorActionsRef.current} + /> +
); } else { return props.onChange(v || 0)} {...config} />; @@ -217,6 +229,7 @@ export const ColorScaleStyleEditor = (props: IStyleEditorProps) => {
{localeService.t('sheet.cf.valueType.min')}
{ @@ -283,6 +297,7 @@ export const ColorScaleStyleEditor = (props: IStyleEditorProps) => {
{localeService.t('sheet.cf.valueType.max')}
{ @@ -298,6 +311,7 @@ export const DataBarStyleEditor = (props: IStyleEditorProps) => {
{localeService.t('sheet.cf.valueType.max')}
{ handleValueTypeChange(v as CFNumberOperator, index); }} /> +
@@ -218,36 +231,38 @@ export const DefinedNameInput = (props: IDefinedNameInputProps) => { {localeService.t('definedName.ratioFormula')}
- {RangeSelector && typeValue === 'range' && ( - { isFocusRangeSelectorSet(false); }} - /> - )} - {typeValue !== 'range' && ( -
- isFocusRangeSelectorSet(true)} + actions={rangeSelectorActionsRef.current} + isSupportAcrossSheet + /> + ) + ) + : (FormulaEditor && ( + { + const formula = v || ''; + formulaEditorChange(formula); + }} + onVerify={(res: boolean) => { + setValidFormulaOrRange(res); + }} + onFocus={() => isFocusFormulaEditorSet(true)} + actions={formulaEditorActionsRef.current} /> -
- )} - + ))}