@univerjs/ui 0.24.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/lib/cjs/facade.js +8 -7
  2. package/lib/cjs/index.js +374 -173
  3. package/lib/cjs/locale/ar-SA.js +81 -0
  4. package/lib/cjs/locale/ca-ES.js +5 -3
  5. package/lib/cjs/locale/de-DE.js +81 -0
  6. package/lib/cjs/locale/en-US.js +5 -3
  7. package/lib/cjs/locale/es-ES.js +5 -3
  8. package/lib/cjs/locale/fa-IR.js +5 -3
  9. package/lib/cjs/locale/fr-FR.js +5 -3
  10. package/lib/cjs/locale/id-ID.js +81 -0
  11. package/lib/cjs/locale/it-IT.js +81 -0
  12. package/lib/cjs/locale/ja-JP.js +5 -3
  13. package/lib/cjs/locale/ko-KR.js +5 -3
  14. package/lib/cjs/locale/pl-PL.js +81 -0
  15. package/lib/cjs/locale/pt-BR.js +81 -0
  16. package/lib/cjs/locale/ru-RU.js +5 -3
  17. package/lib/cjs/locale/sk-SK.js +5 -3
  18. package/lib/cjs/locale/vi-VN.js +5 -3
  19. package/lib/cjs/locale/zh-CN.js +5 -3
  20. package/lib/cjs/locale/zh-HK.js +81 -0
  21. package/lib/cjs/locale/zh-TW.js +5 -3
  22. package/lib/es/facade.js +8 -7
  23. package/lib/es/index.js +375 -158
  24. package/lib/es/locale/ar-SA.js +80 -0
  25. package/lib/es/locale/ca-ES.js +5 -3
  26. package/lib/es/locale/de-DE.js +80 -0
  27. package/lib/es/locale/en-US.js +5 -3
  28. package/lib/es/locale/es-ES.js +5 -3
  29. package/lib/es/locale/fa-IR.js +5 -3
  30. package/lib/es/locale/fr-FR.js +5 -3
  31. package/lib/es/locale/id-ID.js +80 -0
  32. package/lib/es/locale/it-IT.js +80 -0
  33. package/lib/es/locale/ja-JP.js +5 -3
  34. package/lib/es/locale/ko-KR.js +5 -3
  35. package/lib/es/locale/pl-PL.js +80 -0
  36. package/lib/es/locale/pt-BR.js +80 -0
  37. package/lib/es/locale/ru-RU.js +5 -3
  38. package/lib/es/locale/sk-SK.js +5 -3
  39. package/lib/es/locale/vi-VN.js +5 -3
  40. package/lib/es/locale/zh-CN.js +5 -3
  41. package/lib/es/locale/zh-HK.js +80 -0
  42. package/lib/es/locale/zh-TW.js +5 -3
  43. package/lib/facade.js +8 -7
  44. package/lib/index.css +9 -4
  45. package/lib/index.js +375 -158
  46. package/lib/locale/ar-SA.js +80 -0
  47. package/lib/locale/ca-ES.js +5 -3
  48. package/lib/locale/de-DE.js +80 -0
  49. package/lib/locale/en-US.js +5 -3
  50. package/lib/locale/es-ES.js +5 -3
  51. package/lib/locale/fa-IR.js +5 -3
  52. package/lib/locale/fr-FR.js +5 -3
  53. package/lib/locale/id-ID.js +80 -0
  54. package/lib/locale/it-IT.js +80 -0
  55. package/lib/locale/ja-JP.js +5 -3
  56. package/lib/locale/ko-KR.js +5 -3
  57. package/lib/locale/pl-PL.js +80 -0
  58. package/lib/locale/pt-BR.js +80 -0
  59. package/lib/locale/ru-RU.js +5 -3
  60. package/lib/locale/sk-SK.js +5 -3
  61. package/lib/locale/vi-VN.js +5 -3
  62. package/lib/locale/zh-CN.js +5 -3
  63. package/lib/locale/zh-HK.js +80 -0
  64. package/lib/locale/zh-TW.js +5 -3
  65. package/lib/types/components/menu/desktop/DesignTinyMenuGroup.d.ts +1 -0
  66. package/lib/types/components/menu/desktop/TinyMenuGroup.d.ts +4 -0
  67. package/lib/types/facade/f-shortcut.d.ts +2 -1
  68. package/lib/types/facade/f-univer.d.ts +8 -4
  69. package/lib/types/index.d.ts +0 -1
  70. package/lib/types/{components/hooks/locale.d.ts → locale/ar-SA.d.ts} +3 -3
  71. package/lib/types/locale/de-DE.d.ts +18 -0
  72. package/lib/types/locale/en-US.d.ts +79 -75
  73. package/lib/types/locale/id-ID.d.ts +18 -0
  74. package/lib/types/locale/it-IT.d.ts +18 -0
  75. package/lib/types/locale/pl-PL.d.ts +18 -0
  76. package/lib/types/locale/pt-BR.d.ts +18 -0
  77. package/lib/types/locale/zh-HK.d.ts +18 -0
  78. package/lib/types/services/before-close/before-close.service.d.ts +5 -1
  79. package/lib/types/services/clipboard/clipboard-interface.service.d.ts +2 -2
  80. package/lib/types/services/menu/menu-manager.service.d.ts +1 -0
  81. package/lib/types/services/ribbon/ribbon.service.d.ts +2 -0
  82. package/lib/types/services/shortcut/shortcut.service.d.ts +8 -0
  83. package/lib/types/views/components/context-menu/ContextMenuPanel.d.ts +5 -0
  84. package/lib/umd/facade.js +1 -1
  85. package/lib/umd/index.js +51 -36
  86. package/lib/umd/locale/ar-SA.js +1 -0
  87. package/lib/umd/locale/ca-ES.js +1 -1
  88. package/lib/umd/locale/de-DE.js +1 -0
  89. package/lib/umd/locale/en-US.js +1 -1
  90. package/lib/umd/locale/es-ES.js +1 -1
  91. package/lib/umd/locale/fa-IR.js +1 -1
  92. package/lib/umd/locale/fr-FR.js +1 -1
  93. package/lib/umd/locale/id-ID.js +1 -0
  94. package/lib/umd/locale/it-IT.js +1 -0
  95. package/lib/umd/locale/ja-JP.js +1 -1
  96. package/lib/umd/locale/ko-KR.js +1 -1
  97. package/lib/umd/locale/pl-PL.js +1 -0
  98. package/lib/umd/locale/pt-BR.js +1 -0
  99. package/lib/umd/locale/ru-RU.js +1 -1
  100. package/lib/umd/locale/sk-SK.js +1 -1
  101. package/lib/umd/locale/vi-VN.js +1 -1
  102. package/lib/umd/locale/zh-CN.js +1 -1
  103. package/lib/umd/locale/zh-HK.js +1 -0
  104. package/lib/umd/locale/zh-TW.js +1 -1
  105. package/package.json +8 -8
package/lib/cjs/index.js CHANGED
@@ -40,7 +40,7 @@ let react_dom = require("react-dom");
40
40
  let localforage = require("localforage");
41
41
  localforage = __toESM(localforage);
42
42
 
43
- //#region \0@oxc-project+runtime@0.129.0/helpers/typeof.js
43
+ //#region \0@oxc-project+runtime@0.133.0/helpers/esm/typeof.js
44
44
  function _typeof(o) {
45
45
  "@babel/helpers - typeof";
46
46
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -51,7 +51,7 @@ function _typeof(o) {
51
51
  }
52
52
 
53
53
  //#endregion
54
- //#region \0@oxc-project+runtime@0.129.0/helpers/toPrimitive.js
54
+ //#region \0@oxc-project+runtime@0.133.0/helpers/esm/toPrimitive.js
55
55
  function toPrimitive(t, r) {
56
56
  if ("object" != _typeof(t) || !t) return t;
57
57
  var e = t[Symbol.toPrimitive];
@@ -64,14 +64,14 @@ function toPrimitive(t, r) {
64
64
  }
65
65
 
66
66
  //#endregion
67
- //#region \0@oxc-project+runtime@0.129.0/helpers/toPropertyKey.js
67
+ //#region \0@oxc-project+runtime@0.133.0/helpers/esm/toPropertyKey.js
68
68
  function toPropertyKey(t) {
69
69
  var i = toPrimitive(t, "string");
70
70
  return "symbol" == _typeof(i) ? i : i + "";
71
71
  }
72
72
 
73
73
  //#endregion
74
- //#region \0@oxc-project+runtime@0.129.0/helpers/defineProperty.js
74
+ //#region \0@oxc-project+runtime@0.133.0/helpers/esm/defineProperty.js
75
75
  function _defineProperty(e, r, t) {
76
76
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
77
77
  value: t,
@@ -140,7 +140,7 @@ const ToggleShortcutPanelOperation = {
140
140
  } else {
141
141
  shortcutPanelService.open();
142
142
  sidebarService.open({
143
- header: { title: "shortcut-panel.title" },
143
+ header: { title: "ui.shortcut-panel.title" },
144
144
  children: { label: ShortcutPanelComponentName }
145
145
  });
146
146
  }
@@ -368,9 +368,13 @@ function getMenuHiddenObservable(accessor, targetUniverType, matchUnitId, needHi
368
368
  subscriber.next(univerType !== targetUniverType);
369
369
  });
370
370
  const focusedUniverInstance = univerInstanceService.getFocusedUnit();
371
- if (focusedUniverInstance == null) return subscriber.next(true);
372
- const univerType = univerInstanceService.getUnitType(focusedUniverInstance.getUnitId());
373
- subscriber.next(univerType !== targetUniverType);
371
+ if (focusedUniverInstance == null) {
372
+ const currentUnit = univerInstanceService.getCurrentUnitOfType(targetUniverType);
373
+ subscriber.next(currentUnit == null);
374
+ } else {
375
+ const univerType = univerInstanceService.getUnitType(focusedUniverInstance.getUnitId());
376
+ subscriber.next(univerType !== targetUniverType);
377
+ }
374
378
  return () => subscription.unsubscribe();
375
379
  });
376
380
  }
@@ -384,9 +388,11 @@ function getHeaderFooterMenuHiddenObservable(accessor) {
384
388
  subscriber.next(documentFlavor !== _univerjs_core.DocumentFlavor.TRADITIONAL);
385
389
  });
386
390
  const docDataModel = univerInstanceService.getCurrentUniverDocInstance();
387
- if (docDataModel == null) return subscriber.next(true);
388
- const documentFlavor = docDataModel === null || docDataModel === void 0 ? void 0 : docDataModel.getSnapshot().documentStyle.documentFlavor;
389
- subscriber.next(documentFlavor !== _univerjs_core.DocumentFlavor.TRADITIONAL);
391
+ if (docDataModel == null) subscriber.next(true);
392
+ else {
393
+ const documentFlavor = docDataModel === null || docDataModel === void 0 ? void 0 : docDataModel.getSnapshot().documentStyle.documentFlavor;
394
+ subscriber.next(documentFlavor !== _univerjs_core.DocumentFlavor.TRADITIONAL);
395
+ }
390
396
  return () => subscription.unsubscribe();
391
397
  });
392
398
  }
@@ -795,7 +801,7 @@ const configSymbol = Symbol(UI_PLUGIN_CONFIG_KEY);
795
801
  const defaultPluginConfig = {};
796
802
 
797
803
  //#endregion
798
- //#region \0@oxc-project+runtime@0.129.0/helpers/decorateParam.js
804
+ //#region \0@oxc-project+runtime@0.133.0/helpers/esm/decorateParam.js
799
805
  function __decorateParam(paramIndex, decorator) {
800
806
  return function(target, key) {
801
807
  decorator(target, key, paramIndex);
@@ -803,7 +809,7 @@ function __decorateParam(paramIndex, decorator) {
803
809
  }
804
810
 
805
811
  //#endregion
806
- //#region \0@oxc-project+runtime@0.129.0/helpers/decorate.js
812
+ //#region \0@oxc-project+runtime@0.133.0/helpers/esm/decorate.js
807
813
  function __decorate(decorators, target, key, desc) {
808
814
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
809
815
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -817,67 +823,67 @@ const IFontService = (0, _univerjs_core.createIdentifier)("univer.font-service")
817
823
  const DEFAULT_FONT_LIST = [
818
824
  {
819
825
  value: "Arial",
820
- label: "fontFamily.arial",
826
+ label: "ui.fontFamily.arial",
821
827
  category: "sans-serif"
822
828
  },
823
829
  {
824
830
  value: "Times New Roman",
825
- label: "fontFamily.times-new-roman",
831
+ label: "ui.fontFamily.times-new-roman",
826
832
  category: "serif"
827
833
  },
828
834
  {
829
835
  value: "Tahoma",
830
- label: "fontFamily.tahoma",
836
+ label: "ui.fontFamily.tahoma",
831
837
  category: "sans-serif"
832
838
  },
833
839
  {
834
840
  value: "Verdana",
835
- label: "fontFamily.verdana",
841
+ label: "ui.fontFamily.verdana",
836
842
  category: "sans-serif"
837
843
  },
838
844
  {
839
845
  value: "Microsoft YaHei",
840
- label: "fontFamily.microsoft-yahei",
846
+ label: "ui.fontFamily.microsoft-yahei",
841
847
  category: "sans-serif"
842
848
  },
843
849
  {
844
850
  value: "SimSun",
845
- label: "fontFamily.simsun",
851
+ label: "ui.fontFamily.simsun",
846
852
  category: "serif"
847
853
  },
848
854
  {
849
855
  value: "SimHei",
850
- label: "fontFamily.simhei",
856
+ label: "ui.fontFamily.simhei",
851
857
  category: "sans-serif"
852
858
  },
853
859
  {
854
860
  value: "Kaiti",
855
- label: "fontFamily.kaiti",
861
+ label: "ui.fontFamily.kaiti",
856
862
  category: "serif"
857
863
  },
858
864
  {
859
865
  value: "FangSong",
860
- label: "fontFamily.fangsong",
866
+ label: "ui.fontFamily.fangsong",
861
867
  category: "serif"
862
868
  },
863
869
  {
864
870
  value: "NSimSun",
865
- label: "fontFamily.nsimsun",
871
+ label: "ui.fontFamily.nsimsun",
866
872
  category: "serif"
867
873
  },
868
874
  {
869
875
  value: "STXinwei",
870
- label: "fontFamily.stxinwei",
876
+ label: "ui.fontFamily.stxinwei",
871
877
  category: "serif"
872
878
  },
873
879
  {
874
880
  value: "STXingkai",
875
- label: "fontFamily.stxingkai",
881
+ label: "ui.fontFamily.stxingkai",
876
882
  category: "serif"
877
883
  },
878
884
  {
879
885
  value: "STLiti",
880
- label: "fontFamily.stliti",
886
+ label: "ui.fontFamily.stliti",
881
887
  category: "serif"
882
888
  }
883
889
  ];
@@ -1166,7 +1172,7 @@ const FontFamilyItem = ({ id, value }) => {
1166
1172
  type: "button",
1167
1173
  onClick: () => handleSelectFont(font.value),
1168
1174
  children: [localeService.t(font.label), !fontService.isFontSupported(font.value) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Tooltip, {
1169
- title: localeService.t("fontFamily.not-supported"),
1175
+ title: localeService.t("ui.fontFamily.not-supported"),
1170
1176
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.InfoIcon, { className: "univer-text-gray-300 dark:!univer-text-gray-400" })
1171
1177
  })]
1172
1178
  }) }, font.value))
@@ -1274,35 +1280,35 @@ const FONT_SIZE_LIST = [
1274
1280
  ];
1275
1281
  const HEADING_LIST = [
1276
1282
  {
1277
- label: "toolbar.heading.normal",
1283
+ label: "ui.toolbar.heading.normal",
1278
1284
  value: _univerjs_core.NamedStyleType.NORMAL_TEXT
1279
1285
  },
1280
1286
  {
1281
- label: "toolbar.heading.title",
1287
+ label: "ui.toolbar.heading.title",
1282
1288
  value: _univerjs_core.NamedStyleType.TITLE
1283
1289
  },
1284
1290
  {
1285
- label: "toolbar.heading.subTitle",
1291
+ label: "ui.toolbar.heading.subTitle",
1286
1292
  value: _univerjs_core.NamedStyleType.SUBTITLE
1287
1293
  },
1288
1294
  {
1289
- label: "toolbar.heading.1",
1295
+ label: "ui.toolbar.heading.1",
1290
1296
  value: _univerjs_core.NamedStyleType.HEADING_1
1291
1297
  },
1292
1298
  {
1293
- label: "toolbar.heading.2",
1299
+ label: "ui.toolbar.heading.2",
1294
1300
  value: _univerjs_core.NamedStyleType.HEADING_2
1295
1301
  },
1296
1302
  {
1297
- label: "toolbar.heading.3",
1303
+ label: "ui.toolbar.heading.3",
1298
1304
  value: _univerjs_core.NamedStyleType.HEADING_3
1299
1305
  },
1300
1306
  {
1301
- label: "toolbar.heading.4",
1307
+ label: "ui.toolbar.heading.4",
1302
1308
  value: _univerjs_core.NamedStyleType.HEADING_4
1303
1309
  },
1304
1310
  {
1305
- label: "toolbar.heading.5",
1311
+ label: "ui.toolbar.heading.5",
1306
1312
  value: _univerjs_core.NamedStyleType.HEADING_5
1307
1313
  }
1308
1314
  ];
@@ -1494,27 +1500,6 @@ const useVirtualList = (list, options) => {
1494
1500
  }];
1495
1501
  };
1496
1502
 
1497
- //#endregion
1498
- //#region src/components/hooks/locale.ts
1499
- /**
1500
- * Copyright 2023-present DreamNum Co., Ltd.
1501
- *
1502
- * Licensed under the Apache License, Version 2.0 (the "License");
1503
- * you may not use this file except in compliance with the License.
1504
- * You may obtain a copy of the License at
1505
- *
1506
- * http://www.apache.org/licenses/LICENSE-2.0
1507
- *
1508
- * Unless required by applicable law or agreed to in writing, software
1509
- * distributed under the License is distributed on an "AS IS" BASIS,
1510
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1511
- * See the License for the specific language governing permissions and
1512
- * limitations under the License.
1513
- */
1514
- function t(localeService, key, ...args) {
1515
- return localeService.t(key);
1516
- }
1517
-
1518
1503
  //#endregion
1519
1504
  //#region src/components/progress-bar/ProgressBar.tsx
1520
1505
  /**
@@ -2026,15 +2011,17 @@ function whenEditorFocusedButNotCellEditor(contextService) {
2026
2011
  }
2027
2012
  const CopyShortcutItem = {
2028
2013
  id: CopyCommand.id,
2029
- description: "shortcut.copy",
2014
+ description: "ui.shortcut.copy",
2030
2015
  group: "1_common-edit",
2016
+ groupTitle: "ui.common-edit",
2031
2017
  binding: 67 | 4096,
2032
2018
  preconditions: whenEditorFocused
2033
2019
  };
2034
2020
  const CutShortcutItem = {
2035
2021
  id: CutCommand.id,
2036
- description: "shortcut.cut",
2022
+ description: "ui.shortcut.cut",
2037
2023
  group: "1_common-edit",
2024
+ groupTitle: "ui.common-edit",
2038
2025
  binding: 88 | 4096,
2039
2026
  preconditions: whenEditorFocused
2040
2027
  };
@@ -2043,22 +2030,25 @@ const CutShortcutItem = {
2043
2030
  */
2044
2031
  const OnlyDisplayPasteShortcutItem = {
2045
2032
  id: PasteCommand.id,
2046
- description: "shortcut.paste",
2033
+ description: "ui.shortcut.paste",
2047
2034
  group: "1_common-edit",
2035
+ groupTitle: "ui.common-edit",
2048
2036
  binding: 86 | 4096,
2049
2037
  preconditions: () => false
2050
2038
  };
2051
2039
  const UndoShortcutItem = {
2052
2040
  id: _univerjs_core.UndoCommand.id,
2053
- description: "shortcut.undo",
2041
+ description: "ui.shortcut.undo",
2054
2042
  group: "1_common-edit",
2043
+ groupTitle: "ui.common-edit",
2055
2044
  binding: 90 | 4096,
2056
2045
  preconditions: whenEditorFocusedButNotCellEditor
2057
2046
  };
2058
2047
  const RedoShortcutItem = {
2059
2048
  id: _univerjs_core.RedoCommand.id,
2060
- description: "shortcut.redo",
2049
+ description: "ui.shortcut.redo",
2061
2050
  group: "1_common-edit",
2051
+ groupTitle: "ui.common-edit",
2062
2052
  binding: 89 | 4096,
2063
2053
  preconditions: whenEditorFocusedButNotCellEditor
2064
2054
  };
@@ -2195,6 +2185,7 @@ let MenuManagerService = class MenuManagerService extends _univerjs_core.Disposa
2195
2185
  ["ribbon"]: {
2196
2186
  ["ribbon.start"]: {
2197
2187
  order: 0,
2188
+ title: "ui.ribbon.start",
2198
2189
  ["ribbon.start.history"]: { order: 0 },
2199
2190
  ["ribbon.start.format"]: { order: 1 },
2200
2191
  ["ribbon.start.layout"]: { order: 2 },
@@ -2202,17 +2193,20 @@ let MenuManagerService = class MenuManagerService extends _univerjs_core.Disposa
2202
2193
  },
2203
2194
  ["ribbon.insert"]: {
2204
2195
  order: 1,
2196
+ title: "ui.ribbon.insert",
2205
2197
  ["ribbon.insert.edit"]: { order: 0 },
2206
2198
  ["ribbon.insert.media"]: { order: 1 },
2207
2199
  ["ribbon.insert.others"]: { order: 2 }
2208
2200
  },
2209
2201
  ["ribbon.formulas"]: {
2210
2202
  order: 2,
2203
+ title: "ui.ribbon.formulas",
2211
2204
  ["ribbon.formulas.basic"]: { order: 0 },
2212
2205
  ["ribbon.formulas.others"]: { order: 1 }
2213
2206
  },
2214
2207
  ["ribbon.data"]: {
2215
2208
  order: 3,
2209
+ title: "ui.ribbon.data",
2216
2210
  ["ribbon.data.formulas"]: { order: 0 },
2217
2211
  ["ribbon.data.rules"]: { order: 1 },
2218
2212
  ["ribbon.data.organization"]: { order: 2 },
@@ -2220,12 +2214,14 @@ let MenuManagerService = class MenuManagerService extends _univerjs_core.Disposa
2220
2214
  },
2221
2215
  ["ribbon.view"]: {
2222
2216
  order: 4,
2217
+ title: "ui.ribbon.view",
2223
2218
  ["ribbon.view.display"]: { order: 0 },
2224
2219
  ["ribbon.view.Visibility"]: { order: 0 },
2225
2220
  ["ribbon.view.others"]: { order: 0 }
2226
2221
  },
2227
2222
  ["ribbon.others"]: {
2228
2223
  order: 5,
2224
+ title: "ui.ribbon.others",
2229
2225
  ["ribbon.others.others"]: { order: 0 }
2230
2226
  }
2231
2227
  },
@@ -2320,7 +2316,8 @@ let MenuManagerService = class MenuManagerService extends _univerjs_core.Disposa
2320
2316
  order: value.order,
2321
2317
  title: value.title,
2322
2318
  contextual: value.contextual,
2323
- quickLayout: value.quickLayout
2319
+ quickLayout: value.quickLayout,
2320
+ tiny: value.tiny
2324
2321
  };
2325
2322
  if (value.menuItemFactory) {
2326
2323
  const item = this._injector.invoke(value.menuItemFactory);
@@ -2338,7 +2335,7 @@ let MenuManagerService = class MenuManagerService extends _univerjs_core.Disposa
2338
2335
  if (menuItem.item || menuItem.children) result.push(menuItem);
2339
2336
  }
2340
2337
  }
2341
- return result;
2338
+ return result.sort((a, b) => normalizeMenuOrder(a.order) - normalizeMenuOrder(b.order));
2342
2339
  }
2343
2340
  /**
2344
2341
  * Get menu schema by position key
@@ -2379,6 +2376,9 @@ let MenuManagerService = class MenuManagerService extends _univerjs_core.Disposa
2379
2376
  }
2380
2377
  };
2381
2378
  MenuManagerService = __decorate([__decorateParam(0, (0, _univerjs_core.Inject)(_univerjs_core.Injector)), __decorateParam(1, _univerjs_core.IConfigService)], MenuManagerService);
2379
+ function normalizeMenuOrder(order) {
2380
+ return order !== null && order !== void 0 ? order : 0;
2381
+ }
2382
2382
 
2383
2383
  //#endregion
2384
2384
  //#region src/views/components/shortcut-panel/ShortcutPanel.tsx
@@ -2408,6 +2408,7 @@ function ShortcutPanel() {
2408
2408
  const updateShortcuts = (0, react.useCallback)(() => {
2409
2409
  const shortcutGroups = /* @__PURE__ */ new Map();
2410
2410
  const shortcuts = shortcutService.getAllShortcuts().filter((item) => !!item.group);
2411
+ const groupTitles = /* @__PURE__ */ new Map();
2411
2412
  for (const shortcut of shortcuts) {
2412
2413
  var _shortcut$description;
2413
2414
  const group = shortcut.group;
@@ -2415,16 +2416,18 @@ function ShortcutPanel() {
2415
2416
  title: localeService.t((_shortcut$description = shortcut.description) !== null && _shortcut$description !== void 0 ? _shortcut$description : shortcut.id),
2416
2417
  shortcut: shortcutService.getShortcutDisplay(shortcut)
2417
2418
  };
2418
- if (!/\d+_[a-zA-Z0-9]/.test(group)) throw new Error(`[ShortcutPanel]: Invalid shortcut group: ${group}!`);
2419
+ if (!/^\d+_/.test(group)) throw new Error(`[ShortcutPanel]: Invalid shortcut group: ${group}!`);
2420
+ if (!shortcut.groupTitle) throw new Error(`[ShortcutPanel]: Shortcut group "${group}" must provide a groupTitle!`);
2421
+ if (!groupTitles.has(group)) groupTitles.set(group, shortcut.groupTitle);
2419
2422
  if (!shortcutGroups.has(group)) shortcutGroups.set(group, []);
2420
2423
  shortcutGroups.get(group).push(shortcutItem);
2421
2424
  }
2422
2425
  setShortcutItems(Array.from(shortcutGroups.entries()).map(([name, items]) => {
2423
2426
  const groupSequence = name.split("_")[0];
2424
- const groupName = name.slice(groupSequence.length + 1);
2427
+ const localeKey = groupTitles.get(name);
2425
2428
  return {
2426
2429
  sequence: +groupSequence,
2427
- name: localeService.t(groupName),
2430
+ name: localeService.t(localeKey),
2428
2431
  items: (0, _univerjs_core.dedupeBy)(items, (item) => item.title + item.shortcut)
2429
2432
  };
2430
2433
  }).sort((a, b) => a.sequence - b.sequence));
@@ -2461,8 +2464,9 @@ function ShortcutPanel() {
2461
2464
  const ToggleShortcutPanelShortcut = {
2462
2465
  id: ToggleShortcutPanelOperation.id,
2463
2466
  binding: 4096 | 220,
2464
- description: "shortcut.shortcut-panel",
2465
- group: "10_global-shortcut"
2467
+ description: "ui.shortcut.shortcut-panel",
2468
+ group: "10_global-shortcut",
2469
+ groupTitle: "ui.global-shortcut"
2466
2470
  };
2467
2471
  let ShortcutPanelController = class ShortcutPanelController extends _univerjs_core.Disposable {
2468
2472
  constructor(injector, componentManager, shortcutService, _menuManagerService, commandService) {
@@ -2513,7 +2517,7 @@ function UndoMenuItemFactory(accessor) {
2513
2517
  type: 0,
2514
2518
  icon: "UndoIcon",
2515
2519
  title: "Undo",
2516
- tooltip: "toolbar.undo",
2520
+ tooltip: "ui.shortcut.undo",
2517
2521
  disabled$: undoRedoDisableFactory$(accessor, true)
2518
2522
  };
2519
2523
  }
@@ -2523,7 +2527,7 @@ function RedoMenuItemFactory(accessor) {
2523
2527
  type: 0,
2524
2528
  icon: "RedoIcon",
2525
2529
  title: "Redo",
2526
- tooltip: "toolbar.redo",
2530
+ tooltip: "ui.shortcut.redo",
2527
2531
  disabled$: undoRedoDisableFactory$(accessor, false)
2528
2532
  };
2529
2533
  }
@@ -2533,8 +2537,8 @@ function RedoMenuItemFactory(accessor) {
2533
2537
  function ShortcutPanelMenuItemFactory() {
2534
2538
  return {
2535
2539
  id: ToggleShortcutPanelOperation.id,
2536
- title: "toggle-shortcut-panel",
2537
- tooltip: "toggle-shortcut-panel",
2540
+ title: "ui.toggle-shortcut-panel",
2541
+ tooltip: "ui.toggle-shortcut-panel",
2538
2542
  icon: "ShortcutIcon",
2539
2543
  type: 0
2540
2544
  };
@@ -3084,6 +3088,7 @@ let DesktopRibbonService = class DesktopRibbonService extends _univerjs_core.Dis
3084
3088
  _defineProperty(this, "_visibleContextualTabs", /* @__PURE__ */ new Set());
3085
3089
  _defineProperty(this, "_contextualTabs", /* @__PURE__ */ new Set());
3086
3090
  _defineProperty(this, "_lastNonContextualActivatedTab", "ribbon.start");
3091
+ _defineProperty(this, "_hiddenSubscription", null);
3087
3092
  this._initRibbonSubscription();
3088
3093
  }
3089
3094
  setActivatedTab(tab) {
@@ -3116,6 +3121,7 @@ let DesktopRibbonService = class DesktopRibbonService extends _univerjs_core.Dis
3116
3121
  }));
3117
3122
  }
3118
3123
  _updateRibbon() {
3124
+ var _this$_hiddenSubscrip;
3119
3125
  const ribbon = this._filterContextualTabs(this._menuManagerService.getMenuByPositionKey("ribbon"));
3120
3126
  const hiddenObservableMap = [];
3121
3127
  const hiddenKeyMap = [];
@@ -3132,7 +3138,8 @@ let DesktopRibbonService = class DesktopRibbonService extends _univerjs_core.Dis
3132
3138
  this._setRibbon(ribbon);
3133
3139
  return;
3134
3140
  }
3135
- (0, rxjs.combineLatest)(hiddenObservableMap).pipe((0, rxjs_operators.startWith)(new Array(hiddenObservableMap.length).fill(false))).subscribe((hiddenMap) => {
3141
+ (_this$_hiddenSubscrip = this._hiddenSubscription) === null || _this$_hiddenSubscrip === void 0 || _this$_hiddenSubscrip.unsubscribe();
3142
+ this._hiddenSubscription = (0, rxjs.combineLatest)(hiddenObservableMap).pipe((0, rxjs_operators.startWith)(new Array(hiddenObservableMap.length).fill(false))).subscribe((hiddenMap) => {
3136
3143
  const newRibbon = [];
3137
3144
  const hiddenPathMap = hiddenMap.map((hidden, index) => {
3138
3145
  if (hidden) return hiddenKeyMap[index];
@@ -3173,7 +3180,7 @@ let DesktopRibbonService = class DesktopRibbonService extends _univerjs_core.Dis
3173
3180
  })) newRibbon.push(newGroup);
3174
3181
  }
3175
3182
  this._setRibbon(newRibbon);
3176
- }).unsubscribe();
3183
+ });
3177
3184
  }
3178
3185
  _filterContextualTabs(ribbon) {
3179
3186
  this._contextualTabs.clear();
@@ -3189,12 +3196,27 @@ let DesktopRibbonService = class DesktopRibbonService extends _univerjs_core.Dis
3189
3196
  var _ref, _ribbon$find;
3190
3197
  const fallbackTab = (_ref = (_ribbon$find = ribbon.find((group) => group.key === this._lastNonContextualActivatedTab && !group.contextual)) !== null && _ribbon$find !== void 0 ? _ribbon$find : ribbon.find((group) => group.key === "ribbon.start")) !== null && _ref !== void 0 ? _ref : ribbon[0];
3191
3198
  if (fallbackTab) this._activatedTab$.next(fallbackTab.key);
3199
+ } else if (!activeGroup && ribbon.some((group) => group.key === "ribbon.start")) {
3200
+ const fallbackTab = ribbon.find((group) => group.key === "ribbon.start");
3201
+ this._activatedTab$.next(fallbackTab.key);
3202
+ if (!fallbackTab.contextual) this._lastNonContextualActivatedTab = fallbackTab.key;
3192
3203
  } else if (activeGroup && !activeGroup.contextual) this._lastNonContextualActivatedTab = activeGroup.key;
3193
3204
  this._ribbon$.next(ribbon);
3194
3205
  }
3195
3206
  _isContextualTab(tab) {
3196
3207
  return this._contextualTabs.has(tab) || this._ribbon$.getValue().some((group) => group.key === tab && group.contextual);
3197
3208
  }
3209
+ dispose() {
3210
+ var _this$_hiddenSubscrip2;
3211
+ (_this$_hiddenSubscrip2 = this._hiddenSubscription) === null || _this$_hiddenSubscrip2 === void 0 || _this$_hiddenSubscrip2.unsubscribe();
3212
+ this._hiddenSubscription = null;
3213
+ this._ribbon$.next([]);
3214
+ this._ribbon$.complete();
3215
+ this._activatedTab$.complete();
3216
+ this._collapsedIds$.complete();
3217
+ this._fakeToolbarVisible$.complete();
3218
+ super.dispose();
3219
+ }
3198
3220
  };
3199
3221
  DesktopRibbonService = __decorate([__decorateParam(0, IMenuManagerService), __decorateParam(1, _univerjs_core.IUniverInstanceService)], DesktopRibbonService);
3200
3222
 
@@ -3237,14 +3259,14 @@ function ClassicMenu({ ribbon, activatedTab, onSelectTab }) {
3237
3259
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3238
3260
  className: "univer-flex univer-size-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",
3239
3261
  role: "tablist",
3240
- "aria-label": localeService.t("ribbon.menu"),
3262
+ "aria-label": localeService.t("ui.ribbon.menu"),
3241
3263
  children: ribbon.map((group) => {
3242
3264
  const isActive = activatedTab === group.key;
3243
3265
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3244
3266
  type: "button",
3245
3267
  role: "tab",
3246
3268
  "aria-selected": isActive,
3247
- title: localeService.t(group.key),
3269
+ title: localeService.t(group.title || group.key),
3248
3270
  onClick: () => onSelectTab(group),
3249
3271
  className: (0, _univerjs_design.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 ? `
3250
3272
  univer-bg-primary-50 univer-font-semibold univer-text-primary-600 univer-shadow-sm
@@ -3255,7 +3277,7 @@ function ClassicMenu({ ribbon, activatedTab, onSelectTab }) {
3255
3277
  univer-bg-transparent univer-text-gray-700
3256
3278
  dark:!univer-text-gray-200
3257
3279
  `),
3258
- children: localeService.t(group.key)
3280
+ children: localeService.t(group.title || group.key)
3259
3281
  }, group.key);
3260
3282
  })
3261
3283
  });
@@ -3272,7 +3294,9 @@ const iconMap = {
3272
3294
  ["ribbon.others"]: _univerjs_icons.MoreFunctionIcon
3273
3295
  };
3274
3296
  function DefaultMenu({ ribbon, activatedTab, onSelectTab }) {
3297
+ var _ribbon$find;
3275
3298
  const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
3299
+ const activatedTabTitle = ((_ribbon$find = ribbon.find((group) => group.key === activatedTab)) === null || _ribbon$find === void 0 ? void 0 : _ribbon$find.title) || activatedTab;
3276
3300
  const [groupSelectorVisible, setGroupSelectorVisible] = (0, react.useState)(false);
3277
3301
  function handleSelectTab(tab) {
3278
3302
  onSelectTab(tab);
@@ -3299,10 +3323,10 @@ function DefaultMenu({ ribbon, activatedTab, onSelectTab }) {
3299
3323
  className: "univer-flex univer-flex-col",
3300
3324
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
3301
3325
  className: "univer-text-sm univer-font-semibold univer-text-gray-800 dark:!univer-text-gray-200",
3302
- children: localeService.t(group.key)
3326
+ children: localeService.t(group.title || group.key)
3303
3327
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3304
3328
  className: "univer-text-xs univer-text-gray-400",
3305
- children: localeService.t(`${group.key}Desc`)
3329
+ children: localeService.t(`${group.title || group.key}Desc`)
3306
3330
  })]
3307
3331
  })]
3308
3332
  }, group.key);
@@ -3312,7 +3336,7 @@ function DefaultMenu({ ribbon, activatedTab, onSelectTab }) {
3312
3336
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("a", {
3313
3337
  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",
3314
3338
  onClick: () => setGroupSelectorVisible(true),
3315
- children: [localeService.t(activatedTab), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.MoreDownIcon, { className: "univer-text-gray-200 dark:!univer-text-gray-500" })]
3339
+ children: [localeService.t(activatedTabTitle), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.MoreDownIcon, { className: "univer-text-gray-200 dark:!univer-text-gray-500" })]
3316
3340
  })
3317
3341
  });
3318
3342
  }
@@ -3534,6 +3558,10 @@ function DropdownMenuWrapper({ menuId, slot, value, options, children, disabled,
3534
3558
  function handleVisibleChange(visible) {
3535
3559
  setDropdownVisible(visible);
3536
3560
  }
3561
+ function handleOptionSelect(option) {
3562
+ onOptionSelect(option);
3563
+ setDropdownVisible(false);
3564
+ }
3537
3565
  (0, react.useEffect)(() => {
3538
3566
  const subscriptions = [];
3539
3567
  menuItems.forEach((item) => {
@@ -3572,7 +3600,7 @@ function DropdownMenuWrapper({ menuId, slot, value, options, children, disabled,
3572
3600
  overlay: options.map((option, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Label, {
3573
3601
  value,
3574
3602
  option,
3575
- onOptionSelect
3603
+ onOptionSelect: handleOptionSelect
3576
3604
  }, index)),
3577
3605
  children
3578
3606
  });
@@ -3586,15 +3614,16 @@ function DropdownMenuWrapper({ menuId, slot, value, options, children, disabled,
3586
3614
  icon: option.icon,
3587
3615
  value,
3588
3616
  option,
3589
- onOptionSelect
3617
+ onOptionSelect: handleOptionSelect
3590
3618
  }),
3591
3619
  disabled: option.disabled,
3592
3620
  onSelect: () => {
3593
3621
  if (typeof option.value === "undefined") return;
3594
- onOptionSelect === null || onOptionSelect === void 0 || onOptionSelect({ ...option });
3622
+ handleOptionSelect({ ...option });
3595
3623
  }
3596
3624
  };
3597
3625
  });
3626
+ if (filteredMenuItems.length) items.push({ type: "separator" });
3598
3627
  for (const menuItem of filteredMenuItems) {
3599
3628
  if (!menuItem.item) continue;
3600
3629
  const { title, id, commandId, icon } = menuItem.item;
@@ -3610,7 +3639,7 @@ function DropdownMenuWrapper({ menuId, slot, value, options, children, disabled,
3610
3639
  } }
3611
3640
  }),
3612
3641
  onSelect: () => {
3613
- onOptionSelect === null || onOptionSelect === void 0 || onOptionSelect({
3642
+ handleOptionSelect({
3614
3643
  commandId,
3615
3644
  id
3616
3645
  });
@@ -3643,7 +3672,7 @@ function DropdownMenuWrapper({ menuId, slot, value, options, children, disabled,
3643
3672
  } }
3644
3673
  }),
3645
3674
  onSelect: () => {
3646
- onOptionSelect === null || onOptionSelect === void 0 || onOptionSelect({
3675
+ handleOptionSelect({
3647
3676
  commandId,
3648
3677
  id
3649
3678
  });
@@ -3849,13 +3878,17 @@ function Ribbon(props) {
3849
3878
  }
3850
3879
  return ribbonData;
3851
3880
  }, [ribbonType, ribbonData]);
3881
+ const activatedTabTitle = (0, react.useMemo)(() => {
3882
+ var _ribbon$find;
3883
+ return ((_ribbon$find = ribbon.find((group) => group.key === activatedTab)) === null || _ribbon$find === void 0 ? void 0 : _ribbon$find.title) || activatedTab;
3884
+ }, [ribbon, activatedTab]);
3852
3885
  const handleSelectTab = (0, react.useCallback)((group) => {
3853
3886
  toolbarItemRefs.current = {};
3854
3887
  ribbonService.setActivatedTab(group.key);
3855
3888
  }, []);
3856
3889
  const activeGroup = (0, react.useMemo)(() => {
3857
- var _ribbon$find$children, _ribbon$find;
3858
- const allGroups = (_ribbon$find$children = (_ribbon$find = ribbon.find((group) => group.key === activatedTab)) === null || _ribbon$find === void 0 ? void 0 : _ribbon$find.children) !== null && _ribbon$find$children !== void 0 ? _ribbon$find$children : [];
3890
+ var _ribbon$find$children, _ribbon$find2;
3891
+ const allGroups = (_ribbon$find$children = (_ribbon$find2 = ribbon.find((group) => group.key === activatedTab)) === null || _ribbon$find2 === void 0 ? void 0 : _ribbon$find2.children) !== null && _ribbon$find$children !== void 0 ? _ribbon$find$children : [];
3859
3892
  const visibleGroups = [];
3860
3893
  const hiddenGroups = [];
3861
3894
  for (const item of allGroups) if (item.children) {
@@ -3885,14 +3918,14 @@ function Ribbon(props) {
3885
3918
  for (const entry of entries) {
3886
3919
  ribbonService.setFakeToolbarVisible(true);
3887
3920
  timer = requestAnimationFrame(() => {
3888
- var _ribbon$find$children2, _ribbon$find2;
3921
+ var _ribbon$find$children2, _ribbon$find3;
3889
3922
  const { width: avaliableWidth } = entry.contentRect;
3890
3923
  const sortedToolbarItems = Object.values(toolbarItemRefs.current).sort((a, b) => {
3891
3924
  return a.order - b.order || a.groupOrder - b.groupOrder || a.itemOrder - b.itemOrder;
3892
3925
  });
3893
3926
  const newCollapsedIds = [];
3894
3927
  let totalWidth = 32;
3895
- const gapWidth = (((_ribbon$find$children2 = (_ribbon$find2 = ribbon.find((group) => group.key === activatedTab)) === null || _ribbon$find2 === void 0 ? void 0 : _ribbon$find2.children) !== null && _ribbon$find$children2 !== void 0 ? _ribbon$find$children2 : []).length - 1) * 8;
3928
+ const gapWidth = (((_ribbon$find$children2 = (_ribbon$find3 = ribbon.find((group) => group.key === activatedTab)) === null || _ribbon$find3 === void 0 ? void 0 : _ribbon$find3.children) !== null && _ribbon$find$children2 !== void 0 ? _ribbon$find$children2 : []).length - 1) * 8;
3896
3929
  totalWidth += gapWidth;
3897
3930
  for (const { el, key } of sortedToolbarItems) {
3898
3931
  const { width } = el.getBoundingClientRect();
@@ -3917,7 +3950,7 @@ function Ribbon(props) {
3917
3950
  children: activeGroup.allGroups.map((groupItem, index) => {
3918
3951
  var _groupItem$children, _groupItem$children2;
3919
3952
  return (((_groupItem$children = groupItem.children) === null || _groupItem$children === void 0 ? void 0 : _groupItem$children.length) || groupItem.item) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3920
- className: "univer-grid univer-shrink-0 univer-grid-flow-col univer-gap-2 univer-px-2",
3953
+ className: "\n univer-grid univer-shrink-0 univer-grid-flow-col univer-gap-2 univer-px-2\n empty:univer-hidden\n ",
3921
3954
  children: groupItem.children && ((_groupItem$children2 = groupItem.children) === null || _groupItem$children2 === void 0 ? void 0 : _groupItem$children2.map((child) => child.item && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarItem, {
3922
3955
  ...child.item,
3923
3956
  ref: (ref) => {
@@ -3938,7 +3971,7 @@ function Ribbon(props) {
3938
3971
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3939
3972
  "data-u-comp": "ribbon-header-menu",
3940
3973
  className: (0, _univerjs_design.clsx)("univer-relative univer-select-none", { "univer-h-9": ribbonType === "classic" || headerMenuComponents && headerMenuComponents.size > 0 }),
3941
- children: [ribbonType === "classic" && ribbon.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClassicMenu, {
3974
+ children: [ribbonType === "classic" && ribbon.length >= 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClassicMenu, {
3942
3975
  ribbon,
3943
3976
  activatedTab,
3944
3977
  onSelectTab: handleSelectTab
@@ -3949,11 +3982,10 @@ function Ribbon(props) {
3949
3982
  }),
3950
3983
  /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3951
3984
  className: (0, _univerjs_design.clsx)("univer-box-border univer-grid univer-h-10 univer-grid-flow-col univer-items-center univer-px-3 univer-text-sm", {
3952
- "univer-grid-cols-[1fr] univer-justify-center": ribbonType === "classic",
3953
- "univer-grid-cols-[auto,1fr]": ribbon.length > 1 && ribbonType !== "classic",
3954
- "univer-grid-cols-none": ribbon.length === 1
3985
+ "univer-grid-cols-[1fr] univer-justify-center": ribbonType === "classic" || ribbon.length === 1,
3986
+ "univer-grid-cols-[auto,1fr]": ribbon.length > 1 && ribbonType !== "classic"
3955
3987
  }, _univerjs_design.borderBottomClassName),
3956
- children: [ribbonType === "collapsed" && ribbon.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultMenu, {
3988
+ children: [ribbonType === "collapsed" && ribbon.length >= 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultMenu, {
3957
3989
  ribbon,
3958
3990
  activatedTab,
3959
3991
  onSelectTab: handleSelectTab
@@ -3962,11 +3994,11 @@ function Ribbon(props) {
3962
3994
  ref: containerRef,
3963
3995
  className: (0, _univerjs_design.clsx)("univer-flex univer-overflow-hidden", _univerjs_design.divideXClassName, { "univer-justify-center": ribbonType === "classic" }),
3964
3996
  role: "toolbar",
3965
- "aria-label": localeService.t(activatedTab),
3997
+ "aria-label": localeService.t(activatedTabTitle),
3966
3998
  children: [activeGroup.visibleGroups.map((groupItem) => {
3967
3999
  var _groupItem$children3, _groupItem$children4;
3968
4000
  return (((_groupItem$children3 = groupItem.children) === null || _groupItem$children3 === void 0 ? void 0 : _groupItem$children3.length) || groupItem.item) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.Fragment, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3969
- className: "univer-grid univer-shrink-0 univer-grid-flow-col univer-gap-2 univer-px-2",
4001
+ className: "\n univer-grid univer-shrink-0 univer-grid-flow-col univer-gap-2 univer-px-2\n empty:univer-hidden\n ",
3970
4002
  children: groupItem.children && ((_groupItem$children4 = groupItem.children) === null || _groupItem$children4 === void 0 ? void 0 : _groupItem$children4.map((child) => child.item && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarItem, { ...child.item }, child.key)))
3971
4003
  }) }, groupItem.key);
3972
4004
  }), collapsedIds.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -3994,7 +4026,7 @@ function Ribbon(props) {
3994
4026
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3995
4027
  type: "button",
3996
4028
  className: toolbarButtonClassName,
3997
- "aria-label": localeService.t("ribbon.more"),
4029
+ "aria-label": localeService.t("ui.ribbon.more"),
3998
4030
  "aria-haspopup": "true",
3999
4031
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.MoreFunctionIcon, {})
4000
4032
  })
@@ -4119,7 +4151,7 @@ function DesignTinyMenuGroup({ items }) {
4119
4151
  const ele = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4120
4152
  className: (0, _univerjs_design.clsx)("univer-flex univer-size-6 univer-cursor-pointer univer-items-center univer-justify-center univer-rounded-md hover:univer-bg-gray-50 dark:hover:!univer-bg-gray-900", { "univer-bg-gray-50 dark:!univer-bg-gray-900": item.active }, item.className),
4121
4153
  onClick: () => item.onClick(),
4122
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(item.Icon, { className: "univer-size-4 univer-text-gray-900 dark:!univer-text-gray-200" })
4154
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(item.Icon, { className: (0, _univerjs_design.clsx)("univer-size-4 univer-text-gray-900 dark:!univer-text-gray-200", item.iconClassName) })
4123
4155
  }, item.key);
4124
4156
  return item.tooltip ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Tooltip, {
4125
4157
  title: item.tooltip,
@@ -4131,8 +4163,21 @@ function DesignTinyMenuGroup({ items }) {
4131
4163
 
4132
4164
  //#endregion
4133
4165
  //#region src/components/menu/desktop/TinyMenuGroup.tsx
4166
+ const EMPTY_HIDDEN_ITEM_IDS = [];
4167
+ function resolveMenuItemActiveState(itemId, observableActive, activeItemIds) {
4168
+ if (activeItemIds) return Boolean(itemId && activeItemIds.includes(itemId));
4169
+ return observableActive;
4170
+ }
4171
+ function getTinyMenuChildStateKey(child) {
4172
+ var _child$item$id, _child$item;
4173
+ return (_child$item$id = (_child$item = child.item) === null || _child$item === void 0 ? void 0 : _child$item.id) !== null && _child$item$id !== void 0 ? _child$item$id : child.key;
4174
+ }
4175
+ function getVisibleTinyMenuChildren(children, hiddenItemKeys) {
4176
+ const hiddenSet = new Set(hiddenItemKeys);
4177
+ return children.filter((child) => !hiddenSet.has(getTinyMenuChildStateKey(child)));
4178
+ }
4134
4179
  function QuickTileMenuItem(props) {
4135
- const { menuSchema, onOptionSelect } = props;
4180
+ const { menuSchema, activeItemIds, onOptionSelect } = props;
4136
4181
  const componentManager = (0, _wendellhu_redi_react_bindings.useDependency)(ComponentManager);
4137
4182
  const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
4138
4183
  const menuItem = menuSchema.item;
@@ -4147,7 +4192,7 @@ function QuickTileMenuItem(props) {
4147
4192
  univer-cursor-pointer
4148
4193
  hover:univer-bg-gray-50
4149
4194
  dark:hover:!univer-bg-gray-600
4150
- `, activated && `
4195
+ `, resolveMenuItemActiveState(menuItem.id, activated, activeItemIds) && `
4151
4196
  univer-bg-primary-50 univer-text-primary-700 univer-ring-1 univer-ring-primary-600
4152
4197
  dark:!univer-bg-primary-900 dark:!univer-text-primary-100
4153
4198
  `),
@@ -4172,20 +4217,21 @@ function QuickTileMenuItem(props) {
4172
4217
  });
4173
4218
  }
4174
4219
  function UITinyMenuGroup(props) {
4175
- const { item, onOptionSelect } = props;
4220
+ const { item, activeItemIds, hiddenItemIds = EMPTY_HIDDEN_ITEM_IDS, onOptionSelect } = props;
4176
4221
  const [activeItems, setActiveItems] = (0, react.useState)([]);
4222
+ const [hiddenItems, setHiddenItems] = (0, react.useState)([]);
4177
4223
  const componentManager = (0, _wendellhu_redi_react_bindings.useDependency)(ComponentManager);
4178
4224
  const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
4179
4225
  (0, react.useEffect)(() => {
4180
4226
  if (!item.children) return;
4181
4227
  const observables = item.children.map((child) => {
4182
- var _child$item$activated, _child$item;
4183
- return (0, _univerjs_core.convertObservableToBehaviorSubject)((_child$item$activated = (_child$item = child.item) === null || _child$item === void 0 ? void 0 : _child$item.activated$) !== null && _child$item$activated !== void 0 ? _child$item$activated : (0, rxjs.of)(false), false);
4228
+ var _child$item$activated, _child$item2;
4229
+ return (0, _univerjs_core.convertObservableToBehaviorSubject)((_child$item$activated = (_child$item2 = child.item) === null || _child$item2 === void 0 ? void 0 : _child$item2.activated$) !== null && _child$item$activated !== void 0 ? _child$item$activated : (0, rxjs.of)(false), false);
4184
4230
  });
4185
4231
  const subscription = (0, rxjs.combineLatest)(observables).subscribe((activedArr) => {
4186
4232
  const actived = activedArr.map((actived, index) => ({
4187
4233
  actived,
4188
- item: item.children[index].item.id
4234
+ item: getTinyMenuChildStateKey(item.children[index])
4189
4235
  })).filter((actived) => actived.actived);
4190
4236
  if (actived.length === 0) setActiveItems([]);
4191
4237
  else setActiveItems(actived.map((actived) => actived.item));
@@ -4197,34 +4243,65 @@ function UITinyMenuGroup(props) {
4197
4243
  });
4198
4244
  };
4199
4245
  }, [item]);
4246
+ (0, react.useEffect)(() => {
4247
+ if (!item.children) return;
4248
+ const observables = item.children.map((child) => {
4249
+ var _child$item$hidden$, _child$item3;
4250
+ return (0, _univerjs_core.convertObservableToBehaviorSubject)((_child$item$hidden$ = (_child$item3 = child.item) === null || _child$item3 === void 0 ? void 0 : _child$item3.hidden$) !== null && _child$item$hidden$ !== void 0 ? _child$item$hidden$ : (0, rxjs.of)(false), false);
4251
+ });
4252
+ const subscription = (0, rxjs.combineLatest)(observables).subscribe((hiddenArr) => {
4253
+ const hidden = hiddenArr.map((hidden, index) => ({
4254
+ hidden,
4255
+ item: getTinyMenuChildStateKey(item.children[index])
4256
+ })).filter((hidden) => hidden.hidden);
4257
+ if (hidden.length === 0) setHiddenItems([]);
4258
+ else setHiddenItems(hidden.map((hidden) => hidden.item));
4259
+ });
4260
+ return () => {
4261
+ subscription.unsubscribe();
4262
+ observables.forEach((observable) => {
4263
+ observable.complete();
4264
+ });
4265
+ };
4266
+ }, [item]);
4267
+ const visibleChildren = (0, react.useMemo)(() => {
4268
+ var _item$children;
4269
+ return getVisibleTinyMenuChildren((_item$children = item.children) !== null && _item$children !== void 0 ? _item$children : [], [...hiddenItems, ...hiddenItemIds]);
4270
+ }, [
4271
+ hiddenItemIds,
4272
+ hiddenItems,
4273
+ item.children
4274
+ ]);
4200
4275
  if (!item.children) return null;
4201
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignTinyMenuGroup, { items: item.children.map((child) => {
4202
- var _child$item$id2, _child$item7;
4276
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignTinyMenuGroup, { items: visibleChildren.map((child) => {
4277
+ var _child$item9, _child$item10, _child$item$id3, _child$item11;
4203
4278
  return {
4204
4279
  key: child.key,
4205
4280
  onClick: () => {
4206
- var _child$item$id, _child$item2, _child$item3, _child$item4, _child$item5, _child$item6;
4281
+ var _child$item$id2, _child$item4, _child$item5, _child$item6, _child$item7, _child$item8;
4207
4282
  onOptionSelect === null || onOptionSelect === void 0 || onOptionSelect({
4208
- label: (_child$item$id = (_child$item2 = child.item) === null || _child$item2 === void 0 ? void 0 : _child$item2.id) !== null && _child$item$id !== void 0 ? _child$item$id : child.key,
4209
- commandId: (_child$item3 = child.item) === null || _child$item3 === void 0 ? void 0 : _child$item3.commandId,
4210
- id: (_child$item4 = child.item) === null || _child$item4 === void 0 ? void 0 : _child$item4.id,
4211
- tooltip: ((_child$item5 = child.item) === null || _child$item5 === void 0 ? void 0 : _child$item5.tooltip) && localeService.t((_child$item6 = child.item) === null || _child$item6 === void 0 ? void 0 : _child$item6.tooltip)
4283
+ label: (_child$item$id2 = (_child$item4 = child.item) === null || _child$item4 === void 0 ? void 0 : _child$item4.id) !== null && _child$item$id2 !== void 0 ? _child$item$id2 : child.key,
4284
+ commandId: (_child$item5 = child.item) === null || _child$item5 === void 0 ? void 0 : _child$item5.commandId,
4285
+ id: (_child$item6 = child.item) === null || _child$item6 === void 0 ? void 0 : _child$item6.id,
4286
+ tooltip: ((_child$item7 = child.item) === null || _child$item7 === void 0 ? void 0 : _child$item7.tooltip) && localeService.t((_child$item8 = child.item) === null || _child$item8 === void 0 ? void 0 : _child$item8.tooltip)
4212
4287
  });
4213
4288
  },
4214
4289
  className: "",
4290
+ iconClassName: ((_child$item9 = child.item) === null || _child$item9 === void 0 ? void 0 : _child$item9.icon) === "TextTypeIcon" ? "!univer-size-3.5" : void 0,
4215
4291
  Icon: componentManager.get(child.item.icon),
4216
- active: activeItems.includes((_child$item$id2 = (_child$item7 = child.item) === null || _child$item7 === void 0 ? void 0 : _child$item7.id) !== null && _child$item$id2 !== void 0 ? _child$item$id2 : "")
4292
+ active: resolveMenuItemActiveState((_child$item10 = child.item) === null || _child$item10 === void 0 ? void 0 : _child$item10.id, activeItems.includes((_child$item$id3 = (_child$item11 = child.item) === null || _child$item11 === void 0 ? void 0 : _child$item11.id) !== null && _child$item$id3 !== void 0 ? _child$item$id3 : ""), activeItemIds)
4217
4293
  };
4218
4294
  }) });
4219
4295
  }
4220
4296
  function UIQuickTileMenuGroup(props) {
4221
- var _item$children;
4222
- const { item, onOptionSelect } = props;
4223
- if (!((_item$children = item.children) === null || _item$children === void 0 ? void 0 : _item$children.length)) return null;
4297
+ var _item$children2;
4298
+ const { item, activeItemIds, hiddenItemIds = EMPTY_HIDDEN_ITEM_IDS, onOptionSelect } = props;
4299
+ if (!((_item$children2 = item.children) === null || _item$children2 === void 0 ? void 0 : _item$children2.length)) return null;
4224
4300
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4225
4301
  className: "univer-item-center univer-grid univer-grid-cols-3 univer-gap-1.5 univer-py-1",
4226
- children: item.children.map((menuSchema) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuickTileMenuItem, {
4302
+ children: getVisibleTinyMenuChildren(item.children, hiddenItemIds).map((menuSchema) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(QuickTileMenuItem, {
4227
4303
  menuSchema,
4304
+ activeItemIds,
4228
4305
  onOptionSelect
4229
4306
  }, menuSchema.key))
4230
4307
  });
@@ -4236,6 +4313,7 @@ const contentClassName = "univer-inline-flex univer-items-center univer-gap-2";
4236
4313
  const menuViewportPadding = 8;
4237
4314
  const submenuOverlapOffset = 2;
4238
4315
  const submenuVisualGap = 20;
4316
+ const CONTEXT_MENU_SUBMENU_CLOSE_DELAY = 500;
4239
4317
  const CONTEXT_MENU_SUBMENU_PORTAL_ATTR = "data-u-context-menu-submenu";
4240
4318
  function isNonSelectableLabel(label) {
4241
4319
  return typeof label === "object" && (label === null || label === void 0 ? void 0 : label.selectable) === false;
@@ -4243,9 +4321,15 @@ function isNonSelectableLabel(label) {
4243
4321
  function isNonHoverableLabel(label) {
4244
4322
  return typeof label === "object" && (label === null || label === void 0 ? void 0 : label.hoverable) === false;
4245
4323
  }
4324
+ function hasRenderableContextMenuSchema(menuSchema) {
4325
+ var _menuSchema$children;
4326
+ if (menuSchema.item) return true;
4327
+ if (!((_menuSchema$children = menuSchema.children) === null || _menuSchema$children === void 0 ? void 0 : _menuSchema$children.length)) return false;
4328
+ return menuSchema.children.some((childSchema) => Boolean(childSchema.item));
4329
+ }
4246
4330
  function ContextMenuPanel(props) {
4247
4331
  var _layoutService$rootCo, _layoutService$rootCo2;
4248
- const { menuType, menuSessionVersion = 0, className, onOptionSelect } = props;
4332
+ const { menuType, menuSessionVersion = 0, className, activeItemIds, hiddenItemIds, onOptionSelect } = props;
4249
4333
  const menuManagerService = (0, _wendellhu_redi_react_bindings.useDependency)(IMenuManagerService);
4250
4334
  const layoutService = (0, _wendellhu_redi_react_bindings.useDependency)(ILayoutService);
4251
4335
  const [menuElement, setMenuElement] = (0, react.useState)(null);
@@ -4289,23 +4373,26 @@ function ContextMenuPanel(props) {
4289
4373
  menuSchemas: menuItems,
4290
4374
  menuSessionVersion,
4291
4375
  submenuPortalContainer,
4376
+ activeItemIds,
4377
+ hiddenItemIds,
4292
4378
  onOptionSelect,
4293
4379
  maxMenuHeight
4294
4380
  })
4295
4381
  });
4296
4382
  }
4297
4383
  function ContextMenuMenu(props) {
4298
- const { menuSchemas, menuSessionVersion, submenuPortalContainer, onOptionSelect, maxMenuHeight } = props;
4384
+ const { menuSchemas, menuSessionVersion, submenuPortalContainer, activeItemIds, hiddenItemIds, onOptionSelect, maxMenuHeight } = props;
4299
4385
  const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
4300
4386
  const hiddenGroupStates = useContextGroupHiddenStates$1(menuSchemas);
4301
4387
  const visibleSchemas = (0, react.useMemo)(() => {
4302
4388
  return menuSchemas.filter((item) => {
4389
+ if (!hasRenderableContextMenuSchema(item)) return false;
4303
4390
  if (!item.children) return true;
4304
4391
  return !hiddenGroupStates[item.key];
4305
4392
  });
4306
4393
  }, [hiddenGroupStates, menuSchemas]);
4307
4394
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: visibleSchemas.map((menuSchema, index) => {
4308
- var _menuSchema$children;
4395
+ var _menuSchema$children2;
4309
4396
  const hasSeparator = index !== visibleSchemas.length - 1;
4310
4397
  if (menuSchema.item) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContextMenuMenuItem, {
4311
4398
  menuKey: menuSchema.key,
@@ -4313,19 +4400,38 @@ function ContextMenuMenu(props) {
4313
4400
  menuSessionVersion,
4314
4401
  submenuPortalContainer,
4315
4402
  onOptionSelect,
4316
- maxMenuHeight
4403
+ maxMenuHeight,
4404
+ hiddenItemIds
4317
4405
  }, menuSchema.key);
4318
- if (!((_menuSchema$children = menuSchema.children) === null || _menuSchema$children === void 0 ? void 0 : _menuSchema$children.length)) return null;
4406
+ if (!((_menuSchema$children2 = menuSchema.children) === null || _menuSchema$children2 === void 0 ? void 0 : _menuSchema$children2.length)) return null;
4319
4407
  if (menuSchema.quickLayout) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4320
4408
  className: (0, _univerjs_design.clsx)("univer-py-1", hasSeparator && _univerjs_design.borderBottomClassName),
4321
4409
  children: menuSchema.quickLayout === "tile" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UIQuickTileMenuGroup, {
4322
4410
  item: menuSchema,
4411
+ activeItemIds,
4412
+ hiddenItemIds,
4323
4413
  onOptionSelect
4324
4414
  }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UITinyMenuGroup, {
4325
4415
  item: menuSchema,
4416
+ activeItemIds,
4417
+ hiddenItemIds,
4326
4418
  onOptionSelect
4327
4419
  })
4328
4420
  }, menuSchema.key);
4421
+ if (menuSchema.tiny) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4422
+ className: (0, _univerjs_design.clsx)("univer-flex univer-items-center univer-gap-1 univer-py-1", hasSeparator && _univerjs_design.borderBottomClassName),
4423
+ children: menuSchema.children.map((childSchema) => childSchema.item && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ContextMenuMenuItem, {
4424
+ menuKey: childSchema.key,
4425
+ menuItem: childSchema.item,
4426
+ menuSessionVersion,
4427
+ submenuPortalContainer,
4428
+ activeItemIds,
4429
+ hiddenItemIds,
4430
+ onOptionSelect,
4431
+ maxMenuHeight,
4432
+ compact: true
4433
+ }, childSchema.key))
4434
+ }, menuSchema.key);
4329
4435
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4330
4436
  className: (0, _univerjs_design.clsx)("univer-grid univer-gap-1 univer-py-1", hasSeparator && _univerjs_design.borderBottomClassName),
4331
4437
  children: [menuSchema.title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", {
@@ -4336,6 +4442,8 @@ function ContextMenuMenu(props) {
4336
4442
  menuItem: childSchema.item,
4337
4443
  menuSessionVersion,
4338
4444
  submenuPortalContainer,
4445
+ activeItemIds,
4446
+ hiddenItemIds,
4339
4447
  onOptionSelect,
4340
4448
  maxMenuHeight
4341
4449
  }, childSchema.key))]
@@ -4343,8 +4451,9 @@ function ContextMenuMenu(props) {
4343
4451
  }) });
4344
4452
  }
4345
4453
  function ContextMenuMenuItem(props) {
4346
- const { menuKey, menuItem, menuSessionVersion, submenuPortalContainer, onOptionSelect, maxMenuHeight } = props;
4347
- const direction = (0, _wendellhu_redi_react_bindings.useObservable)((0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService).direction$);
4454
+ const { menuKey, menuItem, menuSessionVersion, submenuPortalContainer, activeItemIds, hiddenItemIds = [], compact = false, onOptionSelect, maxMenuHeight } = props;
4455
+ const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
4456
+ const direction = (0, _wendellhu_redi_react_bindings.useObservable)(localeService.direction$);
4348
4457
  const menuManagerService = (0, _wendellhu_redi_react_bindings.useDependency)(IMenuManagerService);
4349
4458
  const disabled = (0, _wendellhu_redi_react_bindings.useObservable)(menuItem.disabled$, false);
4350
4459
  const activated = (0, _wendellhu_redi_react_bindings.useObservable)(menuItem.activated$, false);
@@ -4362,6 +4471,7 @@ function ContextMenuMenuItem(props) {
4362
4471
  const [submenuPlacement, setSubmenuPlacement] = (0, react.useState)("right");
4363
4472
  const menuItemElementRef = (0, react.useRef)(null);
4364
4473
  const submenuElementRef = (0, react.useRef)(null);
4474
+ const submenuCloseTimerRef = (0, react.useRef)(null);
4365
4475
  const selections = (0, react.useMemo)(() => {
4366
4476
  if (menuItem.type !== 1 && menuItem.type !== 2) return [];
4367
4477
  if (selectionsFromObservable) return selectionsFromObservable;
@@ -4383,9 +4493,23 @@ function ContextMenuMenuItem(props) {
4383
4493
  const hasSelectionSubmenu = selections.length > 0;
4384
4494
  const hasSubItemSubmenu = subMenuItems.length > 0;
4385
4495
  const hasSubmenu = hasSelectionSubmenu || hasSubItemSubmenu;
4496
+ const selectionsCommandId = selectorItem.selectionsCommandId;
4497
+ const clearSubmenuCloseTimer = (0, react.useCallback)(() => {
4498
+ if (submenuCloseTimerRef.current == null) return;
4499
+ clearTimeout(submenuCloseTimerRef.current);
4500
+ submenuCloseTimerRef.current = null;
4501
+ }, []);
4502
+ const scheduleSubmenuClose = (0, react.useCallback)(() => {
4503
+ clearSubmenuCloseTimer();
4504
+ submenuCloseTimerRef.current = setTimeout(() => {
4505
+ submenuCloseTimerRef.current = null;
4506
+ setSubmenuVisible(false);
4507
+ }, 500);
4508
+ }, [clearSubmenuCloseTimer]);
4386
4509
  (0, react.useEffect)(() => {
4387
4510
  setInputValue(value);
4388
4511
  }, [value]);
4512
+ (0, react.useEffect)(() => () => clearSubmenuCloseTimer(), [clearSubmenuCloseTimer]);
4389
4513
  (0, react.useEffect)(() => {
4390
4514
  if (!submenuVisible) {
4391
4515
  setSubmenuPositionReady(false);
@@ -4422,19 +4546,30 @@ function ContextMenuMenuItem(props) {
4422
4546
  hasSelectionSubmenu,
4423
4547
  hasSubItemSubmenu
4424
4548
  ]);
4425
- if (hidden) return null;
4549
+ const hiddenById = menuItem.id != null && hiddenItemIds.includes(menuItem.id) || hiddenItemIds.includes(menuKey);
4550
+ if (hidden || hiddenById) return null;
4426
4551
  const onChange = (v) => {
4427
4552
  setInputValue((0, _univerjs_core.isRealNum)(v) && typeof v === "string" ? Number.parseInt(v) : v);
4428
4553
  };
4429
4554
  const onSubmenuOptionSelect = (option) => {
4430
4555
  onOptionSelect === null || onOptionSelect === void 0 || onOptionSelect(option);
4556
+ clearSubmenuCloseTimer();
4431
4557
  setSubmenuVisible(false);
4432
4558
  };
4433
- const itemClassName = (0, _univerjs_design.clsx)("univer-relative univer-flex univer-min-h-8 univer-w-full univer-items-center univer-justify-between univer-gap-3 univer-rounded-md univer-border-none univer-bg-transparent univer-px-2 univer-text-left univer-text-sm dark:!univer-text-white", disabled ? "univer-cursor-not-allowed univer-opacity-60" : `
4559
+ const itemClassName = (0, _univerjs_design.clsx)(compact ? `
4560
+ univer-relative univer-flex univer-size-8 univer-items-center univer-justify-center univer-rounded-md
4561
+ univer-border-none univer-bg-transparent univer-p-0 univer-text-left univer-text-sm
4562
+ dark:!univer-text-white
4563
+ ` : `
4564
+ univer-relative univer-flex univer-min-h-8 univer-w-full univer-items-center univer-justify-between
4565
+ univer-gap-3 univer-rounded-md univer-border-none univer-bg-transparent univer-px-2 univer-text-left
4566
+ univer-text-sm
4567
+ dark:!univer-text-white
4568
+ `, disabled ? "univer-cursor-not-allowed univer-opacity-60" : `
4434
4569
  univer-cursor-pointer
4435
4570
  hover:univer-bg-gray-50
4436
4571
  dark:hover:!univer-bg-gray-600
4437
- `, activated && `
4572
+ `, resolveMenuItemActiveState(menuItem.id, activated, activeItemIds) && `
4438
4573
  univer-bg-gray-200
4439
4574
  dark:!univer-bg-gray-600
4440
4575
  `);
@@ -4442,7 +4577,7 @@ function ContextMenuMenuItem(props) {
4442
4577
  className: contentClassName,
4443
4578
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomLabel, {
4444
4579
  value: inputValue,
4445
- title: menuItem.title,
4580
+ title: compact ? void 0 : menuItem.title,
4446
4581
  label: menuItem.label,
4447
4582
  icon: menuItem.icon,
4448
4583
  onChange
@@ -4458,6 +4593,7 @@ function ContextMenuMenuItem(props) {
4458
4593
  ref: menuItemElementRef,
4459
4594
  className: "univer-relative",
4460
4595
  onMouseEnter: () => {
4596
+ clearSubmenuCloseTimer();
4461
4597
  if (hasSubmenu && !disabled) {
4462
4598
  setSubmenuPositionReady(false);
4463
4599
  setSubmenuVisible(true);
@@ -4468,7 +4604,7 @@ function ContextMenuMenuItem(props) {
4468
4604
  var _submenuElementRef$cu;
4469
4605
  const nextTarget = event.relatedTarget;
4470
4606
  if (nextTarget && ((_submenuElementRef$cu = submenuElementRef.current) === null || _submenuElementRef$cu === void 0 ? void 0 : _submenuElementRef$cu.contains(nextTarget))) return;
4471
- setSubmenuVisible(false);
4607
+ scheduleSubmenuClose();
4472
4608
  }
4473
4609
  },
4474
4610
  children: [renderAsContainer ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -4479,8 +4615,21 @@ function ContextMenuMenuItem(props) {
4479
4615
  type: "button",
4480
4616
  className: interactiveItemClassName,
4481
4617
  disabled,
4618
+ title: compact && typeof menuItem.tooltip === "string" ? localeService.t(menuItem.tooltip) : void 0,
4482
4619
  onClick: () => {
4620
+ clearSubmenuCloseTimer();
4483
4621
  if (hasSubmenu) {
4622
+ if (canExecuteItem) {
4623
+ const item = menuItem;
4624
+ onOptionSelect === null || onOptionSelect === void 0 || onOptionSelect({
4625
+ commandId: item.commandId,
4626
+ params: item.params,
4627
+ value: inputValue,
4628
+ id: item.id,
4629
+ label: menuKey
4630
+ });
4631
+ return;
4632
+ }
4484
4633
  setSubmenuPositionReady(false);
4485
4634
  setSubmenuVisible(true);
4486
4635
  return;
@@ -4489,12 +4638,13 @@ function ContextMenuMenuItem(props) {
4489
4638
  const item = menuItem;
4490
4639
  onOptionSelect === null || onOptionSelect === void 0 || onOptionSelect({
4491
4640
  commandId: item.commandId,
4641
+ params: item.params,
4492
4642
  value: inputValue,
4493
4643
  id: item.id,
4494
4644
  label: menuKey
4495
4645
  });
4496
4646
  },
4497
- children: [contentNode, hasSubmenu && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.MoreIcon, { className: "univer-size-3.5 univer-text-gray-400 dark:!univer-text-gray-200" })]
4647
+ children: [contentNode, hasSubmenu && !compact && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.MoreIcon, { className: "univer-size-3.5 univer-text-gray-400 dark:!univer-text-gray-200" })]
4498
4648
  }), hasSubmenu && submenuVisible && (submenuPortalContainer ? (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4499
4649
  ref: submenuElementRef,
4500
4650
  dir: direction,
@@ -4510,11 +4660,12 @@ function ContextMenuMenuItem(props) {
4510
4660
  visibility: submenuPositionReady ? "visible" : "hidden",
4511
4661
  pointerEvents: submenuPositionReady ? "auto" : "none"
4512
4662
  },
4663
+ onMouseEnter: clearSubmenuCloseTimer,
4513
4664
  onMouseLeave: (event) => {
4514
4665
  var _menuItemElementRef$c;
4515
4666
  const nextTarget = event.relatedTarget;
4516
4667
  if (nextTarget && ((_menuItemElementRef$c = menuItemElementRef.current) === null || _menuItemElementRef$c === void 0 ? void 0 : _menuItemElementRef$c.contains(nextTarget))) return;
4517
- setSubmenuVisible(false);
4668
+ scheduleSubmenuClose();
4518
4669
  },
4519
4670
  onWheel: (event) => event.stopPropagation(),
4520
4671
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -4543,12 +4694,13 @@ function ContextMenuMenuItem(props) {
4543
4694
  label: option.label,
4544
4695
  icon: option.icon,
4545
4696
  onChange: (optionValue) => {
4697
+ var _option$commandId;
4546
4698
  onSubmenuOptionSelect === null || onSubmenuOptionSelect === void 0 || onSubmenuOptionSelect({
4547
4699
  ...option,
4548
4700
  value: optionValue,
4549
4701
  id: menuItem.id,
4550
4702
  label: menuKey,
4551
- commandId: option.commandId
4703
+ commandId: (_option$commandId = option.commandId) !== null && _option$commandId !== void 0 ? _option$commandId : selectionsCommandId
4552
4704
  });
4553
4705
  }
4554
4706
  })
@@ -4558,11 +4710,12 @@ function ContextMenuMenuItem(props) {
4558
4710
  className: optionClassName,
4559
4711
  disabled: option.disabled,
4560
4712
  onClick: () => {
4713
+ var _option$commandId2;
4561
4714
  onSubmenuOptionSelect === null || onSubmenuOptionSelect === void 0 || onSubmenuOptionSelect({
4562
4715
  ...option,
4563
4716
  id: menuItem.id,
4564
4717
  label: menuKey,
4565
- commandId: option.commandId
4718
+ commandId: (_option$commandId2 = option.commandId) !== null && _option$commandId2 !== void 0 ? _option$commandId2 : selectionsCommandId
4566
4719
  });
4567
4720
  },
4568
4721
  children: optionContentNode
@@ -4576,6 +4729,8 @@ function ContextMenuMenuItem(props) {
4576
4729
  menuSchemas: subMenuItems,
4577
4730
  menuSessionVersion,
4578
4731
  submenuPortalContainer,
4732
+ activeItemIds,
4733
+ hiddenItemIds,
4579
4734
  onOptionSelect: onSubmenuOptionSelect,
4580
4735
  maxMenuHeight
4581
4736
  })]
@@ -4587,8 +4742,8 @@ function useContextGroupHiddenStates$1(menuSchemas) {
4587
4742
  const [hiddenStates, setHiddenStates] = (0, react.useState)({});
4588
4743
  (0, react.useEffect)(() => {
4589
4744
  const subscriptions = menuSchemas.map((menuSchema) => {
4590
- var _menuSchema$children2;
4591
- if (!((_menuSchema$children2 = menuSchema.children) === null || _menuSchema$children2 === void 0 ? void 0 : _menuSchema$children2.length)) return null;
4745
+ var _menuSchema$children3;
4746
+ if (!((_menuSchema$children3 = menuSchema.children) === null || _menuSchema$children3 === void 0 ? void 0 : _menuSchema$children3.length)) return null;
4592
4747
  return (0, rxjs.combineLatest)(menuSchema.children.map((childSchema) => {
4593
4748
  var _childSchema$item$hid, _childSchema$item;
4594
4749
  return (_childSchema$item$hid = (_childSchema$item = childSchema.item) === null || _childSchema$item === void 0 ? void 0 : _childSchema$item.hidden$) !== null && _childSchema$item$hid !== void 0 ? _childSchema$item$hid : (0, rxjs.of)(false);
@@ -4757,7 +4912,9 @@ function DesktopContextMenu() {
4757
4912
  onRequestClose: handleClose,
4758
4913
  onOptionSelect: (params) => {
4759
4914
  const { label: id, commandId, value } = params;
4760
- if (commandService) commandService.executeCommand(commandId !== null && commandId !== void 0 ? commandId : id, { value });
4915
+ const rawParams = typeof params.params === "function" ? params.params() : params.params;
4916
+ const commandParams = typeof rawParams === "undefined" ? { value } : rawParams;
4917
+ if (commandService) commandService.executeCommand(commandId !== null && commandId !== void 0 ? commandId : id, commandParams);
4761
4918
  injector.get(ILayoutService).focus();
4762
4919
  handleClose();
4763
4920
  }
@@ -5296,7 +5453,7 @@ const IUIController = (0, _univerjs_core.createIdentifier)("univer.ui.ui-control
5296
5453
  //#endregion
5297
5454
  //#region package.json
5298
5455
  var name = "@univerjs/ui";
5299
- var version = "0.24.0";
5456
+ var version = "0.25.0";
5300
5457
 
5301
5458
  //#endregion
5302
5459
  //#region src/views/components/ribbon/MobileRibbon.tsx
@@ -5364,7 +5521,7 @@ function MobileRibbon(props) {
5364
5521
  const container = toolbarScrollRef.current;
5365
5522
  if (!container) return;
5366
5523
  container.scrollBy({
5367
- left: direction === "left" ? -toolbarScrollOffset : toolbarScrollOffset,
5524
+ left: direction === "left" ? -168 : toolbarScrollOffset,
5368
5525
  behavior: "smooth"
5369
5526
  });
5370
5527
  }
@@ -5405,7 +5562,7 @@ function MobileRibbon(props) {
5405
5562
  dark:!univer-text-gray-200
5406
5563
  `),
5407
5564
  onClick: () => selectTab(index),
5408
- children: [localeService.t(group.key), active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "\n univer-absolute univer-bottom-0 univer-left-1/2 univer-h-0.5 univer-w-8\n -univer-translate-x-1/2 univer-rounded-full univer-bg-primary-600\n dark:!univer-bg-primary-400\n " })]
5565
+ children: [localeService.t(group.title || group.key), active && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "\n univer-absolute univer-bottom-0 univer-left-1/2 univer-h-0.5 univer-w-8\n -univer-translate-x-1/2 univer-rounded-full univer-bg-primary-600\n dark:!univer-bg-primary-400\n " })]
5409
5566
  }, group.key);
5410
5567
  })
5411
5568
  }),
@@ -5826,8 +5983,8 @@ function MobileContextMenu() {
5826
5983
  }
5827
5984
  const sheetTitle = (0, react.useMemo)(() => {
5828
5985
  switch (menuType) {
5829
- case "contextMenu.rowHeader": return localeService.t("row");
5830
- case "contextMenu.colHeader": return localeService.t("column");
5986
+ case "contextMenu.rowHeader": return localeService.t("ui.row");
5987
+ case "contextMenu.colHeader": return localeService.t("ui.column");
5831
5988
  default: return "";
5832
5989
  }
5833
5990
  }, [localeService, menuType]);
@@ -5837,7 +5994,7 @@ function MobileContextMenu() {
5837
5994
  className: "univer-fixed univer-inset-0 univer-z-[1080] univer-flex univer-items-end",
5838
5995
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5839
5996
  type: "button",
5840
- "aria-label": localeService.t("rangeSelector.cancel"),
5997
+ "aria-label": localeService.t("ui.rangeSelector.cancel"),
5841
5998
  className: "univer-absolute univer-inset-0 univer-bg-[rgba(15,23,42,0.32)] univer-backdrop-blur-[2px]",
5842
5999
  onClick: handleClose
5843
6000
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
@@ -5858,7 +6015,7 @@ function MobileContextMenu() {
5858
6015
  })
5859
6016
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
5860
6017
  type: "button",
5861
- "aria-label": localeService.t("rangeSelector.cancel"),
6018
+ "aria-label": localeService.t("ui.rangeSelector.cancel"),
5862
6019
  className: "\n univer-flex univer-size-8 univer-shrink-0 univer-appearance-none univer-items-center\n univer-justify-center univer-rounded-full univer-border-0 univer-bg-white univer-p-0\n univer-leading-none univer-text-gray-600 univer-shadow-sm univer-outline-none\n univer-ring-0 univer-transition-colors\n hover:univer-bg-gray-100\n active:univer-bg-gray-200\n ",
5863
6020
  style: { margin: 0 },
5864
6021
  onClick: handleClose,
@@ -6084,13 +6241,40 @@ const INotificationService = (0, _univerjs_core.createIdentifier)("ui.notificati
6084
6241
  //#endregion
6085
6242
  //#region src/services/before-close/before-close.service.ts
6086
6243
  const IBeforeCloseService = (0, _univerjs_core.createIdentifier)("univer.ui.before-close-service");
6087
- let DesktopBeforeCloseService = class DesktopBeforeCloseService {
6244
+ let DesktopBeforeCloseService = class DesktopBeforeCloseService extends _univerjs_core.Disposable {
6088
6245
  constructor(_notificationService) {
6246
+ super();
6089
6247
  this._notificationService = _notificationService;
6090
6248
  _defineProperty(this, "_beforeUnloadCallbacks", []);
6091
6249
  _defineProperty(this, "_onCloseCallbacks", []);
6250
+ _defineProperty(this, "_beforeUnloadHandler", void 0);
6251
+ _defineProperty(this, "_unloadHandler", void 0);
6252
+ this._beforeUnloadHandler = (_event) => {
6253
+ let event = _event;
6254
+ const message = this._beforeUnloadCallbacks.map((callback) => callback()).filter((m) => !!m).join("\n");
6255
+ if (message) {
6256
+ this._notificationService.show({
6257
+ type: "error",
6258
+ title: "Some changes are not saved",
6259
+ content: message
6260
+ });
6261
+ if (typeof event === "undefined") event = window.event;
6262
+ event.returnValue = message;
6263
+ return message;
6264
+ }
6265
+ };
6266
+ this._unloadHandler = () => {
6267
+ this._onCloseCallbacks.forEach((callback) => callback());
6268
+ };
6092
6269
  this._init();
6093
6270
  }
6271
+ dispose() {
6272
+ window.removeEventListener("beforeunload", this._beforeUnloadHandler);
6273
+ window.removeEventListener("unload", this._unloadHandler);
6274
+ this._beforeUnloadCallbacks = [];
6275
+ this._onCloseCallbacks = [];
6276
+ super.dispose();
6277
+ }
6094
6278
  registerBeforeClose(callback) {
6095
6279
  this._beforeUnloadCallbacks.push(callback);
6096
6280
  return { dispose: () => {
@@ -6104,23 +6288,8 @@ let DesktopBeforeCloseService = class DesktopBeforeCloseService {
6104
6288
  } };
6105
6289
  }
6106
6290
  _init() {
6107
- window.addEventListener("beforeunload", (_event) => {
6108
- let event = _event;
6109
- const message = this._beforeUnloadCallbacks.map((callback) => callback()).filter((m) => !!m).join("\n");
6110
- if (message) {
6111
- this._notificationService.show({
6112
- type: "error",
6113
- title: "Some changes are not saved",
6114
- content: message
6115
- });
6116
- if (typeof event === "undefined") event = window.event;
6117
- event.returnValue = message;
6118
- return message;
6119
- }
6120
- });
6121
- window.addEventListener("unload", () => {
6122
- this._onCloseCallbacks.forEach((callback) => callback());
6123
- });
6291
+ window.addEventListener("beforeunload", this._beforeUnloadHandler);
6292
+ window.addEventListener("unload", this._unloadHandler);
6124
6293
  }
6125
6294
  };
6126
6295
  DesktopBeforeCloseService = __decorate([__decorateParam(0, INotificationService)], DesktopBeforeCloseService);
@@ -6308,14 +6477,25 @@ let BrowserClipboardService = class BrowserClipboardService extends _univerjs_co
6308
6477
  this._logService = _logService;
6309
6478
  this._notificationService = _notificationService;
6310
6479
  }
6311
- async write(text, html) {
6312
- if (!this.supportClipboard) return this._legacyCopyHtml(html);
6480
+ async write(text, html, customData) {
6481
+ if (!this.supportClipboard) return this._legacyCopyHtml(text, html);
6313
6482
  try {
6314
6483
  return await navigator.clipboard.write([new ClipboardItem({
6315
6484
  [PLAIN_TEXT_CLIPBOARD_MIME_TYPE]: new Blob([text], { type: PLAIN_TEXT_CLIPBOARD_MIME_TYPE }),
6316
- [HTML_CLIPBOARD_MIME_TYPE]: new Blob([html], { type: HTML_CLIPBOARD_MIME_TYPE })
6485
+ [HTML_CLIPBOARD_MIME_TYPE]: new Blob([html], { type: HTML_CLIPBOARD_MIME_TYPE }),
6486
+ ...Object.fromEntries(Object.entries(customData !== null && customData !== void 0 ? customData : {}).map(([type, value]) => [type, new Blob([value], { type })]))
6317
6487
  })]);
6318
6488
  } catch (error) {
6489
+ if (customData && Object.keys(customData).length) try {
6490
+ return await navigator.clipboard.write([new ClipboardItem({
6491
+ [PLAIN_TEXT_CLIPBOARD_MIME_TYPE]: new Blob([text], { type: PLAIN_TEXT_CLIPBOARD_MIME_TYPE }),
6492
+ [HTML_CLIPBOARD_MIME_TYPE]: new Blob([html], { type: HTML_CLIPBOARD_MIME_TYPE })
6493
+ })]);
6494
+ } catch (fallbackError) {
6495
+ this._logService.error("[BrowserClipboardService]", fallbackError);
6496
+ this._showClipboardAuthenticationNotification();
6497
+ return;
6498
+ }
6319
6499
  this._logService.error("[BrowserClipboardService]", error);
6320
6500
  this._showClipboardAuthenticationNotification();
6321
6501
  }
@@ -6349,17 +6529,34 @@ let BrowserClipboardService = class BrowserClipboardService extends _univerjs_co
6349
6529
  return "";
6350
6530
  }
6351
6531
  }
6352
- _legacyCopyHtml(html) {
6532
+ _legacyCopyHtml(text, html) {
6353
6533
  const activeElement = document.activeElement;
6354
- const container = createCopyHtmlContainer();
6355
- document.body.appendChild(container);
6356
- container.replaceChildren(sanitizeHtmlForClipboard(html));
6534
+ const sanitizedHtml = serializeSanitizedHtmlForClipboard(html);
6535
+ let handledByClipboardEvent = false;
6536
+ const onCopy = (event) => {
6537
+ if (!event.clipboardData) return;
6538
+ event.preventDefault();
6539
+ event.clipboardData.setData(PLAIN_TEXT_CLIPBOARD_MIME_TYPE, text);
6540
+ event.clipboardData.setData(HTML_CLIPBOARD_MIME_TYPE, sanitizedHtml);
6541
+ handledByClipboardEvent = true;
6542
+ };
6543
+ document.addEventListener("copy", onCopy);
6357
6544
  try {
6358
- select(container);
6359
6545
  document.execCommand("copy");
6546
+ if (!handledByClipboardEvent) {
6547
+ const container = createCopyHtmlContainer();
6548
+ document.body.appendChild(container);
6549
+ container.innerHTML = sanitizedHtml;
6550
+ try {
6551
+ select(container);
6552
+ document.execCommand("copy");
6553
+ } finally {
6554
+ document.body.removeChild(container);
6555
+ }
6556
+ }
6360
6557
  } finally {
6558
+ document.removeEventListener("copy", onCopy);
6361
6559
  if (activeElement instanceof HTMLElement) activeElement.focus();
6362
- document.body.removeChild(container);
6363
6560
  }
6364
6561
  }
6365
6562
  _legacyCopyText(text) {
@@ -6379,8 +6576,8 @@ let BrowserClipboardService = class BrowserClipboardService extends _univerjs_co
6379
6576
  var _this$_notificationSe;
6380
6577
  (_this$_notificationSe = this._notificationService) === null || _this$_notificationSe === void 0 || _this$_notificationSe.show({
6381
6578
  type: "warning",
6382
- title: this._localeService.t("clipboard.authentication.title"),
6383
- content: this._localeService.t("clipboard.authentication.content")
6579
+ title: this._localeService.t("ui.clipboard.authentication.title"),
6580
+ content: this._localeService.t("ui.clipboard.authentication.content")
6384
6581
  });
6385
6582
  }
6386
6583
  };
@@ -6417,6 +6614,11 @@ function sanitizeHtmlForClipboard(html) {
6417
6614
  });
6418
6615
  return fragment;
6419
6616
  }
6617
+ function serializeSanitizedHtmlForClipboard(html) {
6618
+ const container = document.createElement("div");
6619
+ container.appendChild(sanitizeHtmlForClipboard(html));
6620
+ return container.innerHTML;
6621
+ }
6420
6622
  function sanitizeHtmlNode(node) {
6421
6623
  if (node.nodeType === Node.TEXT_NODE) {
6422
6624
  var _node$textContent;
@@ -8219,7 +8421,6 @@ exports.parseHtmlFragment = parseHtmlFragment;
8219
8421
  exports.sanitizeParsedHtml = sanitizeParsedHtml;
8220
8422
  exports.splitSpanText = splitSpanText;
8221
8423
  exports.supportClipboardAPI = supportClipboardAPI;
8222
- exports.t = t;
8223
8424
  exports.textTrim = textTrim;
8224
8425
  exports.useClickOutSide = useClickOutSide;
8225
8426
  exports.useComponentsOfPart = useComponentsOfPart;