mirror of
https://github.com/dream-num/univer.git
synced 2026-09-24 15:32:18 +08:00
feat(ui): add new ribbon type (#6105)
This commit is contained in:
@@ -93,11 +93,11 @@
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@univerjs-infra/shared": "workspace:*",
|
||||
"detect-port": "^2.1.0",
|
||||
"esbuild": "^0.25.11",
|
||||
"esbuild": "^0.25.12",
|
||||
"esbuild-plugin-alias": "^0.2.1",
|
||||
"esbuild-plugin-clean": "^1.0.1",
|
||||
"esbuild-plugin-copy": "^2.1.1",
|
||||
"esbuild-plugin-vue3": "^0.4.2",
|
||||
"esbuild-plugin-vue3": "^0.5.1",
|
||||
"esbuild-style-plugin": "^1.6.3",
|
||||
"fs-extra": "^11.3.2",
|
||||
"minimist": "^1.2.8",
|
||||
|
||||
@@ -122,6 +122,7 @@ function createNewInstance() {
|
||||
[UniverRenderEnginePlugin],
|
||||
[UniverUIPlugin, {
|
||||
container: 'app',
|
||||
// ribbonType: 'classic',
|
||||
}],
|
||||
[UniverWebComponentAdapterPlugin],
|
||||
[UniverVue3AdapterPlugin],
|
||||
|
||||
+7
-7
@@ -3,7 +3,7 @@
|
||||
"type": "module",
|
||||
"version": "0.11.0",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.18.3",
|
||||
"packageManager": "pnpm@10.20.0",
|
||||
"author": "DreamNum Co., Ltd. <developer@univer.ai>",
|
||||
"license": "Apache-2.0",
|
||||
"funding": {
|
||||
@@ -45,21 +45,21 @@
|
||||
"release": "release-it"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^6.1.0",
|
||||
"@antfu/eslint-config": "^6.2.0",
|
||||
"@commitlint/cli": "^20.1.0",
|
||||
"@commitlint/config-conventional": "^20.0.0",
|
||||
"@eslint-react/eslint-plugin": "^2.2.4",
|
||||
"@eslint-react/eslint-plugin": "^2.3.1",
|
||||
"@playwright/test": "^1.56.1",
|
||||
"@release-it-plugins/workspaces": "^5.0.3",
|
||||
"@release-it/conventional-changelog": "^10.0.1",
|
||||
"@types/fs-extra": "^11.0.4",
|
||||
"@types/node": "^24.9.2",
|
||||
"@types/node": "^24.10.0",
|
||||
"@types/react": "19.2.2",
|
||||
"@types/react-dom": "19.2.2",
|
||||
"@univerjs-infra/shared": "workspace:*",
|
||||
"@univerjs/design": "workspace:*",
|
||||
"@vitejs/plugin-react": "^5.1.0",
|
||||
"eslint": "9.38.0",
|
||||
"eslint": "9.39.1",
|
||||
"eslint-plugin-format": "^1.0.2",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-react-hooks": "7.0.1",
|
||||
@@ -67,14 +67,14 @@
|
||||
"fs-extra": "^11.3.2",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^16.2.6",
|
||||
"posthog-node": "^5.10.4",
|
||||
"posthog-node": "^5.11.0",
|
||||
"react": "19.2.0",
|
||||
"react-dom": "19.2.0",
|
||||
"release-it": "^19.0.5",
|
||||
"serve": "^14.2.5",
|
||||
"tailwindcss": "3.4.18",
|
||||
"tsx": "^4.20.6",
|
||||
"turbo": "^2.5.8",
|
||||
"turbo": "^2.6.0",
|
||||
"typescript": "^5.9.3",
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import type { IAccessor } from '@univerjs/core';
|
||||
import type { IMenuButtonItem, IMenuSelectorItem, MenuSchemaType } from '@univerjs/ui';
|
||||
import { MenuItemType, RibbonStartGroup } from '@univerjs/ui';
|
||||
import { MenuItemType, RibbonOthersGroup } from '@univerjs/ui';
|
||||
import { ReplayLocalRecordCommand, ReplayLocalRecordOnActiveCommand, ReplayLocalRecordOnNamesakeCommand } from '../commands/commands/replay.command';
|
||||
import { OpenRecordPanelOperation } from '../commands/operations/operation';
|
||||
import { ActionRecorderService } from '../services/action-recorder.service';
|
||||
@@ -67,9 +67,9 @@ export function ReplayLocalRecordOnActiveMenuItemFactory(): IMenuButtonItem {
|
||||
}
|
||||
|
||||
export const menuSchema: MenuSchemaType = {
|
||||
[RibbonStartGroup.OTHERS]: {
|
||||
[RibbonOthersGroup.OTHERS]: {
|
||||
[RECORD_MENU_ITEM_ID]: {
|
||||
order: 2,
|
||||
order: 1,
|
||||
menuItemFactory: RecordMenuItemFactory,
|
||||
[OpenRecordPanelOperation.id]: {
|
||||
order: 1,
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
"@univerjs/themes": "workspace:*",
|
||||
"@wendellhu/redi": "1.0.1",
|
||||
"async-lock": "^1.4.1",
|
||||
"dayjs": "^1.11.18",
|
||||
"dayjs": "^1.11.19",
|
||||
"fast-diff": "1.3.0",
|
||||
"kdbush": "^4.0.2",
|
||||
"lodash-es": "^4.17.21",
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
"@univerjs/themes": "workspace:*",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"dayjs": "^1.11.18",
|
||||
"dayjs": "^1.11.19",
|
||||
"rc-dropdown": "^4.2.1",
|
||||
"rc-menu": "^9.16.0",
|
||||
"rc-virtual-list": "^3.16.1",
|
||||
|
||||
@@ -16,31 +16,31 @@
|
||||
|
||||
import type { MenuSchemaType } from '@univerjs/ui';
|
||||
import { AddDecimalCommand, SetCurrencyCommand, SetPercentCommand, SubtractDecimalCommand } from '@univerjs/sheets-numfmt';
|
||||
import { RibbonDataGroup } from '@univerjs/ui';
|
||||
import { RibbonStartGroup } from '@univerjs/ui';
|
||||
import { OpenNumfmtPanelOperator } from '../commands/operations/open.numfmt.panel.operation';
|
||||
import { AddDecimalMenuItem, CurrencySymbolIconMenuItem, FactoryOtherMenuItem, PercentMenuItem, SubtractDecimalMenuItem } from './menu';
|
||||
|
||||
export const menuSchema: MenuSchemaType = {
|
||||
[RibbonDataGroup.FORMULAS]: {
|
||||
[RibbonStartGroup.LAYOUT]: {
|
||||
[OpenNumfmtPanelOperator.id]: {
|
||||
order: 9,
|
||||
menuItemFactory: FactoryOtherMenuItem,
|
||||
},
|
||||
[SetPercentCommand.id]: {
|
||||
order: 9.1,
|
||||
menuItemFactory: PercentMenuItem,
|
||||
},
|
||||
[SetCurrencyCommand.id]: {
|
||||
order: 0,
|
||||
order: 9.2,
|
||||
menuItemFactory: CurrencySymbolIconMenuItem,
|
||||
},
|
||||
[AddDecimalCommand.id]: {
|
||||
order: 1,
|
||||
order: 9.3,
|
||||
menuItemFactory: AddDecimalMenuItem,
|
||||
},
|
||||
[SubtractDecimalCommand.id]: {
|
||||
order: 2,
|
||||
order: 9.4,
|
||||
menuItemFactory: SubtractDecimalMenuItem,
|
||||
},
|
||||
[SetPercentCommand.id]: {
|
||||
order: 3,
|
||||
menuItemFactory: PercentMenuItem,
|
||||
},
|
||||
[OpenNumfmtPanelOperator.id]: {
|
||||
order: 4,
|
||||
menuItemFactory: FactoryOtherMenuItem,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { ICommand } from '@univerjs/core';
|
||||
import { CommandType, EDITOR_ACTIVATED, ICommandService, IContextService, ThemeService } from '@univerjs/core';
|
||||
import type { ICommand, Workbook } from '@univerjs/core';
|
||||
import { CommandType, DEFAULT_STYLES, EDITOR_ACTIVATED, ICommandService, IContextService, IUniverInstanceService, ThemeService, UniverInstanceType } from '@univerjs/core';
|
||||
import {
|
||||
SetInlineFormatBoldCommand,
|
||||
SetInlineFormatFontFamilyCommand,
|
||||
@@ -35,7 +35,9 @@ import {
|
||||
SetStrikeThroughCommand,
|
||||
SetTextColorCommand,
|
||||
SetUnderlineCommand,
|
||||
SheetsSelectionsService,
|
||||
} from '@univerjs/sheets';
|
||||
import { getFontStyleAtCursor } from '../../controllers/menu/utils';
|
||||
|
||||
/**
|
||||
* It is used to set the bold style of selections or one cell, need to distinguish between
|
||||
@@ -155,6 +157,90 @@ export const SetRangeFontSizeCommand: ICommand = {
|
||||
},
|
||||
};
|
||||
|
||||
export const SetRangeFontIncreaseCommand: ICommand = {
|
||||
type: CommandType.COMMAND,
|
||||
id: 'sheet.command.set-range-font-increase',
|
||||
handler: async (accessor) => {
|
||||
const univerInstanceService = accessor.get(IUniverInstanceService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const contextService = accessor.get(IContextService);
|
||||
const isCellEditorFocus = contextService.getContextValue(EDITOR_ACTIVATED);
|
||||
const selectionManagerService = accessor.get(SheetsSelectionsService);
|
||||
|
||||
const defaultValue = DEFAULT_STYLES.fs;
|
||||
|
||||
const workbook = univerInstanceService.getCurrentUnitOfType<Workbook>(UniverInstanceType.UNIVER_SHEET)!;
|
||||
const worksheet = workbook.getActiveSheet();
|
||||
const primary = selectionManagerService.getCurrentLastSelection()?.primary;
|
||||
|
||||
const params = {
|
||||
value: defaultValue,
|
||||
};
|
||||
|
||||
if (isCellEditorFocus) {
|
||||
const textRun = getFontStyleAtCursor(accessor);
|
||||
if (textRun != null) {
|
||||
const value = textRun.ts?.fs ?? defaultValue;
|
||||
|
||||
params.value = value >= 400 ? 400 : value + 1;
|
||||
}
|
||||
|
||||
return commandService.executeCommand(SetInlineFormatFontSizeCommand.id, params);
|
||||
}
|
||||
|
||||
if (primary != null) {
|
||||
const style = worksheet.getComposedCellStyle(primary.startRow, primary.startColumn);
|
||||
const value = style.fs ?? defaultValue;
|
||||
params.value = value >= 400 ? 400 : value + 1;
|
||||
return commandService.executeCommand(SetFontSizeCommand.id, params);
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
export const SetRangeFontDecreaseCommand: ICommand = {
|
||||
type: CommandType.COMMAND,
|
||||
id: 'sheet.command.set-range-font-decrease',
|
||||
handler: async (accessor) => {
|
||||
const univerInstanceService = accessor.get(IUniverInstanceService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const contextService = accessor.get(IContextService);
|
||||
const isCellEditorFocus = contextService.getContextValue(EDITOR_ACTIVATED);
|
||||
const selectionManagerService = accessor.get(SheetsSelectionsService);
|
||||
|
||||
const defaultValue = DEFAULT_STYLES.fs;
|
||||
|
||||
const workbook = univerInstanceService.getCurrentUnitOfType<Workbook>(UniverInstanceType.UNIVER_SHEET)!;
|
||||
const worksheet = workbook.getActiveSheet();
|
||||
const primary = selectionManagerService.getCurrentLastSelection()?.primary;
|
||||
|
||||
const params = {
|
||||
value: defaultValue,
|
||||
};
|
||||
|
||||
if (isCellEditorFocus) {
|
||||
const textRun = getFontStyleAtCursor(accessor);
|
||||
if (textRun != null) {
|
||||
const value = textRun.ts?.fs ?? defaultValue;
|
||||
|
||||
params.value = value <= 6 ? 6 : value - 1;
|
||||
}
|
||||
|
||||
return commandService.executeCommand(SetInlineFormatFontSizeCommand.id, params);
|
||||
}
|
||||
|
||||
if (primary != null) {
|
||||
const style = worksheet.getComposedCellStyle(primary.startRow, primary.startColumn);
|
||||
const value = style.fs ?? defaultValue;
|
||||
params.value = value <= 6 ? 6 : value - 1;
|
||||
return commandService.executeCommand(SetFontSizeCommand.id, params);
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
};
|
||||
|
||||
export const SetRangeFontFamilyCommand: ICommand = {
|
||||
type: CommandType.COMMAND,
|
||||
id: 'sheet.command.set-range-font-family',
|
||||
|
||||
@@ -64,7 +64,9 @@ import { DeleteRangeMoveUpConfirmCommand } from '../commands/commands/delete-ran
|
||||
import { HideColConfirmCommand, HideRowConfirmCommand } from '../commands/commands/hide-row-col-confirm.command';
|
||||
import {
|
||||
SetRangeBoldCommand,
|
||||
SetRangeFontDecreaseCommand,
|
||||
SetRangeFontFamilyCommand,
|
||||
SetRangeFontIncreaseCommand,
|
||||
SetRangeFontSizeCommand,
|
||||
SetRangeItalicCommand,
|
||||
SetRangeStrickThroughCommand,
|
||||
@@ -96,6 +98,7 @@ import { RenameSheetOperation } from '../commands/operations/rename-sheet.operat
|
||||
import { CellBorderSelectorMenuItemFactory } from './menu/border.menu';
|
||||
import { CLEAR_SELECTION_MENU_ID, ClearSelectionAllMenuItemFactory, ClearSelectionContentMenuItemFactory, ClearSelectionFormatMenuItemFactory, ClearSelectionMenuItemFactory } from './menu/clear.menu';
|
||||
import { DELETE_RANGE_MENU_ID, DeleteRangeMenuItemFactory, DeleteRangeMoveLeftMenuItemFactory, DeleteRangeMoveUpMenuItemFactory, RemoveColMenuItemFactory, RemoveRowMenuItemFactory } from './menu/delete.menu';
|
||||
import { FontSizeDecreaseMenuItemFactory, FontSizeIncreaseMenuItemFactory, FontSizeSelectorMenuItemFactory } from './menu/font.menu';
|
||||
import { ToggleGridlinesMenuFactory } from './menu/gridlines.menu';
|
||||
import {
|
||||
CELL_INSERT_MENU_ID,
|
||||
@@ -118,7 +121,6 @@ import {
|
||||
// CutMenuItemFactory,
|
||||
FitContentMenuItemFactory,
|
||||
FontFamilySelectorMenuItemFactory,
|
||||
FontSizeSelectorMenuItemFactory,
|
||||
FormatPainterMenuItemFactory,
|
||||
FrozenColMenuItemFactory,
|
||||
FrozenMenuItemFactory,
|
||||
@@ -196,8 +198,14 @@ export const menuSchema: MenuSchemaType = {
|
||||
order: 2,
|
||||
menuItemFactory: FontSizeSelectorMenuItemFactory,
|
||||
},
|
||||
// TODO: fontsize +
|
||||
// TODO: fontsize -
|
||||
[SetRangeFontIncreaseCommand.id]: {
|
||||
order: 2.1,
|
||||
menuItemFactory: FontSizeIncreaseMenuItemFactory,
|
||||
},
|
||||
[SetRangeFontDecreaseCommand.id]: {
|
||||
order: 2.2,
|
||||
menuItemFactory: FontSizeDecreaseMenuItemFactory,
|
||||
},
|
||||
[SetRangeBoldCommand.id]: {
|
||||
order: 5,
|
||||
menuItemFactory: BoldMenuItemFactory,
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* 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 type { IAccessor } from '@univerjs/core';
|
||||
import type { IMenuButtonItem, IMenuSelectorItem } from '@univerjs/ui';
|
||||
import {
|
||||
DEFAULT_STYLES,
|
||||
EDITOR_ACTIVATED,
|
||||
FOCUSING_SHEET,
|
||||
ICommandService,
|
||||
IContextService,
|
||||
IUniverInstanceService,
|
||||
UniverInstanceType,
|
||||
} from '@univerjs/core';
|
||||
import { SetTextSelectionsOperation } from '@univerjs/docs';
|
||||
import { SetInlineFormatCommand } from '@univerjs/docs-ui';
|
||||
import {
|
||||
RangeProtectionPermissionEditPoint,
|
||||
SetRangeValuesMutation,
|
||||
SetSelectionsOperation,
|
||||
SetWorksheetActiveOperation,
|
||||
SheetsSelectionsService,
|
||||
WorkbookEditablePermission,
|
||||
WorksheetEditPermission,
|
||||
WorksheetSetCellStylePermission,
|
||||
} from '@univerjs/sheets';
|
||||
import { FONT_SIZE_COMPONENT, FONT_SIZE_LIST, getMenuHiddenObservable, MenuItemType } from '@univerjs/ui';
|
||||
import { Observable } from 'rxjs';
|
||||
import {
|
||||
SetRangeFontDecreaseCommand,
|
||||
SetRangeFontIncreaseCommand,
|
||||
SetRangeFontSizeCommand,
|
||||
} from '../../commands/commands/inline-format.command';
|
||||
import { deriveStateFromActiveSheet$, getCurrentRangeDisable$ } from './menu-util';
|
||||
import { getFontStyleAtCursor } from './utils';
|
||||
|
||||
function updateFontSizeValue(accessor: IAccessor, defaultValue: number) {
|
||||
const selectionManagerService = accessor.get(SheetsSelectionsService);
|
||||
const univerInstanceService = accessor.get(IUniverInstanceService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const contextService = accessor.get(IContextService);
|
||||
|
||||
return deriveStateFromActiveSheet$(univerInstanceService, defaultValue, ({ worksheet }) => new Observable((subscriber) => {
|
||||
const updateSheet = () => {
|
||||
let fs = defaultValue;
|
||||
const primary = selectionManagerService.getCurrentLastSelection()?.primary;
|
||||
if (primary != null) {
|
||||
const style = worksheet.getComposedCellStyle(primary.startRow, primary.startColumn);
|
||||
if (style.fs) {
|
||||
fs = style.fs;
|
||||
}
|
||||
}
|
||||
|
||||
subscriber.next(fs);
|
||||
};
|
||||
|
||||
const updateSheetEditor = () => {
|
||||
const textRun = getFontStyleAtCursor(accessor);
|
||||
if (textRun != null) {
|
||||
const fs = (textRun.ts?.fs ?? defaultValue);
|
||||
|
||||
subscriber.next(fs);
|
||||
}
|
||||
};
|
||||
|
||||
const disposable = commandService.onCommandExecuted((c) => {
|
||||
const id = c.id;
|
||||
if (id === SetRangeValuesMutation.id || id === SetSelectionsOperation.id || id === SetWorksheetActiveOperation.id) {
|
||||
updateSheet();
|
||||
}
|
||||
|
||||
if (
|
||||
(id === SetTextSelectionsOperation.id || id === SetInlineFormatCommand.id) &&
|
||||
contextService.getContextValue(EDITOR_ACTIVATED) &&
|
||||
contextService.getContextValue(FOCUSING_SHEET)
|
||||
) {
|
||||
updateSheetEditor();
|
||||
}
|
||||
});
|
||||
|
||||
updateSheet();
|
||||
return disposable.dispose;
|
||||
}));
|
||||
}
|
||||
|
||||
export function FontSizeSelectorMenuItemFactory(accessor: IAccessor): IMenuSelectorItem<number> {
|
||||
const defaultValue = DEFAULT_STYLES.fs;
|
||||
const disabled$ = getCurrentRangeDisable$(accessor, {
|
||||
workbookTypes: [WorkbookEditablePermission],
|
||||
worksheetTypes: [WorksheetEditPermission, WorksheetSetCellStylePermission],
|
||||
rangeTypes: [RangeProtectionPermissionEditPoint],
|
||||
}, true);
|
||||
|
||||
return {
|
||||
id: SetRangeFontSizeCommand.id,
|
||||
type: MenuItemType.SELECTOR,
|
||||
tooltip: 'toolbar.fontSize',
|
||||
label: {
|
||||
name: FONT_SIZE_COMPONENT,
|
||||
props: {
|
||||
min: 6,
|
||||
max: 400,
|
||||
disabled$,
|
||||
},
|
||||
},
|
||||
selections: FONT_SIZE_LIST,
|
||||
disabled$,
|
||||
value$: updateFontSizeValue(accessor, defaultValue),
|
||||
hidden$: getMenuHiddenObservable(accessor, UniverInstanceType.UNIVER_SHEET),
|
||||
};
|
||||
}
|
||||
|
||||
export function FontSizeIncreaseMenuItemFactory(accessor: IAccessor): IMenuButtonItem {
|
||||
const disabled$ = getCurrentRangeDisable$(accessor, {
|
||||
workbookTypes: [WorkbookEditablePermission],
|
||||
worksheetTypes: [WorksheetEditPermission, WorksheetSetCellStylePermission],
|
||||
rangeTypes: [RangeProtectionPermissionEditPoint],
|
||||
}, true);
|
||||
|
||||
return {
|
||||
id: SetRangeFontIncreaseCommand.id,
|
||||
type: MenuItemType.BUTTON,
|
||||
icon: 'FontSizeIncreaseIcon',
|
||||
tooltip: 'toolbar.fontSizeIncrease',
|
||||
disabled$,
|
||||
hidden$: getMenuHiddenObservable(accessor, UniverInstanceType.UNIVER_SHEET),
|
||||
};
|
||||
}
|
||||
|
||||
export function FontSizeDecreaseMenuItemFactory(accessor: IAccessor) {
|
||||
const disabled$ = getCurrentRangeDisable$(accessor, {
|
||||
workbookTypes: [WorkbookEditablePermission],
|
||||
worksheetTypes: [WorksheetEditPermission, WorksheetSetCellStylePermission],
|
||||
rangeTypes: [RangeProtectionPermissionEditPoint],
|
||||
}, true);
|
||||
|
||||
return {
|
||||
id: SetRangeFontDecreaseCommand.id,
|
||||
type: MenuItemType.BUTTON,
|
||||
icon: 'FontSizeReduceIcon',
|
||||
tooltip: 'toolbar.fontSizeDecrease',
|
||||
disabled$,
|
||||
hidden$: getMenuHiddenObservable(accessor, UniverInstanceType.UNIVER_SHEET),
|
||||
};
|
||||
}
|
||||
@@ -14,13 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { DocumentDataModel, IAccessor, IColorStyle, Nullable, Workbook } from '@univerjs/core';
|
||||
import type { IAccessor, IColorStyle, Nullable, Workbook } from '@univerjs/core';
|
||||
import type { IMenuButtonItem, IMenuSelectorItem } from '@univerjs/ui';
|
||||
import {
|
||||
BooleanNumber,
|
||||
composeStyles,
|
||||
DEFAULT_STYLES,
|
||||
DOCS_NORMAL_EDITOR_UNIT_ID_KEY,
|
||||
EDITOR_ACTIVATED,
|
||||
FOCUSING_SHEET,
|
||||
FontItalic,
|
||||
@@ -35,7 +34,7 @@ import {
|
||||
VerticalAlign,
|
||||
WrapStrategy,
|
||||
} from '@univerjs/core';
|
||||
import { DocSelectionManagerService, SetTextSelectionsOperation } from '@univerjs/docs';
|
||||
import { SetTextSelectionsOperation } from '@univerjs/docs';
|
||||
import { SetInlineFormatCommand } from '@univerjs/docs-ui';
|
||||
import {
|
||||
CancelFrozenCommand,
|
||||
@@ -77,8 +76,6 @@ import {
|
||||
FONT_FAMILY_COMPONENT,
|
||||
FONT_FAMILY_ITEM_COMPONENT,
|
||||
FONT_FAMILY_LIST,
|
||||
FONT_SIZE_COMPONENT,
|
||||
FONT_SIZE_LIST,
|
||||
getMenuHiddenObservable,
|
||||
IClipboardInterfaceService,
|
||||
MenuItemType,
|
||||
@@ -98,7 +95,6 @@ import {
|
||||
ResetRangeTextColorCommand,
|
||||
SetRangeBoldCommand,
|
||||
SetRangeFontFamilyCommand,
|
||||
SetRangeFontSizeCommand,
|
||||
SetRangeItalicCommand,
|
||||
SetRangeStrickThroughCommand,
|
||||
SetRangeTextColorCommand,
|
||||
@@ -110,6 +106,7 @@ import { SetWorksheetColAutoWidthCommand } from '../../commands/commands/set-wor
|
||||
import { MENU_ITEM_INPUT_COMPONENT } from '../../components/menu-item-input';
|
||||
import { FormatPainterStatus, IFormatPainterService } from '../../services/format-painter/format-painter.service';
|
||||
import { deriveStateFromActiveSheet$, getCurrentRangeDisable$, getObservableWithExclusiveRange$ } from './menu-util';
|
||||
import { getFontStyleAtCursor } from './utils';
|
||||
|
||||
export enum SheetMenuPosition {
|
||||
ROW_HEADER_CONTEXT_MENU = 'ROW_HEADER_CONTEXT_MENU',
|
||||
@@ -448,76 +445,6 @@ export function FontFamilySelectorMenuItemFactory(accessor: IAccessor): IMenuSel
|
||||
};
|
||||
}
|
||||
|
||||
export function FontSizeSelectorMenuItemFactory(accessor: IAccessor): IMenuSelectorItem<number> {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const univerInstanceService = accessor.get(IUniverInstanceService);
|
||||
const selectionManagerService = accessor.get(SheetsSelectionsService);
|
||||
const contextService = accessor.get(IContextService);
|
||||
|
||||
const defaultValue = DEFAULT_STYLES.fs;
|
||||
const disabled$ = getCurrentRangeDisable$(accessor, {
|
||||
workbookTypes: [WorkbookEditablePermission],
|
||||
worksheetTypes: [WorksheetEditPermission, WorksheetSetCellStylePermission],
|
||||
rangeTypes: [RangeProtectionPermissionEditPoint],
|
||||
}, true);
|
||||
|
||||
return {
|
||||
id: SetRangeFontSizeCommand.id,
|
||||
type: MenuItemType.SELECTOR,
|
||||
tooltip: 'toolbar.fontSize',
|
||||
label: {
|
||||
name: FONT_SIZE_COMPONENT,
|
||||
props: {
|
||||
min: 1,
|
||||
max: 400,
|
||||
disabled$,
|
||||
},
|
||||
},
|
||||
selections: FONT_SIZE_LIST,
|
||||
disabled$,
|
||||
value$: deriveStateFromActiveSheet$(univerInstanceService, defaultValue, ({ worksheet }) => new Observable((subscriber) => {
|
||||
const updateSheet = () => {
|
||||
let fs = defaultValue;
|
||||
const primary = selectionManagerService.getCurrentLastSelection()?.primary;
|
||||
if (primary != null) {
|
||||
const style = worksheet.getComposedCellStyle(primary.startRow, primary.startColumn);
|
||||
if (style.fs) {
|
||||
fs = style.fs;
|
||||
}
|
||||
}
|
||||
subscriber.next(fs);
|
||||
};
|
||||
|
||||
const updateSheetEditor = () => {
|
||||
const textRun = getFontStyleAtCursor(accessor);
|
||||
if (textRun != null) {
|
||||
const fs = textRun.ts?.fs ?? defaultValue;
|
||||
subscriber.next(fs);
|
||||
}
|
||||
};
|
||||
|
||||
const disposable = commandService.onCommandExecuted((c) => {
|
||||
const id = c.id;
|
||||
if (id === SetRangeValuesMutation.id || id === SetSelectionsOperation.id || id === SetWorksheetActiveOperation.id) {
|
||||
updateSheet();
|
||||
}
|
||||
|
||||
if (
|
||||
(id === SetTextSelectionsOperation.id || id === SetInlineFormatCommand.id) &&
|
||||
contextService.getContextValue(EDITOR_ACTIVATED) &&
|
||||
contextService.getContextValue(FOCUSING_SHEET)
|
||||
) {
|
||||
updateSheetEditor();
|
||||
}
|
||||
});
|
||||
|
||||
updateSheet();
|
||||
return disposable.dispose;
|
||||
})),
|
||||
hidden$: getMenuHiddenObservable(accessor, UniverInstanceType.UNIVER_SHEET),
|
||||
};
|
||||
}
|
||||
|
||||
export function ResetTextColorMenuItemFactory(accessor: IAccessor): IMenuButtonItem {
|
||||
return {
|
||||
id: ResetRangeTextColorCommand.id,
|
||||
@@ -1394,20 +1321,3 @@ export function SetColWidthMenuItemFactory(accessor: IAccessor): IMenuButtonItem
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
function getFontStyleAtCursor(accessor: IAccessor) {
|
||||
const univerInstanceService = accessor.get(IUniverInstanceService);
|
||||
const textSelectionService = accessor.get(DocSelectionManagerService);
|
||||
|
||||
const editorDataModel = univerInstanceService.getUnit<DocumentDataModel>(DOCS_NORMAL_EDITOR_UNIT_ID_KEY);
|
||||
const activeTextRange = textSelectionService.getActiveTextRange();
|
||||
|
||||
if (editorDataModel == null || activeTextRange == null) return null;
|
||||
|
||||
const textRuns = editorDataModel.getBody()?.textRuns;
|
||||
if (textRuns == null) return;
|
||||
|
||||
const { startOffset } = activeTextRange;
|
||||
const textRun = textRuns.find(({ st, ed }) => startOffset >= st && startOffset <= ed);
|
||||
return textRun;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 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 type { DocumentDataModel, IAccessor } from '@univerjs/core';
|
||||
import { DOCS_NORMAL_EDITOR_UNIT_ID_KEY, IUniverInstanceService } from '@univerjs/core';
|
||||
import { DocSelectionManagerService } from '@univerjs/docs';
|
||||
|
||||
export function getFontStyleAtCursor(accessor: IAccessor) {
|
||||
const univerInstanceService = accessor.get(IUniverInstanceService);
|
||||
const textSelectionService = accessor.get(DocSelectionManagerService);
|
||||
|
||||
const editorDataModel = univerInstanceService.getUnit<DocumentDataModel>(DOCS_NORMAL_EDITOR_UNIT_ID_KEY);
|
||||
const activeTextRange = textSelectionService.getActiveTextRange();
|
||||
|
||||
if (editorDataModel == null || activeTextRange == null) return null;
|
||||
|
||||
const textRuns = editorDataModel.getBody()?.textRuns;
|
||||
if (textRuns == null) return;
|
||||
|
||||
const { startOffset } = activeTextRange;
|
||||
const textRun = textRuns.find(({ st, ed }) => startOffset >= st && startOffset <= ed);
|
||||
return textRun;
|
||||
}
|
||||
@@ -41,7 +41,9 @@ import { HideColConfirmCommand, HideRowConfirmCommand } from '../commands/comman
|
||||
import {
|
||||
ResetRangeTextColorCommand,
|
||||
SetRangeBoldCommand,
|
||||
SetRangeFontDecreaseCommand,
|
||||
SetRangeFontFamilyCommand,
|
||||
SetRangeFontIncreaseCommand,
|
||||
SetRangeFontSizeCommand,
|
||||
SetRangeItalicCommand,
|
||||
SetRangeStrickThroughCommand,
|
||||
@@ -192,6 +194,7 @@ export class SheetUIController extends Disposable {
|
||||
this.disposeWithMe(componentManager.register('HideGridlinesDoubleIcon', HideGridlinesDoubleIcon));
|
||||
}
|
||||
|
||||
// eslint-disable-next-line max-lines-per-function
|
||||
private _initCommands(): void {
|
||||
[
|
||||
AddWorksheetMergeAllCommand,
|
||||
@@ -223,6 +226,8 @@ export class SheetUIController extends Disposable {
|
||||
SetRangeSubscriptCommand,
|
||||
SetRangeSuperscriptCommand,
|
||||
SetRangeFontSizeCommand,
|
||||
SetRangeFontIncreaseCommand,
|
||||
SetRangeFontDecreaseCommand,
|
||||
SetRangeFontFamilyCommand,
|
||||
SetRangeTextColorCommand,
|
||||
ResetRangeTextColorCommand,
|
||||
|
||||
@@ -37,7 +37,9 @@ export { HideColConfirmCommand, HideRowConfirmCommand } from './commands/command
|
||||
export {
|
||||
ResetRangeTextColorCommand,
|
||||
SetRangeBoldCommand,
|
||||
SetRangeFontDecreaseCommand,
|
||||
SetRangeFontFamilyCommand,
|
||||
SetRangeFontIncreaseCommand,
|
||||
SetRangeFontSizeCommand,
|
||||
SetRangeItalicCommand,
|
||||
SetRangeStrickThroughCommand,
|
||||
|
||||
@@ -26,6 +26,8 @@ const locale: typeof enUS = {
|
||||
formatPainter: 'Copiar format',
|
||||
font: 'Tipus de lletra',
|
||||
fontSize: 'Mida de la lletra',
|
||||
fontSizeIncrease: 'Augmentar la mida de la lletra',
|
||||
fontSizeDecrease: 'Disminuir la mida de la lletra',
|
||||
bold: 'Negreta',
|
||||
italic: 'Cursiva',
|
||||
strikethrough: 'Ratllat',
|
||||
|
||||
@@ -24,6 +24,8 @@ const locale = {
|
||||
formatPainter: 'Paint format',
|
||||
font: 'Font',
|
||||
fontSize: 'Font size',
|
||||
fontSizeIncrease: 'Increase font size',
|
||||
fontSizeDecrease: 'Decrease font size',
|
||||
bold: 'Bold',
|
||||
italic: 'Italic',
|
||||
strikethrough: 'Strikethrough',
|
||||
|
||||
@@ -26,6 +26,8 @@ const locale: typeof enUS = {
|
||||
formatPainter: 'Copiar formato',
|
||||
font: 'Fuente',
|
||||
fontSize: 'Tamaño de fuente',
|
||||
fontSizeIncrease: 'Aumentar tamaño de fuente',
|
||||
fontSizeDecrease: 'Disminuir tamaño de fuente',
|
||||
bold: 'Negrita',
|
||||
italic: 'Cursiva',
|
||||
strikethrough: 'Tachado',
|
||||
|
||||
@@ -26,6 +26,8 @@ const locale: typeof enUS = {
|
||||
formatPainter: 'کپی قالب',
|
||||
font: 'فونت',
|
||||
fontSize: 'اندازه فونت',
|
||||
fontSizeIncrease: 'افزایش اندازه فونت',
|
||||
fontSizeDecrease: 'کاهش اندازه فونت',
|
||||
bold: 'پررنگ',
|
||||
italic: 'ایتالیک',
|
||||
strikethrough: 'خطدار',
|
||||
|
||||
@@ -26,6 +26,8 @@ const locale: typeof enUS = {
|
||||
formatPainter: 'Reproduire la mise en forme',
|
||||
font: 'Police',
|
||||
fontSize: 'Taille de police',
|
||||
fontSizeIncrease: 'Augmenter la taille de la police',
|
||||
fontSizeDecrease: 'Diminuer la taille de la police',
|
||||
bold: 'Gras',
|
||||
italic: 'Italique',
|
||||
strikethrough: 'Barré',
|
||||
|
||||
@@ -26,6 +26,8 @@ const locale: typeof enUS = {
|
||||
formatPainter: '서식 페인트',
|
||||
font: '글꼴',
|
||||
fontSize: '글꼴 크기',
|
||||
fontSizeIncrease: '글꼴 크기 증가',
|
||||
fontSizeDecrease: '글꼴 크기 감소',
|
||||
bold: '굵게',
|
||||
italic: '기울임',
|
||||
strikethrough: '취소선',
|
||||
|
||||
@@ -26,6 +26,8 @@ const locale: typeof enUS = {
|
||||
formatPainter: 'Копировать формат',
|
||||
font: 'Шрифт',
|
||||
fontSize: 'Размер шрифта',
|
||||
fontSizeIncrease: 'Увеличить размер шрифта',
|
||||
fontSizeDecrease: 'Уменьшить размер шрифта',
|
||||
bold: 'Жирный',
|
||||
italic: 'Курсив',
|
||||
strikethrough: 'Зачеркнутый',
|
||||
|
||||
@@ -26,6 +26,8 @@ const locale: typeof enUS = {
|
||||
formatPainter: 'Chổi định dạng',
|
||||
font: 'Phông chữ',
|
||||
fontSize: 'Cỡ chữ',
|
||||
fontSizeIncrease: 'Tăng cỡ chữ',
|
||||
fontSizeDecrease: 'Giảm cỡ chữ',
|
||||
bold: 'In đậm',
|
||||
italic: 'In nghiêng',
|
||||
strikethrough: 'Gạch ngang',
|
||||
|
||||
@@ -27,6 +27,8 @@ const locale: typeof enUS = {
|
||||
formatPainter: '格式刷',
|
||||
font: '字体',
|
||||
fontSize: '字号',
|
||||
fontSizeIncrease: '增大字号',
|
||||
fontSizeDecrease: '减小字号',
|
||||
bold: '粗体',
|
||||
italic: '斜体',
|
||||
strikethrough: '删除线',
|
||||
|
||||
@@ -27,6 +27,8 @@ const locale: typeof enUS = {
|
||||
formatPainter: '格式刷',
|
||||
font: '字體',
|
||||
fontSize: '字號',
|
||||
fontSizeIncrease: '增大字號',
|
||||
fontSizeDecrease: '減小字號',
|
||||
bold: '粗體',
|
||||
italic: '斜體',
|
||||
strikethrough: '刪除線',
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import { createIdentifier } from '@univerjs/core';
|
||||
|
||||
export type RibbonType = 'default' | 'simple';
|
||||
export type RibbonType = 'default' | 'simple' | 'classic';
|
||||
|
||||
export interface IWorkbenchOptions {
|
||||
container?: string | HTMLElement;
|
||||
|
||||
@@ -61,7 +61,7 @@ interface IMenuItemBase<V> {
|
||||
|
||||
hidden$?: Observable<boolean>;
|
||||
disabled$?: Observable<boolean>;
|
||||
params?: any;
|
||||
params?: any | Function;
|
||||
/** On observable value that should emit the value of the corresponding selection component. */
|
||||
value$?: Observable<V>;
|
||||
}
|
||||
|
||||
@@ -18,15 +18,17 @@ import type { ComponentType } from 'react';
|
||||
import type { Observable } from 'rxjs';
|
||||
import type { RibbonType } from '../../../controllers/ui/ui.controller';
|
||||
import type { IMenuSchema } from '../../../services/menu/menu-manager.service';
|
||||
import { IUniverInstanceService, LocaleService, throttle } from '@univerjs/core';
|
||||
import { borderBottomClassName, borderClassName, clsx, divideXClassName, Dropdown, HoverCard } from '@univerjs/design';
|
||||
import { DatabaseIcon, EyeIcon, FunctionIcon, HomeIcon, InsertIcon, MoreDownIcon, MoreFunctionIcon } from '@univerjs/icons';
|
||||
import { IUniverInstanceService, throttle } from '@univerjs/core';
|
||||
import { borderBottomClassName, clsx, divideXClassName, Dropdown } from '@univerjs/design';
|
||||
import { MoreFunctionIcon } from '@univerjs/icons';
|
||||
import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { combineLatest } from 'rxjs';
|
||||
import { IMenuManagerService } from '../../../services/menu/menu-manager.service';
|
||||
import { MenuManagerPosition, RibbonPosition } from '../../../services/menu/types';
|
||||
import { useDependency, useObservable } from '../../../utils/di';
|
||||
import { ComponentContainer } from '../ComponentContainer';
|
||||
import { ClassicMenu } from './ribbon-menu/ClassicMenu';
|
||||
import { DefaultMenu } from './ribbon-menu/DefaultMenu';
|
||||
import { toolbarButtonClassName } from './ToolbarButton';
|
||||
import { ToolbarItem } from './ToolbarItem';
|
||||
|
||||
@@ -36,21 +38,12 @@ interface IRibbonProps {
|
||||
headerMenu?: boolean;
|
||||
}
|
||||
|
||||
const iconMap = {
|
||||
[RibbonPosition.START]: HomeIcon,
|
||||
[RibbonPosition.INSERT]: InsertIcon,
|
||||
[RibbonPosition.FORMULAS]: FunctionIcon,
|
||||
[RibbonPosition.DATA]: DatabaseIcon,
|
||||
[RibbonPosition.VIEW]: EyeIcon,
|
||||
[RibbonPosition.OTHERS]: MoreFunctionIcon,
|
||||
};
|
||||
|
||||
export function Ribbon(props: IRibbonProps) {
|
||||
const { ribbonType, headerMenuComponents, headerMenu = true } = props;
|
||||
|
||||
const menuManagerService = useDependency(IMenuManagerService);
|
||||
const univerInstanceService = useDependency(IUniverInstanceService);
|
||||
const localeService = useDependency(LocaleService);
|
||||
|
||||
const [menuChangedTimes, setMenuChangedTimes] = useState(0);
|
||||
|
||||
const focusedUnit = useObservable(univerInstanceService.focused$);
|
||||
@@ -76,14 +69,12 @@ export function Ribbon(props: IRibbonProps) {
|
||||
|
||||
const [ribbon, setRibbon] = useState<IMenuSchema[]>([]);
|
||||
const [activatedTab, setActivatedTab] = useState<string>(RibbonPosition.START);
|
||||
const [groupSelectorVisible, setGroupSelectorVisible] = useState(false);
|
||||
const [collapsedIds, setCollapsedIds] = useState<string[]>([]);
|
||||
const [fakeToolbarVisible, setFakeToolbarVisible] = useState(false);
|
||||
|
||||
const handleSelectTab = useCallback((group: IMenuSchema) => {
|
||||
toolbarItemRefs.current = {};
|
||||
setActivatedTab(group.key);
|
||||
setGroupSelectorVisible(false);
|
||||
}, []);
|
||||
|
||||
// process menu changes
|
||||
@@ -287,7 +278,7 @@ export function Ribbon(props: IRibbonProps) {
|
||||
return (
|
||||
<>
|
||||
{headerMenu && (headerMenuComponents && headerMenuComponents.size > 0) && (
|
||||
<header className={clsx('univer-relative univer-h-11 univer-select-none', borderBottomClassName)}>
|
||||
<header className={clsx('univer-relative univer-h-10 univer-select-none', borderBottomClassName)}>
|
||||
<div
|
||||
className={`
|
||||
univer-absolute univer-right-2 univer-top-0 univer-flex univer-h-full univer-items-center
|
||||
@@ -302,97 +293,37 @@ export function Ribbon(props: IRibbonProps) {
|
||||
</header>
|
||||
)}
|
||||
|
||||
{ribbonType === 'classic' && ribbon.length > 1 && (
|
||||
<ClassicMenu
|
||||
ribbon={ribbon}
|
||||
activatedTab={activatedTab}
|
||||
onSelectTab={handleSelectTab}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div
|
||||
className={clsx(`
|
||||
univer-box-border univer-grid univer-h-10 univer-grid-flow-col univer-items-center univer-px-3
|
||||
`, {
|
||||
'univer-grid-cols-[auto,1fr]': ribbon.length > 1,
|
||||
'univer-grid-cols-[1fr] univer-justify-center': ribbonType === 'classic',
|
||||
'univer-grid-cols-[auto,1fr]': ribbon.length > 1 && ribbonType !== 'classic',
|
||||
'univer-grid-cols-none': ribbon.length === 1,
|
||||
}, borderBottomClassName)}
|
||||
>
|
||||
{/* <search className="univer-mr-1 univer-w-20">
|
||||
<Input />
|
||||
</search> */}
|
||||
|
||||
{ribbon.length > 1 && (
|
||||
<HoverCard
|
||||
className="univer-max-w-96 !univer-rounded-xl"
|
||||
align="start"
|
||||
open={groupSelectorVisible}
|
||||
overlay={(
|
||||
<div className="univer-grid univer-gap-1 univer-px-2 univer-py-1">
|
||||
{ribbon.map((group) => {
|
||||
const Icon = iconMap[group.key as RibbonPosition];
|
||||
|
||||
return (
|
||||
<a
|
||||
key={group.key}
|
||||
data-u-comp="ribbon-group-btn"
|
||||
className={`
|
||||
univer-box-border univer-flex univer-cursor-pointer univer-items-center
|
||||
univer-gap-2.5 univer-rounded-lg univer-px-2 univer-py-1.5
|
||||
hover:univer-bg-gray-100
|
||||
dark:hover:!univer-bg-gray-700
|
||||
`}
|
||||
onClick={() => handleSelectTab(group)}
|
||||
>
|
||||
<span
|
||||
className={clsx(`
|
||||
univer-box-border univer-flex univer-size-9 univer-flex-shrink-0
|
||||
univer-items-center univer-justify-center univer-rounded-lg
|
||||
`, borderClassName)}
|
||||
>
|
||||
<Icon
|
||||
className={`
|
||||
univer-text-gray-500
|
||||
dark:!univer-text-gray-300
|
||||
`}
|
||||
/>
|
||||
</span>
|
||||
<span className="univer-flex univer-flex-col">
|
||||
<strong
|
||||
className={`
|
||||
univer-text-sm univer-font-semibold univer-text-gray-800
|
||||
dark:!univer-text-gray-200
|
||||
`}
|
||||
>
|
||||
{localeService.t(group.key)}
|
||||
</strong>
|
||||
<span className="univer-text-xs univer-text-gray-400">
|
||||
{localeService.t(`${group.key}Desc`)}
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
onOpenChange={setGroupSelectorVisible}
|
||||
>
|
||||
<a
|
||||
className={`
|
||||
univer-mr-2 univer-flex univer-h-7 univer-cursor-pointer univer-items-center
|
||||
univer-gap-1.5 univer-whitespace-nowrap !univer-rounded-full univer-bg-gray-700
|
||||
univer-pl-3 univer-pr-2 univer-text-sm univer-text-white
|
||||
dark:!univer-bg-gray-200 dark:!univer-text-gray-800
|
||||
`}
|
||||
onClick={() => setGroupSelectorVisible(true)}
|
||||
>
|
||||
{localeService.t(activatedTab)}
|
||||
<MoreDownIcon
|
||||
className={`
|
||||
univer-text-gray-200
|
||||
dark:!univer-text-gray-500
|
||||
`}
|
||||
/>
|
||||
</a>
|
||||
</HoverCard>
|
||||
{ribbonType === 'default' && ribbon.length > 1 && (
|
||||
<DefaultMenu
|
||||
ribbon={ribbon}
|
||||
activatedTab={activatedTab}
|
||||
onSelectTab={handleSelectTab}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div
|
||||
data-u-comp="ribbon-toolbar"
|
||||
ref={containerRef}
|
||||
className={clsx('univer-flex univer-overflow-hidden', divideXClassName)}
|
||||
className={clsx('univer-flex univer-overflow-hidden', divideXClassName, {
|
||||
'univer-justify-center': ribbonType === 'classic',
|
||||
})}
|
||||
>
|
||||
{activeGroup.visibleGroups.map((groupItem) => (groupItem.children?.length || groupItem.item) && (
|
||||
<Fragment key={groupItem.key}>
|
||||
|
||||
@@ -213,6 +213,8 @@ export const ToolbarItem = forwardRef<ITooltipWrapperRef, IDisplayMenuItem<IMenu
|
||||
function renderButtonType() {
|
||||
const isCustomComponent = componentManager.get(typeof label === 'string' ? label : label?.name ?? '');
|
||||
|
||||
const commandValue = value ?? typeof params === 'function' ? params() : params;
|
||||
|
||||
return (
|
||||
<ToolbarButton
|
||||
data-u-command={id}
|
||||
@@ -220,7 +222,7 @@ export const ToolbarItem = forwardRef<ITooltipWrapperRef, IDisplayMenuItem<IMenu
|
||||
noIcon={!icon}
|
||||
active={activated}
|
||||
disabled={disabled}
|
||||
onClick={() => executeCommand(props.commandId ?? props.id, value ?? params)}
|
||||
onClick={() => executeCommand(props.commandId ?? props.id, commandValue)}
|
||||
onDoubleClick={() => props.subId && executeCommand(props.subId)}
|
||||
>
|
||||
{isCustomComponent
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* 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 type { IMenuSchema } from '../../../../services/menu/menu-manager.service';
|
||||
import { LocaleService } from '@univerjs/core';
|
||||
import { clsx } from '@univerjs/design';
|
||||
import { useDependency } from '../../../../utils/di';
|
||||
|
||||
export function ClassicMenu({
|
||||
ribbon,
|
||||
activatedTab,
|
||||
onSelectTab,
|
||||
}: {
|
||||
ribbon: IMenuSchema[];
|
||||
activatedTab: string;
|
||||
onSelectTab: (tab: IMenuSchema) => void;
|
||||
}) {
|
||||
const localeService = useDependency(LocaleService);
|
||||
return (
|
||||
<div
|
||||
className={`
|
||||
univer-flex univer-h-9 univer-w-full univer-items-center univer-justify-center univer-gap-1
|
||||
univer-overflow-x-auto univer-rounded-md univer-bg-gray-50 univer-px-3
|
||||
dark:!univer-bg-gray-900
|
||||
`}
|
||||
role="tablist"
|
||||
aria-label={localeService.t('ribbon.menu')}
|
||||
>
|
||||
{ribbon.map((group) => {
|
||||
const isActive = activatedTab === group.key;
|
||||
return (
|
||||
<button
|
||||
key={group.key}
|
||||
type="button"
|
||||
role="tab"
|
||||
aria-selected={isActive}
|
||||
title={localeService.t(group.key)}
|
||||
onClick={() => onSelectTab(group)}
|
||||
className={clsx(`
|
||||
univer-focus:outline-none univer-focus:ring-2 univer-focus:ring-primary-500
|
||||
dark:!univer-focus:ring-primary-300
|
||||
univer-flex univer-cursor-pointer univer-appearance-none univer-items-center univer-gap-1
|
||||
univer-rounded-sm univer-border-none univer-px-2 univer-py-1 univer-text-sm
|
||||
univer-transition-colors
|
||||
`, isActive
|
||||
? `
|
||||
univer-bg-primary-50 univer-font-semibold univer-text-primary-600 univer-shadow-sm
|
||||
dark:!univer-bg-primary-900 dark:!univer-text-primary-300
|
||||
`
|
||||
: `
|
||||
univer-hover:bg-gray-100
|
||||
dark:!univer-hover:bg-gray-700
|
||||
univer-bg-transparent univer-text-gray-700
|
||||
dark:!univer-text-gray-200
|
||||
`)}
|
||||
>
|
||||
{localeService.t(group.key)}
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* 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 type { IMenuSchema } from '../../../../services/menu/menu-manager.service';
|
||||
import { LocaleService } from '@univerjs/core';
|
||||
import { borderClassName, clsx, HoverCard } from '@univerjs/design';
|
||||
import { DatabaseIcon, EyeIcon, FunctionIcon, HomeIcon, InsertIcon, MoreDownIcon, MoreFunctionIcon } from '@univerjs/icons';
|
||||
import { useState } from 'react';
|
||||
import { RibbonPosition } from '../../../../services/menu/types';
|
||||
import { useDependency } from '../../../../utils/di';
|
||||
|
||||
const iconMap = {
|
||||
[RibbonPosition.START]: HomeIcon,
|
||||
[RibbonPosition.INSERT]: InsertIcon,
|
||||
[RibbonPosition.FORMULAS]: FunctionIcon,
|
||||
[RibbonPosition.DATA]: DatabaseIcon,
|
||||
[RibbonPosition.VIEW]: EyeIcon,
|
||||
[RibbonPosition.OTHERS]: MoreFunctionIcon,
|
||||
};
|
||||
|
||||
export function DefaultMenu({
|
||||
ribbon,
|
||||
activatedTab,
|
||||
onSelectTab,
|
||||
}: {
|
||||
ribbon: IMenuSchema[];
|
||||
activatedTab: string;
|
||||
onSelectTab: (tab: IMenuSchema) => void;
|
||||
}) {
|
||||
const localeService = useDependency(LocaleService);
|
||||
|
||||
const [groupSelectorVisible, setGroupSelectorVisible] = useState(false);
|
||||
|
||||
function handleSelectTab(tab: IMenuSchema) {
|
||||
onSelectTab(tab);
|
||||
setGroupSelectorVisible(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<HoverCard
|
||||
className="univer-max-w-96 !univer-rounded-xl"
|
||||
align="start"
|
||||
open={groupSelectorVisible}
|
||||
overlay={(
|
||||
<div className="univer-grid univer-gap-1 univer-px-2 univer-py-1">
|
||||
{ribbon.map((group) => {
|
||||
const Icon = iconMap[group.key as RibbonPosition];
|
||||
|
||||
return (
|
||||
<a
|
||||
key={group.key}
|
||||
data-u-comp="ribbon-group-btn"
|
||||
className={`
|
||||
univer-box-border univer-flex univer-cursor-pointer univer-items-center univer-gap-2.5
|
||||
univer-rounded-lg univer-px-2 univer-py-1.5
|
||||
hover:univer-bg-gray-100
|
||||
dark:hover:!univer-bg-gray-700
|
||||
`}
|
||||
role="button"
|
||||
onClick={() => handleSelectTab(group)}
|
||||
>
|
||||
<span
|
||||
className={clsx(`
|
||||
univer-box-border univer-flex univer-size-9 univer-flex-shrink-0
|
||||
univer-items-center univer-justify-center univer-rounded-lg
|
||||
`, borderClassName)}
|
||||
>
|
||||
<Icon
|
||||
className={`
|
||||
univer-text-gray-500
|
||||
dark:!univer-text-gray-300
|
||||
`}
|
||||
/>
|
||||
</span>
|
||||
<span className="univer-flex univer-flex-col">
|
||||
<strong
|
||||
className={`
|
||||
univer-text-sm univer-font-semibold univer-text-gray-800
|
||||
dark:!univer-text-gray-200
|
||||
`}
|
||||
>
|
||||
{localeService.t(group.key)}
|
||||
</strong>
|
||||
<span className="univer-text-xs univer-text-gray-400">
|
||||
{localeService.t(`${group.key}Desc`)}
|
||||
</span>
|
||||
</span>
|
||||
</a>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
onOpenChange={setGroupSelectorVisible}
|
||||
>
|
||||
<a
|
||||
className={`
|
||||
univer-mr-2 univer-flex univer-h-7 univer-cursor-pointer univer-items-center univer-gap-1.5
|
||||
univer-whitespace-nowrap !univer-rounded-full univer-bg-gray-700 univer-pl-3 univer-pr-2
|
||||
univer-text-sm univer-text-white
|
||||
dark:!univer-bg-gray-200 dark:!univer-text-gray-800
|
||||
`}
|
||||
onClick={() => setGroupSelectorVisible(true)}
|
||||
>
|
||||
{localeService.t(activatedTab)}
|
||||
<MoreDownIcon
|
||||
className={`
|
||||
univer-text-gray-200
|
||||
dark:!univer-text-gray-500
|
||||
`}
|
||||
/>
|
||||
</a>
|
||||
</HoverCard>
|
||||
);
|
||||
}
|
||||
@@ -15,14 +15,14 @@
|
||||
*/
|
||||
|
||||
import type { MenuSchemaType } from '@univerjs/ui';
|
||||
import { RibbonStartGroup } from '@univerjs/ui';
|
||||
import { RibbonOthersGroup } from '@univerjs/ui';
|
||||
import { ToggleScriptPanelOperation } from '../commands/operations/panel.operation';
|
||||
import { UniscriptMenuItemFactory } from './menu';
|
||||
|
||||
export const menuSchema: MenuSchemaType = {
|
||||
[RibbonStartGroup.OTHERS]: {
|
||||
[RibbonOthersGroup.OTHERS]: {
|
||||
[ToggleScriptPanelOperation.id]: {
|
||||
order: 2,
|
||||
order: 0,
|
||||
menuItemFactory: UniscriptMenuItemFactory,
|
||||
},
|
||||
},
|
||||
|
||||
Generated
+1047
-941
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user