@univerjs/ui 1.0.0-rc.0 → 1.0.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 (111) hide show
  1. package/README.md +16 -0
  2. package/lib/cjs/facade.js +12 -6
  3. package/lib/cjs/index.js +1820 -635
  4. package/lib/cjs/locale/ar-SA.js +2 -1
  5. package/lib/cjs/locale/ca-ES.js +2 -1
  6. package/lib/cjs/locale/de-DE.js +2 -1
  7. package/lib/cjs/locale/en-US.js +2 -1
  8. package/lib/cjs/locale/es-ES.js +2 -1
  9. package/lib/cjs/locale/fa-IR.js +2 -1
  10. package/lib/cjs/locale/fr-FR.js +2 -1
  11. package/lib/cjs/locale/id-ID.js +2 -1
  12. package/lib/cjs/locale/it-IT.js +2 -1
  13. package/lib/cjs/locale/ja-JP.js +2 -1
  14. package/lib/cjs/locale/ko-KR.js +2 -1
  15. package/lib/cjs/locale/pl-PL.js +2 -1
  16. package/lib/cjs/locale/pt-BR.js +2 -1
  17. package/lib/cjs/locale/ru-RU.js +2 -1
  18. package/lib/cjs/locale/sk-SK.js +2 -1
  19. package/lib/cjs/locale/vi-VN.js +2 -1
  20. package/lib/cjs/locale/zh-CN.js +2 -1
  21. package/lib/cjs/locale/zh-HK.js +2 -1
  22. package/lib/cjs/locale/zh-TW.js +2 -1
  23. package/lib/es/facade.js +12 -6
  24. package/lib/es/index.js +1815 -638
  25. package/lib/es/locale/ar-SA.js +2 -0
  26. package/lib/es/locale/ca-ES.js +2 -0
  27. package/lib/es/locale/de-DE.js +2 -0
  28. package/lib/es/locale/en-US.js +2 -0
  29. package/lib/es/locale/es-ES.js +2 -0
  30. package/lib/es/locale/fa-IR.js +2 -0
  31. package/lib/es/locale/fr-FR.js +2 -0
  32. package/lib/es/locale/id-ID.js +2 -0
  33. package/lib/es/locale/it-IT.js +2 -0
  34. package/lib/es/locale/ja-JP.js +2 -0
  35. package/lib/es/locale/ko-KR.js +2 -0
  36. package/lib/es/locale/pl-PL.js +2 -0
  37. package/lib/es/locale/pt-BR.js +2 -0
  38. package/lib/es/locale/ru-RU.js +2 -0
  39. package/lib/es/locale/sk-SK.js +2 -0
  40. package/lib/es/locale/vi-VN.js +2 -0
  41. package/lib/es/locale/zh-CN.js +2 -0
  42. package/lib/es/locale/zh-HK.js +2 -0
  43. package/lib/es/locale/zh-TW.js +2 -0
  44. package/lib/facade.js +12 -6
  45. package/lib/index.css +102 -34
  46. package/lib/index.js +1815 -638
  47. package/lib/locale/ar-SA.js +2 -0
  48. package/lib/locale/ca-ES.js +2 -0
  49. package/lib/locale/de-DE.js +2 -0
  50. package/lib/locale/en-US.js +2 -0
  51. package/lib/locale/es-ES.js +2 -0
  52. package/lib/locale/fa-IR.js +2 -0
  53. package/lib/locale/fr-FR.js +2 -0
  54. package/lib/locale/id-ID.js +2 -0
  55. package/lib/locale/it-IT.js +2 -0
  56. package/lib/locale/ja-JP.js +2 -0
  57. package/lib/locale/ko-KR.js +2 -0
  58. package/lib/locale/pl-PL.js +2 -0
  59. package/lib/locale/pt-BR.js +2 -0
  60. package/lib/locale/ru-RU.js +2 -0
  61. package/lib/locale/sk-SK.js +2 -0
  62. package/lib/locale/vi-VN.js +2 -0
  63. package/lib/locale/zh-CN.js +2 -0
  64. package/lib/locale/zh-HK.js +2 -0
  65. package/lib/locale/zh-TW.js +2 -0
  66. package/lib/types/controllers/format-painter.controller.d.ts +25 -0
  67. package/lib/types/facade/f-menu-builder.d.ts +14 -1
  68. package/lib/types/facade/f-univer.d.ts +30 -5
  69. package/lib/types/index.d.ts +10 -0
  70. package/lib/types/locale/en-US.d.ts +2 -0
  71. package/lib/types/menu/format-painter.menu.d.ts +19 -0
  72. package/lib/types/services/contextmenu/contextmenu.service.d.ts +1 -0
  73. package/lib/types/services/format-painter/format-painter-canvas.d.ts +28 -0
  74. package/lib/types/services/format-painter/format-painter-session.service.d.ts +61 -0
  75. package/lib/types/services/menu/menu-manager.service.d.ts +13 -1
  76. package/lib/types/services/menu/menu.d.ts +6 -0
  77. package/lib/types/utils/mobile-canvas-gesture.d.ts +50 -0
  78. package/lib/types/views/components/context-menu/MobileContextMenu.d.ts +6 -0
  79. package/lib/types/views/components/dialog-part/MobileDialogPart.d.ts +5 -0
  80. package/lib/types/views/components/mobile-drawer/MobileDrawer.d.ts +2 -0
  81. package/lib/types/views/components/mobile-zoom-indicator/mobile-zoom-indicator.d.ts +26 -0
  82. package/lib/types/views/components/ribbon/ToolbarButton.d.ts +1 -1
  83. package/lib/types/views/components/sidebar/MobileSidebar.d.ts +5 -0
  84. package/lib/types/views/emoji-picker/emoji-picker-utils.d.ts +1 -1
  85. package/lib/types/views/font-family/MobileFontFamilyDropdown.d.ts +17 -0
  86. package/lib/types/views/menu/mobile/MobileMenu.d.ts +1 -1
  87. package/lib/types/views/mobile-workbench/MobileCanvasLayout.d.ts +42 -0
  88. package/lib/types/views/mobile-workbench/MobileWorkbench.d.ts +2 -0
  89. package/lib/types/views/notification/Notification.d.ts +6 -1
  90. package/lib/umd/facade.js +1 -1
  91. package/lib/umd/index.js +34 -16
  92. package/lib/umd/locale/ar-SA.js +1 -1
  93. package/lib/umd/locale/ca-ES.js +1 -1
  94. package/lib/umd/locale/de-DE.js +1 -1
  95. package/lib/umd/locale/en-US.js +1 -1
  96. package/lib/umd/locale/es-ES.js +1 -1
  97. package/lib/umd/locale/fa-IR.js +1 -1
  98. package/lib/umd/locale/fr-FR.js +1 -1
  99. package/lib/umd/locale/id-ID.js +1 -1
  100. package/lib/umd/locale/it-IT.js +1 -1
  101. package/lib/umd/locale/ja-JP.js +1 -1
  102. package/lib/umd/locale/ko-KR.js +1 -1
  103. package/lib/umd/locale/pl-PL.js +1 -1
  104. package/lib/umd/locale/pt-BR.js +1 -1
  105. package/lib/umd/locale/ru-RU.js +1 -1
  106. package/lib/umd/locale/sk-SK.js +1 -1
  107. package/lib/umd/locale/vi-VN.js +1 -1
  108. package/lib/umd/locale/zh-CN.js +1 -1
  109. package/lib/umd/locale/zh-HK.js +1 -1
  110. package/lib/umd/locale/zh-TW.js +1 -1
  111. package/package.json +12 -12
package/lib/cjs/index.js CHANGED
@@ -56,7 +56,7 @@ function getAttributeValue(target, name) {
56
56
  }
57
57
 
58
58
  //#endregion
59
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/typeof.js
59
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/typeof.js
60
60
  function _typeof(o) {
61
61
  "@babel/helpers - typeof";
62
62
  return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
@@ -67,7 +67,7 @@ function _typeof(o) {
67
67
  }
68
68
 
69
69
  //#endregion
70
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/toPrimitive.js
70
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPrimitive.js
71
71
  function toPrimitive(t, r) {
72
72
  if ("object" != _typeof(t) || !t) return t;
73
73
  var e = t[Symbol.toPrimitive];
@@ -80,14 +80,14 @@ function toPrimitive(t, r) {
80
80
  }
81
81
 
82
82
  //#endregion
83
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/toPropertyKey.js
83
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/toPropertyKey.js
84
84
  function toPropertyKey(t) {
85
85
  var i = toPrimitive(t, "string");
86
86
  return "symbol" == _typeof(i) ? i : i + "";
87
87
  }
88
88
 
89
89
  //#endregion
90
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/defineProperty.js
90
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/defineProperty.js
91
91
  function _defineProperty(e, r, t) {
92
92
  return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
93
93
  value: t,
@@ -98,7 +98,7 @@ function _defineProperty(e, r, t) {
98
98
  }
99
99
 
100
100
  //#endregion
101
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/decorateParam.js
101
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorateParam.js
102
102
  function __decorateParam(paramIndex, decorator) {
103
103
  return function(target, key) {
104
104
  decorator(target, key, paramIndex);
@@ -106,7 +106,7 @@ function __decorateParam(paramIndex, decorator) {
106
106
  }
107
107
 
108
108
  //#endregion
109
- //#region \0@oxc-project+runtime@0.140.0/helpers/esm/decorate.js
109
+ //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorate.js
110
110
  function __decorate(decorators, target, key, desc) {
111
111
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
112
112
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -524,10 +524,12 @@ function mergeMenuConfigs(baseConfig, additionalConfig) {
524
524
  return baseConfig;
525
525
  }
526
526
  function updateReactiveProperty(baseConfig, key, value) {
527
- if (value !== void 0) if (baseConfig[key]) baseConfig[key] = baseConfig[key].pipe((0, rxjs.switchMap)(() => new rxjs.BehaviorSubject(value)));
528
- else baseConfig[key] = new rxjs.Observable((subscriber) => {
529
- subscriber.next(value);
530
- });
527
+ if (value !== void 0) {
528
+ if (baseConfig[key]) baseConfig[key] = baseConfig[key].pipe((0, rxjs.switchMap)(() => new rxjs.BehaviorSubject(value)));
529
+ else baseConfig[key] = new rxjs.Observable((subscriber) => {
530
+ subscriber.next(value);
531
+ });
532
+ }
531
533
  }
532
534
 
533
535
  //#endregion
@@ -673,21 +675,6 @@ const IMessageService = (0, _univerjs_core.createIdentifier)("ui.message.service
673
675
 
674
676
  //#endregion
675
677
  //#region src/controllers/error/error.controller.ts
676
- /**
677
- * Copyright 2023-present DreamNum Co., Ltd.
678
- *
679
- * Licensed under the Apache License, Version 2.0 (the "License");
680
- * you may not use this file except in compliance with the License.
681
- * You may obtain a copy of the License at
682
- *
683
- * http://www.apache.org/licenses/LICENSE-2.0
684
- *
685
- * Unless required by applicable law or agreed to in writing, software
686
- * distributed under the License is distributed on an "AS IS" BASIS,
687
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
688
- * See the License for the specific language governing permissions and
689
- * limitations under the License.
690
- */
691
678
  const PERMISSION_MESSAGE_ID = "ui.permission-denied";
692
679
  const PERMISSION_MESSAGE_DURATION = 3e3;
693
680
  let ErrorController = class ErrorController extends _univerjs_core.Disposable {
@@ -1104,7 +1091,7 @@ let ShortcutService = class ShortcutService extends _univerjs_core.Disposable {
1104
1091
  }
1105
1092
  dispatch(e) {
1106
1093
  if (e.isComposing) return;
1107
- if ((e.keyCode === 8 || e.keyCode === 46) && e.target instanceof HTMLInputElement && e.target.closest("[data-u-command]")) return;
1094
+ if (e.target instanceof HTMLInputElement && e.target.closest("[data-u-command]")) return;
1108
1095
  if (!e.ctrlKey && !e.metaKey && !e.altKey && MENU_NAVIGATION_KEYS.has(e.keyCode) && e.target instanceof HTMLElement && (e.target.matches("button[data-u-command], [data-u-command][role=\"button\"], [data-embed-floating-menu=\"true\"] button, [data-u-command] input") || e.target.closest("[role=\"menu\"]"))) return;
1109
1096
  if (this._forceEscapeCount > 0 || this._forceDisabled) return;
1110
1097
  if (this._layoutService && !this._layoutService.checkElementInCurrentContainers(e.target)) return;
@@ -1478,6 +1465,7 @@ let MenuManagerService = _MenuManagerService = class MenuManagerService extends
1478
1465
  }
1479
1466
  dispose() {
1480
1467
  this.menuChanged$.complete();
1468
+ super.dispose();
1481
1469
  }
1482
1470
  /**
1483
1471
  * Merge source menu to target menu recursively
@@ -1497,46 +1485,48 @@ let MenuManagerService = _MenuManagerService = class MenuManagerService extends
1497
1485
  this._menu = (0, _univerjs_core.merge)({}, this._menu, source);
1498
1486
  this.menuChanged$.next();
1499
1487
  }
1488
+ updateMenuConfig(config) {
1489
+ this._configService.setConfig("menu", config, { merge: true });
1490
+ this.menuChanged$.next();
1491
+ }
1500
1492
  createScoped(injector) {
1501
- const root = this;
1502
1493
  const createScopedBuilder = () => {
1503
- const service = new _MenuManagerService(injector, root._configService);
1504
- service._menu = root._menu;
1494
+ const service = new _MenuManagerService(injector, this._configService);
1495
+ service._menu = this._menu;
1505
1496
  return service;
1506
1497
  };
1507
1498
  return {
1508
- menuChanged$: root.menuChanged$,
1509
- mergeMenu: (source, target) => root.mergeMenu(source, target),
1510
- appendRootMenu: (source) => root.appendRootMenu(source),
1499
+ menuChanged$: this.menuChanged$,
1500
+ mergeMenu: (source, target) => this.mergeMenu(source, target),
1501
+ appendRootMenu: (source) => this.appendRootMenu(source),
1502
+ updateMenuConfig: (config) => this.updateMenuConfig(config),
1511
1503
  getMenuByPositionKey: (position) => createScopedBuilder().getMenuByPositionKey(position),
1512
1504
  getFlatMenuByPositionKey: (position) => createScopedBuilder().getFlatMenuByPositionKey(position)
1513
1505
  };
1514
1506
  }
1515
1507
  _buildMenuSchema(data) {
1516
1508
  const result = [];
1509
+ const menuConfig = this._configService.getConfig("menu");
1517
1510
  for (const [key, value] of Object.entries(data)) {
1518
1511
  if (key === "replace") continue;
1512
+ const item = value.menuItemFactory ? this._injector.invoke(value.menuItemFactory) : void 0;
1513
+ const config = menuConfig === null || menuConfig === void 0 ? void 0 : menuConfig[(item === null || item === void 0 ? void 0 : item.id) ?? key];
1519
1514
  const menuItem = {
1520
1515
  key,
1521
- order: value.order,
1516
+ order: (config === null || config === void 0 ? void 0 : config.order) ?? value.order,
1522
1517
  title: value.title,
1523
1518
  contextual: value.contextual,
1524
1519
  quickLayout: value.quickLayout,
1525
1520
  quickColumns: value.quickColumns,
1526
1521
  quickLayoutVariant: value.quickLayoutVariant,
1522
+ mobileLayout: value.mobileLayout,
1527
1523
  tiny: value.tiny,
1528
- gridLayout: value.gridLayout
1524
+ gridLayout: (config === null || config === void 0 ? void 0 : config.gridLayout) ? {
1525
+ ...value.gridLayout,
1526
+ ...config.gridLayout
1527
+ } : value.gridLayout
1529
1528
  };
1530
- if (value.menuItemFactory) {
1531
- const item = this._injector.invoke(value.menuItemFactory);
1532
- if (item) {
1533
- const menuItemConfig = this._configService.getConfig("menu");
1534
- if (menuItemConfig && item.id in menuItemConfig) {
1535
- const _key = item.id;
1536
- menuItem.item = mergeMenuConfigs(item, menuItemConfig[_key]);
1537
- } else menuItem.item = item;
1538
- }
1539
- }
1529
+ if (item) menuItem.item = config ? mergeMenuConfigs(item, config) : item;
1540
1530
  if (value.headerActionMenuItemFactory) menuItem.headerActionItem = this._injector.invoke(value.headerActionMenuItemFactory);
1541
1531
  if (typeof value === "object") {
1542
1532
  const children = this._buildMenuSchema(value);
@@ -1832,7 +1822,7 @@ function FeatureSearch() {
1832
1822
  const dialogService = (0, _wendellhu_redi_react_bindings.useDependency)(IDialogService);
1833
1823
  const layoutService = (0, _wendellhu_redi_react_bindings.useDependency)(ILayoutService);
1834
1824
  const ribbonService = (0, _wendellhu_redi_react_bindings.useDependency)(IRibbonService);
1835
- const items = (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => {
1825
+ const items$ = (0, react.useMemo)(() => {
1836
1826
  function getItemTitle(item) {
1837
1827
  const titleKey = item.title ?? item.tooltip ?? item.description;
1838
1828
  return titleKey ? localeService.t(titleKey) : "";
@@ -1867,15 +1857,17 @@ function FeatureSearch() {
1867
1857
  const hasOptions = item.type === 1 || item.type === 2;
1868
1858
  const selections = hasOptions ? item.selections : void 0;
1869
1859
  const selections$ = (0, rxjs.isObservable)(selections) ? selections.pipe((0, rxjs_operators.startWith)([])) : (0, rxjs.of)(selections ?? []);
1860
+ const ancestorHidden$ = candidate.ancestors.length ? (0, rxjs.combineLatest)(candidate.ancestors.map((ancestor) => {
1861
+ var _ancestor$hidden$;
1862
+ return ((_ancestor$hidden$ = ancestor.hidden$) === null || _ancestor$hidden$ === void 0 ? void 0 : _ancestor$hidden$.pipe((0, rxjs_operators.startWith)(true))) ?? (0, rxjs.of)(false);
1863
+ })).pipe((0, rxjs_operators.map)((states) => states.some(Boolean))) : (0, rxjs.of)(false);
1864
+ const ancestorDisabled$ = candidate.ancestors.length ? (0, rxjs.combineLatest)(candidate.ancestors.map((ancestor) => {
1865
+ var _ancestor$disabled$;
1866
+ return ((_ancestor$disabled$ = ancestor.disabled$) === null || _ancestor$disabled$ === void 0 ? void 0 : _ancestor$disabled$.pipe((0, rxjs_operators.startWith)(true))) ?? (0, rxjs.of)(false);
1867
+ })).pipe((0, rxjs_operators.map)((states) => states.some(Boolean))) : (0, rxjs.of)(false);
1870
1868
  return (0, rxjs.combineLatest)([
1871
- candidate.ancestors.length ? (0, rxjs.combineLatest)(candidate.ancestors.map((ancestor) => {
1872
- var _ancestor$hidden$;
1873
- return ((_ancestor$hidden$ = ancestor.hidden$) === null || _ancestor$hidden$ === void 0 ? void 0 : _ancestor$hidden$.pipe((0, rxjs_operators.startWith)(true))) ?? (0, rxjs.of)(false);
1874
- })).pipe((0, rxjs_operators.map)((states) => states.some(Boolean))) : (0, rxjs.of)(false),
1875
- candidate.ancestors.length ? (0, rxjs.combineLatest)(candidate.ancestors.map((ancestor) => {
1876
- var _ancestor$disabled$;
1877
- return ((_ancestor$disabled$ = ancestor.disabled$) === null || _ancestor$disabled$ === void 0 ? void 0 : _ancestor$disabled$.pipe((0, rxjs_operators.startWith)(true))) ?? (0, rxjs.of)(false);
1878
- })).pipe((0, rxjs_operators.map)((states) => states.some(Boolean))) : (0, rxjs.of)(false),
1869
+ ancestorHidden$,
1870
+ ancestorDisabled$,
1879
1871
  ((_item$hidden$ = item.hidden$) === null || _item$hidden$ === void 0 ? void 0 : _item$hidden$.pipe((0, rxjs_operators.startWith)(true))) ?? (0, rxjs.of)(false),
1880
1872
  ((_item$disabled$ = item.disabled$) === null || _item$disabled$ === void 0 ? void 0 : _item$disabled$.pipe((0, rxjs_operators.startWith)(true))) ?? (0, rxjs.of)(false),
1881
1873
  ((_item$value$ = item.value$) === null || _item$value$ === void 0 ? void 0 : _item$value$.pipe((0, rxjs_operators.startWith)(void 0))) ?? (0, rxjs.of)(void 0),
@@ -1921,7 +1913,8 @@ function FeatureSearch() {
1921
1913
  localeService,
1922
1914
  menuManagerService,
1923
1915
  ribbonService
1924
- ]), []);
1916
+ ]);
1917
+ const items = (0, _wendellhu_redi_react_bindings.useObservable)(items$, []);
1925
1918
  async function execute(item) {
1926
1919
  layoutService.focus();
1927
1920
  if (await commandService.executeCommand(item.commandId, item.getParams())) dialogService.close(FEATURE_SEARCH_DIALOG_ID);
@@ -1980,6 +1973,260 @@ const OpenFeatureSearchOperation = {
1980
1973
  }
1981
1974
  };
1982
1975
 
1976
+ //#endregion
1977
+ //#region src/services/format-painter/format-painter-canvas.ts
1978
+ const FORMAT_PAINTER_CURSOR_CSS = `
1979
+ /* Keep the brush visible while the render engine updates its usual object/text cursors. */
1980
+ canvas[data-format-painter="available"] {
1981
+ cursor: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 28 28'%3E%3Cpath d='M2 1v18l4-4 3 7 3-2-3-6h6z' fill='white' stroke='black'/%3E%3Cpath d='m17 13 8-10 2 2-8 10z' fill='white' stroke='black'/%3E%3Cpath d='M17 14c-4 0-2 5-6 6 5 2 10-1 8-5z' fill='black' stroke='white'/%3E%3C/svg%3E") 2 1, crosshair !important;
1982
+ }
1983
+ canvas[data-format-painter="unavailable"] {
1984
+ cursor: not-allowed !important;
1985
+ }
1986
+ `;
1987
+ function bindFormatPainterCanvas(canvas, session, options) {
1988
+ let pressed = false;
1989
+ let applyTask;
1990
+ const active = () => {
1991
+ var _options$getUnitId;
1992
+ return session.isActive(options.adapterId) && session.unitId === (((_options$getUnitId = options.getUnitId) === null || _options$getUnitId === void 0 ? void 0 : _options$getUnitId.call(options)) ?? options.unitId);
1993
+ };
1994
+ const updateCursor = (event) => {
1995
+ if (active()) canvas.dataset.formatPainter = event && !options.getTarget(event) ? "unavailable" : "available";
1996
+ };
1997
+ const subscription = session.state$.subscribe(() => {
1998
+ if (active()) updateCursor();
1999
+ else if (session.mode === "off") {
2000
+ delete canvas.dataset.formatPainter;
2001
+ pressed = false;
2002
+ clearTimeout(applyTask);
2003
+ }
2004
+ });
2005
+ const down = (event) => {
2006
+ if (!active() || event.button !== 0) return;
2007
+ pressed = !!options.getTarget(event);
2008
+ if (options.intercept || !pressed) {
2009
+ canvas.focus();
2010
+ event.preventDefault();
2011
+ event.stopImmediatePropagation();
2012
+ }
2013
+ };
2014
+ const up = (event) => {
2015
+ if (!active() || !pressed || event.button !== 0) return;
2016
+ pressed = false;
2017
+ if (options.intercept) {
2018
+ event.preventDefault();
2019
+ event.stopImmediatePropagation();
2020
+ }
2021
+ clearTimeout(applyTask);
2022
+ applyTask = setTimeout(() => {
2023
+ const target = active() ? options.getTarget(event) : null;
2024
+ if (target) session.apply(options.adapterId, target).catch((error) => console.error("[FormatPainter]", error));
2025
+ }, 0);
2026
+ };
2027
+ const cancel = () => {
2028
+ pressed = false;
2029
+ };
2030
+ const doubleClick = (event) => {
2031
+ if (active() && options.intercept) {
2032
+ event.preventDefault();
2033
+ event.stopImmediatePropagation();
2034
+ }
2035
+ };
2036
+ canvas.addEventListener("pointerdown", down, true);
2037
+ canvas.addEventListener("pointerup", up, true);
2038
+ canvas.addEventListener("pointermove", updateCursor, true);
2039
+ canvas.addEventListener("pointercancel", cancel, true);
2040
+ canvas.addEventListener("pointerleave", cancel, true);
2041
+ canvas.addEventListener("dblclick", doubleClick, true);
2042
+ return { dispose: () => {
2043
+ clearTimeout(applyTask);
2044
+ subscription.unsubscribe();
2045
+ canvas.removeEventListener("pointerdown", down, true);
2046
+ canvas.removeEventListener("pointerup", up, true);
2047
+ canvas.removeEventListener("pointermove", updateCursor, true);
2048
+ canvas.removeEventListener("pointercancel", cancel, true);
2049
+ canvas.removeEventListener("pointerleave", cancel, true);
2050
+ canvas.removeEventListener("dblclick", doubleClick, true);
2051
+ delete canvas.dataset.formatPainter;
2052
+ } };
2053
+ }
2054
+
2055
+ //#endregion
2056
+ //#region src/services/format-painter/format-painter-session.service.ts
2057
+ /** One local interaction session; domain commands retain ownership of persisted formatting. */
2058
+ var FormatPainterSessionService = class extends _univerjs_core.Disposable {
2059
+ constructor(..._args) {
2060
+ super(..._args);
2061
+ _defineProperty(this, "_adapters", []);
2062
+ _defineProperty(this, "_state$", new rxjs.BehaviorSubject("off"));
2063
+ _defineProperty(this, "state$", this._state$.asObservable());
2064
+ _defineProperty(this, "_session", null);
2065
+ _defineProperty(this, "_applying", false);
2066
+ }
2067
+ get mode() {
2068
+ return this._state$.value;
2069
+ }
2070
+ get unitId() {
2071
+ var _this$_session;
2072
+ return (_this$_session = this._session) === null || _this$_session === void 0 ? void 0 : _this$_session.source.unitId;
2073
+ }
2074
+ register(adapter) {
2075
+ this._adapters.push(adapter);
2076
+ this._adapters.sort((a, b) => b.priority - a.priority);
2077
+ const subscription = adapter.changes$.subscribe(() => this.refresh());
2078
+ this.refresh();
2079
+ return this.disposeWithMe(() => {
2080
+ subscription.unsubscribe();
2081
+ const index = this._adapters.indexOf(adapter);
2082
+ if (index >= 0) this._adapters.splice(index, 1);
2083
+ if (this.isActive(adapter.id)) this.cancel();
2084
+ this.refresh();
2085
+ });
2086
+ }
2087
+ refresh() {
2088
+ this._state$.next(this.mode);
2089
+ }
2090
+ canStart() {
2091
+ var _this$_adapters$find;
2092
+ return ((_this$_adapters$find = this._adapters.find((adapter) => adapter.isActive())) === null || _this$_adapters$find === void 0 ? void 0 : _this$_adapters$find.canStart()) ?? false;
2093
+ }
2094
+ isActive(adapterId) {
2095
+ var _this$_session2;
2096
+ return ((_this$_session2 = this._session) === null || _this$_session2 === void 0 ? void 0 : _this$_session2.adapterId) === adapterId;
2097
+ }
2098
+ canClear() {
2099
+ const adapter = this._adapters.find((candidate) => candidate.isActive());
2100
+ return !!(adapter === null || adapter === void 0 ? void 0 : adapter.clear) && adapter.canStart();
2101
+ }
2102
+ async clearFormatting() {
2103
+ const adapter = this._adapters.find((candidate) => candidate.isActive());
2104
+ if (!(adapter === null || adapter === void 0 ? void 0 : adapter.clear) || !adapter.canStart() || this._applying) return false;
2105
+ this.cancel();
2106
+ this._applying = true;
2107
+ try {
2108
+ return await adapter.clear();
2109
+ } finally {
2110
+ this._applying = false;
2111
+ this.refresh();
2112
+ }
2113
+ }
2114
+ activate(continuous = false) {
2115
+ if (this._session) {
2116
+ if (continuous) this._setMode("continuous");
2117
+ else this.cancel();
2118
+ return true;
2119
+ }
2120
+ const adapter = this._adapters.find((candidate) => candidate.isActive());
2121
+ if (!(adapter === null || adapter === void 0 ? void 0 : adapter.canStart())) return false;
2122
+ const source = adapter.capture();
2123
+ if (!source) return false;
2124
+ this._session = {
2125
+ adapterId: adapter.id,
2126
+ source
2127
+ };
2128
+ this._setMode(continuous ? "continuous" : "once");
2129
+ return true;
2130
+ }
2131
+ async apply(adapterId, target) {
2132
+ const session = this._session;
2133
+ if (!session || session.adapterId !== adapterId || target.unitId !== session.source.unitId || this._applying) return false;
2134
+ this._applying = true;
2135
+ try {
2136
+ const applied = await session.source.apply(target);
2137
+ if (applied && this._session === session && this.mode === "once") this.cancel();
2138
+ return applied;
2139
+ } finally {
2140
+ this._applying = false;
2141
+ }
2142
+ }
2143
+ cancel() {
2144
+ var _session$source, _session$source$onMod;
2145
+ const session = this._session;
2146
+ this._session = null;
2147
+ session === null || session === void 0 || (_session$source$onMod = (_session$source = session.source).onModeChange) === null || _session$source$onMod === void 0 || _session$source$onMod.call(_session$source, "off");
2148
+ this._state$.next("off");
2149
+ }
2150
+ _setMode(mode) {
2151
+ var _this$_session3, _this$_session3$sourc, _this$_session3$sourc2;
2152
+ (_this$_session3 = this._session) === null || _this$_session3 === void 0 || (_this$_session3$sourc2 = (_this$_session3$sourc = _this$_session3.source).onModeChange) === null || _this$_session3$sourc2 === void 0 || _this$_session3$sourc2.call(_this$_session3$sourc, mode);
2153
+ this._state$.next(mode);
2154
+ }
2155
+ dispose() {
2156
+ this.cancel();
2157
+ this._adapters.length = 0;
2158
+ this._state$.complete();
2159
+ super.dispose();
2160
+ }
2161
+ };
2162
+
2163
+ //#endregion
2164
+ //#region src/controllers/format-painter.controller.ts
2165
+ const ActivateFormatPainterOperation = {
2166
+ id: "ui.operation.activate-format-painter",
2167
+ type: _univerjs_core.CommandType.OPERATION,
2168
+ handler: (accessor) => accessor.get(FormatPainterSessionService).activate()
2169
+ };
2170
+ const ContinuousFormatPainterOperation = {
2171
+ id: "ui.operation.continuous-format-painter",
2172
+ type: _univerjs_core.CommandType.OPERATION,
2173
+ handler: (accessor) => accessor.get(FormatPainterSessionService).activate(true)
2174
+ };
2175
+ const ClearFormattingCommand = {
2176
+ id: "ui.command.clear-formatting",
2177
+ type: _univerjs_core.CommandType.COMMAND,
2178
+ handler: (accessor) => accessor.get(FormatPainterSessionService).clearFormatting()
2179
+ };
2180
+ const CancelFormatPainterOperation = {
2181
+ id: "ui.operation.cancel-format-painter",
2182
+ type: _univerjs_core.CommandType.OPERATION,
2183
+ handler: (accessor) => {
2184
+ accessor.get(FormatPainterSessionService).cancel();
2185
+ return true;
2186
+ }
2187
+ };
2188
+ let FormatPainterController = class FormatPainterController extends _univerjs_core.Disposable {
2189
+ constructor(session, commandService, shortcutService, instanceService) {
2190
+ super();
2191
+ const cursorStyle = document.createElement("style");
2192
+ cursorStyle.textContent = FORMAT_PAINTER_CURSOR_CSS;
2193
+ document.head.appendChild(cursorStyle);
2194
+ this.disposeWithMe({ dispose: () => cursorStyle.remove() });
2195
+ for (const command of [
2196
+ ActivateFormatPainterOperation,
2197
+ ContinuousFormatPainterOperation,
2198
+ CancelFormatPainterOperation,
2199
+ ClearFormattingCommand
2200
+ ]) this.disposeWithMe(commandService.registerCommand(command));
2201
+ this.disposeWithMe(shortcutService.registerShortcut({
2202
+ id: CancelFormatPainterOperation.id,
2203
+ binding: 27,
2204
+ priority: 1e3,
2205
+ preconditions: () => session.mode !== "off"
2206
+ }));
2207
+ this.disposeWithMe(fromGlobalEvent("keydown", (event) => {
2208
+ if (event.key === "Escape" && session.mode !== "off" && event.target instanceof HTMLElement && event.target.closest(`[data-u-command="${ActivateFormatPainterOperation.id}"]`)) {
2209
+ commandService.syncExecuteCommand(CancelFormatPainterOperation.id);
2210
+ event.preventDefault();
2211
+ event.stopPropagation();
2212
+ }
2213
+ }, { capture: true }));
2214
+ this.disposeWithMe(instanceService.unitDisposed$.subscribe((unit) => {
2215
+ if (unit.getUnitId() === session.unitId) session.cancel();
2216
+ }));
2217
+ this.disposeWithMe(instanceService.focused$.subscribe((unitId) => {
2218
+ if (unitId && session.unitId && unitId !== session.unitId) session.cancel();
2219
+ session.refresh();
2220
+ }));
2221
+ }
2222
+ };
2223
+ FormatPainterController = __decorate([
2224
+ __decorateParam(0, (0, _univerjs_core.Inject)(FormatPainterSessionService)),
2225
+ __decorateParam(1, _univerjs_core.ICommandService),
2226
+ __decorateParam(2, IShortcutService),
2227
+ __decorateParam(3, _univerjs_core.IUniverInstanceService)
2228
+ ], FormatPainterController);
2229
+
1983
2230
  //#endregion
1984
2231
  //#region src/menu/feature-search.menu.ts
1985
2232
  function FeatureSearchMenuItemFactory() {
@@ -1992,6 +2239,33 @@ function FeatureSearchMenuItemFactory() {
1992
2239
  };
1993
2240
  }
1994
2241
 
2242
+ //#endregion
2243
+ //#region src/menu/format-painter.menu.ts
2244
+ function FormatPainterMenuItemFactory(accessor) {
2245
+ const session = accessor.get(FormatPainterSessionService);
2246
+ return {
2247
+ id: ActivateFormatPainterOperation.id,
2248
+ subId: ContinuousFormatPainterOperation.id,
2249
+ type: 0,
2250
+ icon: "BrushIcon",
2251
+ title: "ui.formatPainter",
2252
+ tooltip: "ui.formatPainter",
2253
+ activated$: session.state$.pipe((0, rxjs.map)((mode) => mode !== "off")),
2254
+ disabled$: session.state$.pipe((0, rxjs.map)((mode) => mode === "off" && !session.canStart()))
2255
+ };
2256
+ }
2257
+ function ClearFormattingMenuItemFactory(accessor) {
2258
+ const session = accessor.get(FormatPainterSessionService);
2259
+ return {
2260
+ id: ClearFormattingCommand.id,
2261
+ type: 0,
2262
+ icon: "ClearFormatDoubleIcon",
2263
+ title: "ui.clearFormatting",
2264
+ tooltip: "ui.clearFormatting",
2265
+ disabled$: session.state$.pipe((0, rxjs.map)(() => !session.canClear()))
2266
+ };
2267
+ }
2268
+
1995
2269
  //#endregion
1996
2270
  //#region src/menu/history.menu.ts
1997
2271
  const undoRedoDisableFactory$ = (accessor, isUndo) => {
@@ -2041,6 +2315,24 @@ function ShortcutPanelMenuItemFactory() {
2041
2315
  //#region src/menu/schema.ts
2042
2316
  const menuSchema = {
2043
2317
  ["ribbon.start.history"]: {
2318
+ [ActivateFormatPainterOperation.id]: {
2319
+ order: 2,
2320
+ gridLayout: {
2321
+ row: 1,
2322
+ column: 2,
2323
+ showLabel: false
2324
+ },
2325
+ menuItemFactory: FormatPainterMenuItemFactory
2326
+ },
2327
+ [ClearFormattingCommand.id]: {
2328
+ order: 3,
2329
+ gridLayout: {
2330
+ row: 2,
2331
+ column: 2,
2332
+ showLabel: false
2333
+ },
2334
+ menuItemFactory: ClearFormattingMenuItemFactory
2335
+ },
2044
2336
  [_univerjs_core.UndoCommand.id]: {
2045
2337
  order: 0,
2046
2338
  gridLayout: {
@@ -2637,7 +2929,7 @@ function RectPopup(props) {
2637
2929
  const containerBottom = Math.min((boundaryRect === null || boundaryRect === void 0 ? void 0 : boundaryRect.bottom) ?? window.innerHeight, window.innerHeight);
2638
2930
  const containerWidth = Math.max(containerRight - containerLeft, 0);
2639
2931
  const containerHeight = Math.max(containerBottom - containerTop, 0);
2640
- const minimumGap = noPushMinimumGap ? 0 : PUSHING_MINIMUM_GAP * 2;
2932
+ const minimumGap = noPushMinimumGap ? 0 : 16;
2641
2933
  const cannotFitBoundary = boundaryElement != null && (containerWidth <= 0 || containerHeight <= 0 || containerWidth < clientWidth + minimumGap || containerHeight < clientHeight + minimumGap);
2642
2934
  nodeRef.current.style.visibility = cannotFitBoundary ? "hidden" : "";
2643
2935
  if (cannotFitBoundary) return;
@@ -2713,7 +3005,8 @@ function RectPopup(props) {
2713
3005
  window.removeEventListener("contextmenu", handleContextMenu);
2714
3006
  };
2715
3007
  }, [contextMenuFn]);
2716
- const dir = (0, _wendellhu_redi_react_bindings.useObservable)((0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService).direction$);
3008
+ const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
3009
+ const dir = (0, _wendellhu_redi_react_bindings.useObservable)(localeService.direction$);
2717
3010
  const ele = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [mask && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2718
3011
  "data-u-comp": "rect-popup-mask",
2719
3012
  className: "univer-fixed univer-inset-0 univer-z-[100]",
@@ -2766,10 +3059,11 @@ const SingleCanvasPopup = ({ popup, children }) => {
2766
3059
  var _popup$hiddenRects$;
2767
3060
  return ((_popup$hiddenRects$ = popup.hiddenRects$) === null || _popup$hiddenRects$ === void 0 ? void 0 : _popup$hiddenRects$.pipe((0, rxjs.throttleTime)(0, rxjs.animationFrameScheduler))) ?? (0, rxjs.of)([]);
2768
3061
  }, [popup.hiddenRects$]);
2769
- const excludeRectsRef = useObservableRef((0, react.useMemo)(() => {
3062
+ const excludeRects$ = (0, react.useMemo)(() => {
2770
3063
  var _popup$excludeRects$;
2771
3064
  return (_popup$excludeRects$ = popup.excludeRects$) === null || _popup$excludeRects$ === void 0 ? void 0 : _popup$excludeRects$.pipe((0, rxjs.throttleTime)(0, rxjs.animationFrameScheduler));
2772
- }, [popup.excludeRects$]), popup.excludeRects);
3065
+ }, [popup.excludeRects$]);
3066
+ const excludeRectsRef = useObservableRef(excludeRects$, popup.excludeRects);
2773
3067
  const { boundaryInsets, canvasElement, constrainToCanvas = false, hideOnInvisible = true, hiddenType = "destroy" } = popup;
2774
3068
  const hidden = (0, _wendellhu_redi_react_bindings.useObservable)(hideOnInvisible ? () => (0, rxjs.combineLatest)([anchorRect$, hiddenRects$]).pipe((0, rxjs.map)(([rectWithOffset, hiddenRects]) => {
2775
3069
  const { top, left, bottom, right } = canvasElement.getBoundingClientRect();
@@ -2818,16 +3112,20 @@ const SingleCanvasPopup = ({ popup, children }) => {
2818
3112
  };
2819
3113
  function CanvasPopup() {
2820
3114
  const popupService = (0, _wendellhu_redi_react_bindings.useDependency)(ICanvasPopupService);
2821
- const componentManager = (0, _wendellhu_redi_react_bindings.useDependency)(ComponentManager);
2822
- return (0, _wendellhu_redi_react_bindings.useObservable)(popupService.popups$, void 0, true).map((item) => {
2823
- const [key, popup] = item;
2824
- const Component = componentManager.get(popup.componentKey);
2825
- const PopupComponent = Component && popup.connectorInjector ? (0, _wendellhu_redi_react_bindings.connectInjector)(Component, popup.connectorInjector) : Component;
2826
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SingleCanvasPopup, {
2827
- popup,
2828
- children: PopupComponent && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PopupComponent, { popup })
2829
- }, key);
2830
- });
3115
+ return (0, _wendellhu_redi_react_bindings.useObservable)(popupService.popups$, void 0, true).map(([key, popup]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SingleCanvasPopup, {
3116
+ popup,
3117
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CanvasPopupContent, { popup })
3118
+ }, key));
3119
+ }
3120
+ function CanvasPopupContent({ popup }) {
3121
+ const Component = (0, _wendellhu_redi_react_bindings.useDependency)(ComponentManager).get(popup.componentKey);
3122
+ const connectorContext = (0, react.useMemo)(() => ({ injector: popup.connectorInjector ?? null }), [popup.connectorInjector]);
3123
+ if (!Component) return null;
3124
+ const content = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, { popup });
3125
+ return popup.connectorInjector ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_wendellhu_redi_react_bindings.RediContext.Provider, {
3126
+ value: connectorContext,
3127
+ children: content
3128
+ }) : content;
2831
3129
  }
2832
3130
 
2833
3131
  //#endregion
@@ -2879,13 +3177,15 @@ function ComponentContainer(props) {
2879
3177
  function useComponentsOfPart(part, injector) {
2880
3178
  const injectedUIPartsService = (0, _wendellhu_redi_react_bindings.useDependency)(IUIPartsService);
2881
3179
  const uiPartsService = (injector === null || injector === void 0 ? void 0 : injector.get(IUIPartsService)) ?? injectedUIPartsService;
2882
- const changeInfo = (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => uiPartsService.uiVisibleChange$.pipe((0, rxjs.filter)((ui) => ui.ui === part)), [part, uiPartsService]));
3180
+ const uiVisibleChange$ = (0, react.useMemo)(() => uiPartsService.uiVisibleChange$.pipe((0, rxjs.filter)((ui) => ui.ui === part)), [part, uiPartsService]);
3181
+ const changeInfo = (0, _wendellhu_redi_react_bindings.useObservable)(uiVisibleChange$);
2883
3182
  const updateCounterRef = (0, react.useRef)(0);
2884
- return (0, react.useMemo)(() => uiPartsService.isUIVisible(part) ? uiPartsService.getComponents(part) : /* @__PURE__ */ new Set(), [(0, _wendellhu_redi_react_bindings.useObservable)(() => uiPartsService.componentRegistered$.pipe((0, rxjs.filter)((key) => key === part), (0, rxjs.debounceTime)(200), (0, rxjs.map)(() => updateCounterRef.current += 1), (0, rxjs.startWith)(updateCounterRef.current += 1)), void 0, void 0, [
3183
+ const componentPartUpdateCount = (0, _wendellhu_redi_react_bindings.useObservable)(() => uiPartsService.componentRegistered$.pipe((0, rxjs.filter)((key) => key === part), (0, rxjs.debounceTime)(200), (0, rxjs.map)(() => updateCounterRef.current += 1), (0, rxjs.startWith)(updateCounterRef.current += 1)), void 0, void 0, [
2885
3184
  uiPartsService,
2886
3185
  part,
2887
3186
  changeInfo
2888
- ])]);
3187
+ ]);
3188
+ return (0, react.useMemo)(() => uiPartsService.isUIVisible(part) ? uiPartsService.getComponents(part) : /* @__PURE__ */ new Set(), [componentPartUpdateCount]);
2889
3189
  }
2890
3190
 
2891
3191
  //#endregion
@@ -2991,7 +3291,7 @@ function RibbonGridMenu({ ribbon, activatedTab, onSelectTab }) {
2991
3291
  "aria-selected": isActive,
2992
3292
  title,
2993
3293
  onClick: () => onSelectTab(group),
2994
- className: (0, _univerjs_design.clsx)("univer-relative univer-flex univer-h-9 univer-cursor-pointer univer-items-center univer-whitespace-nowrap univer-border-0 univer-border-b-[3px] univer-bg-transparent univer-px-3 univer-text-base univer-font-semibold univer-text-gray-700 univer-transition-colors hover:univer-text-gray-900 focus-visible:univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 dark:!univer-text-gray-200 dark:hover:!univer-text-gray-0", isActive ? "univer-border-primary-600 univer-text-primary-700 dark:!univer-text-primary-300" : "univer-border-transparent"),
3294
+ className: (0, _univerjs_design.clsx)("univer-relative univer-flex univer-h-8 univer-cursor-pointer univer-items-center univer-whitespace-nowrap univer-border-0 univer-border-b-[3px] univer-bg-transparent univer-px-3 univer-text-sm univer-font-semibold univer-text-gray-700 univer-transition-colors hover:univer-text-gray-900 focus-visible:univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 dark:!univer-text-gray-200 dark:hover:!univer-text-gray-0", isActive ? "univer-border-primary-600 univer-text-primary-700 dark:!univer-text-primary-300" : "univer-border-transparent"),
2995
3295
  children: title
2996
3296
  }, group.key);
2997
3297
  })
@@ -3093,7 +3393,8 @@ function CustomLabel(props) {
3093
3393
  const componentManager = (0, _wendellhu_redi_react_bindings.useDependency)(ComponentManager);
3094
3394
  const iconManager = (0, _wendellhu_redi_react_bindings.useDependency)(IconManager);
3095
3395
  const subscribedValue = (0, _wendellhu_redi_react_bindings.useObservable)(value$ ?? null, value);
3096
- const subscribedIcon = (0, _wendellhu_redi_react_bindings.useObservable)((0, rxjs.isObservable)(icon) ? icon : null, "");
3396
+ const observableIcon = (0, rxjs.isObservable)(icon) ? icon : null;
3397
+ const subscribedIcon = (0, _wendellhu_redi_react_bindings.useObservable)(observableIcon, "");
3097
3398
  const realIcon = (0, rxjs.isObservable)(icon) ? subscribedIcon : icon ?? "";
3098
3399
  const nodes = [];
3099
3400
  let index = 0;
@@ -3161,9 +3462,10 @@ function useToolbarItemStatus(menuItem) {
3161
3462
  const disabled = (0, _wendellhu_redi_react_bindings.useObservable)(disabled$ ?? null, false);
3162
3463
  const activated = (0, _wendellhu_redi_react_bindings.useObservable)(activated$ ?? null, false);
3163
3464
  const hidden = (0, _wendellhu_redi_react_bindings.useObservable)(hidden$ ?? null, false);
3465
+ const valueObservable = (0, react.useMemo)(() => (0, rxjs.merge)(value$ ?? rxjs.EMPTY, selectionsValue$ ?? rxjs.EMPTY), [selectionsValue$, value$]);
3164
3466
  return {
3165
3467
  disabled,
3166
- value: (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => (0, rxjs.merge)(value$ ?? rxjs.EMPTY, selectionsValue$ ?? rxjs.EMPTY), [selectionsValue$, value$])),
3468
+ value: (0, _wendellhu_redi_react_bindings.useObservable)(valueObservable),
3167
3469
  activated,
3168
3470
  hidden,
3169
3471
  selectionsValue: (0, _wendellhu_redi_react_bindings.useObservable)(selectionsValue$ ?? null)
@@ -3172,11 +3474,12 @@ function useToolbarItemStatus(menuItem) {
3172
3474
  function useToolbarShortcutDisplay({ id, commandId, shortcut }) {
3173
3475
  const shortcutService = (0, _wendellhu_redi_react_bindings.useDependency)(IShortcutService);
3174
3476
  const shortcutCommandId = commandId ?? id;
3175
- return (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => shortcut ? (0, rxjs.of)(shortcut) : shortcutService.shortcutChanged$.pipe((0, rxjs.map)(() => shortcutService.getShortcutDisplayOfCommand(shortcutCommandId)), (0, rxjs.startWith)(shortcutService.getShortcutDisplayOfCommand(shortcutCommandId))), [
3477
+ const shortcut$ = (0, react.useMemo)(() => shortcut ? (0, rxjs.of)(shortcut) : shortcutService.shortcutChanged$.pipe((0, rxjs.map)(() => shortcutService.getShortcutDisplayOfCommand(shortcutCommandId)), (0, rxjs.startWith)(shortcutService.getShortcutDisplayOfCommand(shortcutCommandId))), [
3176
3478
  shortcut,
3177
3479
  shortcutService,
3178
3480
  shortcutCommandId
3179
- ]), null, true);
3481
+ ]);
3482
+ return (0, _wendellhu_redi_react_bindings.useObservable)(shortcut$, null, true);
3180
3483
  }
3181
3484
 
3182
3485
  //#endregion
@@ -3203,6 +3506,7 @@ univer-text-gray-900 univer-outline-none univer-transition-colors univer-animate
3203
3506
  dark:!univer-text-gray-0 dark:hover:!univer-bg-gray-700 dark:disabled:!univer-text-gray-600
3204
3507
  disabled:univer-cursor-not-allowed disabled:univer-text-gray-300 disabled:hover:univer-bg-transparent
3205
3508
  hover:univer-bg-gray-100 whitespace-nowrap univer-w-max
3509
+ [&_svg]:univer-shrink-0
3206
3510
  `;
3207
3511
  const toolbarButtonVariants = (0, _univerjs_design.cva)(toolbarButtonClassName, {
3208
3512
  variants: {
@@ -3241,11 +3545,11 @@ function ToolbarButton(props) {
3241
3545
  };
3242
3546
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3243
3547
  type: "button",
3244
- className: toolbarButtonVariants({
3548
+ className: (0, _univerjs_design.clsx)(toolbarButtonVariants({
3245
3549
  noIcon,
3246
3550
  active,
3247
3551
  className
3248
- }),
3552
+ })),
3249
3553
  style,
3250
3554
  disabled,
3251
3555
  onClick: handleClick,
@@ -3454,7 +3758,7 @@ function DropdownMenuWrapper({ menuId, slot, value, options, children, disabled,
3454
3758
  const menuManagerService = (0, _wendellhu_redi_react_bindings.useDependency)(IMenuManagerService);
3455
3759
  const resolveMenuItems = () => menuId ? menuManagerService.getMenuByPositionKey(menuId) : [];
3456
3760
  const menuItems = (0, _wendellhu_redi_react_bindings.useObservable)(() => menuManagerService.menuChanged$.pipe((0, rxjs.map)(resolveMenuItems), (0, rxjs.startWith)(resolveMenuItems())), resolveMenuItems(), false, [menuId, menuManagerService]);
3457
- const hiddenStates = (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => {
3761
+ const hiddenStates$ = (0, react.useMemo)(() => {
3458
3762
  const itemStates = menuItems.map((item) => {
3459
3763
  var _item$item;
3460
3764
  return (item.children ? (0, rxjs.combineLatest)(item.children.map((subItem) => {
@@ -3466,7 +3770,8 @@ function DropdownMenuWrapper({ menuId, slot, value, options, children, disabled,
3466
3770
  ...states,
3467
3771
  [key]: hidden
3468
3772
  }), {}), (0, rxjs.startWith)({})) : (0, rxjs.of)({});
3469
- }, [menuItems]), {});
3773
+ }, [menuItems]);
3774
+ const hiddenStates = (0, _wendellhu_redi_react_bindings.useObservable)(hiddenStates$, {});
3470
3775
  const filteredMenuItems = (0, react.useMemo)(() => {
3471
3776
  return menuItems.filter((item) => {
3472
3777
  var _item$key;
@@ -3768,13 +4073,14 @@ const ToolbarItem = (0, react.forwardRef)((props, ref) => {
3768
4073
  let tooltipTitle = tooltip ? localeService.t(tooltip) : "";
3769
4074
  if (shortcutDisplay) tooltipTitle += ` (${shortcutDisplay})`;
3770
4075
  const { selections } = props;
3771
- const options = (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => {
4076
+ const selections$ = (0, react.useMemo)(() => {
3772
4077
  if ((0, rxjs.isObservable)(selections)) return selections;
3773
4078
  else return new rxjs.Observable((subscribe) => {
3774
4079
  subscribe.next(selections);
3775
4080
  });
3776
- }, [selections]));
3777
- const iconToDisplay = (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => {
4081
+ }, [selections]);
4082
+ const options = (0, _wendellhu_redi_react_bindings.useObservable)(selections$);
4083
+ const icon$ = (0, react.useMemo)(() => {
3778
4084
  if ((0, rxjs.isObservable)(icon)) return icon;
3779
4085
  else return new rxjs.Observable((subscribe) => {
3780
4086
  var _options$find;
@@ -3785,7 +4091,8 @@ const ToolbarItem = (0, react.forwardRef)((props, ref) => {
3785
4091
  icon,
3786
4092
  options,
3787
4093
  value
3788
- ]), void 0, true);
4094
+ ]);
4095
+ const iconToDisplay = (0, _wendellhu_redi_react_bindings.useObservable)(icon$, void 0, true);
3789
4096
  function renderSelectorType(menuType) {
3790
4097
  const selectionsCommandId = props.selectionsCommandId;
3791
4098
  const bId = commandId ?? id;
@@ -3815,6 +4122,7 @@ const ToolbarItem = (0, react.forwardRef)((props, ref) => {
3815
4122
  if (menuType === 2) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3816
4123
  "data-u-command": id,
3817
4124
  "data-disabled": disabled,
4125
+ "aria-disabled": disabled,
3818
4126
  className: (0, _univerjs_design.clsx)(toolbarButtonSelectorRootVariants({ disabled }), {
3819
4127
  "univer-box-border univer-h-full univer-min-w-14 univer-flex-col !univer-pr-0": grid && large,
3820
4128
  "univer-box-border univer-h-full": grid && !large
@@ -3824,7 +4132,7 @@ const ToolbarItem = (0, react.forwardRef)((props, ref) => {
3824
4132
  active: activated,
3825
4133
  disabled
3826
4134
  }), {
3827
- "univer-h-full univer-w-full univer-flex-col univer-justify-center univer-rounded univer-px-1 univer-pb-4 [&>svg]:univer-size-8": grid && large,
4135
+ "univer-h-full univer-w-full univer-flex-col univer-justify-center univer-rounded univer-px-1 univer-pb-4 [&>svg]:univer-size-6": grid && large,
3828
4136
  "[&>svg]:univer-size-4": grid && !large
3829
4137
  }),
3830
4138
  onClick: handleClick,
@@ -3880,7 +4188,7 @@ const ToolbarItem = (0, react.forwardRef)((props, ref) => {
3880
4188
  disabled,
3881
4189
  active: activated
3882
4190
  }), {
3883
- "univer-box-border univer-h-full univer-min-w-14 univer-flex-col univer-justify-center univer-gap-1 univer-px-1.5 univer-py-1 univer-text-xs [&>svg]:univer-size-8": grid && large,
4191
+ "univer-box-border univer-h-full univer-min-w-14 univer-flex-col univer-justify-center univer-gap-1 univer-px-1.5 univer-py-1 univer-text-xs [&>svg]:univer-size-6": grid && large,
3884
4192
  "univer-box-border univer-h-full": grid && !large,
3885
4193
  "univer-bg-gray-0 dark:!univer-bg-gray-800": grid && !large && !icon,
3886
4194
  "[&>svg]:univer-size-4": grid && !large
@@ -3915,7 +4223,7 @@ const ToolbarItem = (0, react.forwardRef)((props, ref) => {
3915
4223
  function renderButtonType() {
3916
4224
  const isCustomComponent = componentManager.get(typeof label === "string" ? label : (label === null || label === void 0 ? void 0 : label.name) ?? "");
3917
4225
  const buttonAriaLabel = tooltip ? localeService.t(tooltip) : typeof title === "string" ? localeService.t(title) : void 0;
3918
- const buttonClassName = (0, _univerjs_design.clsx)(grid && !large && "univer-h-full univer-min-w-8 [&>svg]:univer-size-4", grid && large ? "univer-h-full univer-min-w-14 univer-flex-col univer-gap-1 univer-px-1.5 univer-py-1 univer-text-xs [&>svg]:univer-size-8" : showLabel ? "univer-gap-1 univer-px-1.5 univer-text-sm" : "univer-text-sm", grid && fullWidth && isCustomComponent && "!univer-px-0");
4226
+ const buttonClassName = (0, _univerjs_design.clsx)(grid && !large && "[&>svg]:univer-size-4", grid && large ? "univer-h-full univer-min-w-14 univer-flex-col univer-gap-1 univer-px-1.5 univer-py-1 univer-text-xs [&>svg]:univer-size-6" : showLabel ? "univer-gap-1 univer-px-1.5 univer-text-sm" : "univer-text-sm", grid && fullWidth && isCustomComponent && "!univer-px-0");
3919
4227
  const buttonStyle = grid && large ? {
3920
4228
  textAlign: "center",
3921
4229
  whiteSpace: "normal"
@@ -3924,11 +4232,11 @@ const ToolbarItem = (0, react.forwardRef)((props, ref) => {
3924
4232
  const hoverable = typeof label === "string" || (label === null || label === void 0 ? void 0 : label.hoverable) !== false;
3925
4233
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
3926
4234
  "data-u-command": id,
3927
- className: toolbarButtonVariants({
4235
+ className: (0, _univerjs_design.clsx)(toolbarButtonVariants({
3928
4236
  noIcon: !icon,
3929
4237
  active: activated,
3930
4238
  className: (0, _univerjs_design.clsx)(buttonClassName, !hoverable && "univer-cursor-default !univer-bg-transparent hover:!univer-bg-transparent dark:hover:!univer-bg-transparent")
3931
- }),
4239
+ })),
3932
4240
  style: buttonStyle,
3933
4241
  "aria-disabled": disabled,
3934
4242
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomLabel, {
@@ -3946,8 +4254,10 @@ const ToolbarItem = (0, react.forwardRef)((props, ref) => {
3946
4254
  style: buttonStyle,
3947
4255
  noIcon: !icon,
3948
4256
  active: activated,
4257
+ "aria-pressed": props.activated$ ? activated : void 0,
3949
4258
  disabled,
3950
- onClick: () => {
4259
+ onClick: (event) => {
4260
+ if (props.subId && event.detail > 1) return;
3951
4261
  const commandParams = typeof params === "function" ? params() : params;
3952
4262
  executeCommand(props.commandId ?? props.id, commandParams ?? (typeof value === "undefined" ? void 0 : { value }));
3953
4263
  },
@@ -3986,17 +4296,18 @@ function RibbonGrid({ groups, title, className, ...props }) {
3986
4296
  ...props,
3987
4297
  "data-testid": "ribbon-grid-toolbar",
3988
4298
  "data-u-comp": "ribbon-grid-toolbar",
3989
- className: (0, _univerjs_design.clsx)("univer-box-border univer-flex univer-h-[88px] univer-overflow-x-auto univer-overflow-y-hidden univer-bg-gray-50 univer-px-2 univer-text-sm dark:!univer-bg-gray-900", _univerjs_design.borderBottomClassName, _univerjs_design.scrollbarClassName, className),
4299
+ className: (0, _univerjs_design.clsx)("univer-box-border univer-flex univer-overflow-x-auto univer-overflow-y-hidden univer-bg-gray-50 univer-px-2 univer-text-sm dark:!univer-bg-gray-900", _univerjs_design.borderBottomClassName, _univerjs_design.scrollbarClassName, className),
3990
4300
  role: "toolbar",
3991
4301
  "aria-label": localeService.t(title),
3992
4302
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarDropdownProvider, { children: groups.map((group) => {
4303
+ const placements = placeRibbonGridItems(group.children ?? []);
3993
4304
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3994
4305
  "data-u-comp": "ribbon-grid-group",
3995
4306
  className: "univer-relative univer-box-border univer-flex univer-min-w-16 univer-shrink-0 univer-flex-col univer-px-2",
3996
4307
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3997
4308
  "data-testid": "ribbon-grid-group-grid",
3998
- className: "univer-grid univer-min-h-0 univer-flex-1 univer-grid-flow-col univer-grid-rows-2 univer-content-center univer-gap-x-1 univer-gap-y-2 univer-py-2 [&>div>span>span]:univer-h-full",
3999
- children: placeRibbonGridItems(group.children ?? []).map((placement) => placement.item.item && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4309
+ className: "univer-grid univer-min-h-0 univer-flex-1 univer-grid-flow-col univer-grid-rows-[repeat(2,1.5rem)] univer-content-center univer-gap-2 univer-py-2 [&>div>span>span]:univer-h-full",
4310
+ children: placements.map((placement) => placement.item.item && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4000
4311
  className: (0, _univerjs_design.clsx)("univer-flex univer-items-stretch [&>span>button]:univer-h-full [&>span]:univer-h-full", placement.width && "[&>span>span]:univer-w-full [&>span]:univer-w-full [&_[data-u-command]]:univer-w-full"),
4001
4312
  style: {
4002
4313
  gridRow: `${placement.row} / span ${placement.rowSpan}`,
@@ -4172,108 +4483,110 @@ function Ribbon(props) {
4172
4483
  "data-embed-ribbon-override": "true",
4173
4484
  "data-embed-id": ribbonOverride.id
4174
4485
  } : {};
4175
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RibbonOverrideRuntimeProvider, {
4176
- override: ribbonOverride,
4177
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
4178
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4179
- "data-u-comp": "ribbon-header-menu",
4180
- ...embedRibbonOverrideAttributes,
4181
- className: (0, _univerjs_design.clsx)("univer-relative univer-select-none", headerClassName, {
4182
- "univer-hidden": toolbarOnly,
4183
- "univer-h-9": !toolbarOnly && (ribbonType === "classic" || ribbonType === "grid" || headerMenuComponents && headerMenuComponents.size > 0)
4184
- }),
4185
- children: [
4186
- !toolbarOnly && (ribbonOverride === null || ribbonOverride === void 0 ? void 0 : ribbonOverride.placeholderTitle) && ribbon.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4187
- className: (0, _univerjs_design.clsx)("univer-flex univer-h-9 univer-items-end univer-px-3", { "univer-justify-center": hideToolbar }),
4188
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4189
- className: "univer-relative univer-inline-flex univer-h-8 univer-items-center univer-justify-center univer-rounded-t univer-bg-primary-50 univer-px-3 univer-text-sm univer-font-medium univer-text-primary-600",
4190
- children: ribbonOverride.placeholderTitle
4191
- })
4192
- }),
4193
- !toolbarOnly && ribbonType === "classic" && ribbon.length >= 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClassicMenu, {
4194
- ribbon,
4195
- activatedTab,
4196
- onSelectTab: handleSelectTab
4197
- }),
4198
- !toolbarOnly && ribbonType === "grid" && ribbon.length >= 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RibbonGridMenu, {
4199
- ribbon,
4200
- activatedTab,
4201
- onSelectTab: handleSelectTab
4202
- }),
4203
- headerMenu && headerMenuComponents && headerMenuComponents.size > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4204
- className: "univer-absolute univer-right-2 univer-top-0 univer-flex univer-h-full univer-flex-row univer-items-center univer-gap-2 rtl:univer-left-2 rtl:univer-right-auto [&>*]:univer-inline-flex [&>*]:univer-h-6 [&>*]:univer-items-center [&>*]:univer-rounded [&>*]:univer-px-1 [&>*]:univer-transition-colors hover:[&>*]:univer-bg-gray-100",
4205
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, { components: headerMenuComponents })
4206
- })
4207
- ]
4208
- }),
4209
- !hideToolbar && ribbonType === "grid" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RibbonGrid, {
4210
- ...embedRibbonOverrideAttributes,
4211
- groups: activeGroup.allGroups,
4212
- title: activatedTabTitle
4486
+ const content = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
4487
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4488
+ "data-u-comp": "ribbon-header-menu",
4489
+ ...embedRibbonOverrideAttributes,
4490
+ className: (0, _univerjs_design.clsx)("univer-relative univer-select-none", headerClassName, {
4491
+ "univer-hidden": toolbarOnly,
4492
+ "univer-h-8": !toolbarOnly && ribbonType === "grid",
4493
+ "univer-h-9": !toolbarOnly && ribbonType !== "grid" && (ribbonType === "classic" || headerMenuComponents && headerMenuComponents.size > 0)
4213
4494
  }),
4214
- !hideToolbar && ribbonType !== "grid" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4215
- ...embedRibbonOverrideAttributes,
4216
- 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", {
4217
- "univer-grid-cols-[1fr] univer-justify-center": ribbonType === "classic" || ribbon.length === 1,
4218
- "univer-grid-cols-[auto,1fr]": ribbon.length > 1 && ribbonType !== "classic"
4219
- }, _univerjs_design.borderBottomClassName),
4220
- children: [ribbonType === "collapsed" && ribbon.length >= 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultMenu, {
4495
+ children: [
4496
+ !toolbarOnly && (ribbonOverride === null || ribbonOverride === void 0 ? void 0 : ribbonOverride.placeholderTitle) && ribbon.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4497
+ className: (0, _univerjs_design.clsx)("univer-flex univer-h-9 univer-items-end univer-px-3", { "univer-justify-center": hideToolbar }),
4498
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4499
+ className: "univer-relative univer-inline-flex univer-h-8 univer-items-center univer-justify-center univer-rounded-t univer-bg-primary-50 univer-px-3 univer-text-sm univer-font-medium univer-text-primary-600",
4500
+ children: ribbonOverride.placeholderTitle
4501
+ })
4502
+ }),
4503
+ !toolbarOnly && ribbonType === "classic" && ribbon.length >= 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ClassicMenu, {
4221
4504
  ribbon,
4222
4505
  activatedTab,
4223
4506
  onSelectTab: handleSelectTab
4224
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4225
- "data-u-comp": "ribbon-toolbar",
4226
- ref: containerRef,
4227
- className: (0, _univerjs_design.clsx)("univer-flex univer-overflow-hidden", _univerjs_design.divideXClassName, { "univer-justify-center": ribbonType === "classic" }),
4228
- role: "toolbar",
4229
- "aria-label": localeService.t(activatedTabTitle),
4230
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ToolbarDropdownProvider, { children: [activeGroup.visibleGroups.map((groupItem) => {
4231
- var _groupItem$children3, _groupItem$children4;
4232
- 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", {
4233
- className: "univer-grid univer-shrink-0 univer-grid-flow-col univer-gap-2 univer-px-2 empty:univer-hidden",
4234
- 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, {
4235
- ...child.item,
4236
- preserveStrokeWidth: true
4237
- }, child.key)))
4238
- }) }, groupItem.key);
4239
- }), collapsedIds.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4240
- className: "univer-pl-2 rtl:univer-pr-2",
4241
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Dropdown, {
4242
- collisionPadding: {
4243
- right: 12,
4244
- left: 12
4245
- },
4246
- onOpenAutoFocus: (e) => e.preventDefault(),
4247
- overlay: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4248
- className: "univer-box-border univer-grid univer-max-w-[--radix-popper-available-width] univer-gap-2 univer-p-2",
4249
- children: activeGroup.hiddenGroups.map((groupItem) => {
4250
- var _groupItem$children5;
4251
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4252
- className: "univer-flex univer-items-center univer-gap-2",
4253
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4254
- className: "univer-flex univer-flex-wrap univer-gap-2",
4255
- children: groupItem.children ? (_groupItem$children5 = groupItem.children) === null || _groupItem$children5 === void 0 ? void 0 : _groupItem$children5.map((child) => child.item && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarItem, {
4256
- ...child.item,
4257
- preserveStrokeWidth: true
4258
- }, child.key)) : groupItem.item && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarItem, {
4259
- ...groupItem.item,
4260
- preserveStrokeWidth: true
4261
- }, groupItem.key)
4262
- })
4263
- }, groupItem.key);
4264
- })
4265
- }),
4266
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4267
- type: "button",
4268
- className: toolbarButtonClassName,
4269
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.MoreVerticalIcon, { preserveStrokeWidth: true })
4507
+ }),
4508
+ !toolbarOnly && ribbonType === "grid" && ribbon.length >= 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RibbonGridMenu, {
4509
+ ribbon,
4510
+ activatedTab,
4511
+ onSelectTab: handleSelectTab
4512
+ }),
4513
+ headerMenu && headerMenuComponents && headerMenuComponents.size > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4514
+ className: "univer-absolute univer-right-2 univer-top-0 univer-flex univer-h-full univer-flex-row univer-items-center univer-gap-2 rtl:univer-left-2 rtl:univer-right-auto [&>*]:univer-inline-flex [&>*]:univer-h-6 [&>*]:univer-items-center [&>*]:univer-rounded [&>*]:univer-px-1 [&>*]:univer-transition-colors hover:[&>*]:univer-bg-gray-100",
4515
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, { components: headerMenuComponents })
4516
+ })
4517
+ ]
4518
+ }),
4519
+ !hideToolbar && ribbonType === "grid" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RibbonGrid, {
4520
+ ...embedRibbonOverrideAttributes,
4521
+ groups: activeGroup.allGroups,
4522
+ title: activatedTabTitle
4523
+ }),
4524
+ !hideToolbar && ribbonType !== "grid" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4525
+ ...embedRibbonOverrideAttributes,
4526
+ 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", {
4527
+ "univer-grid-cols-[1fr] univer-justify-center": ribbonType === "classic" || ribbon.length === 1,
4528
+ "univer-grid-cols-[auto,1fr]": ribbon.length > 1 && ribbonType !== "classic"
4529
+ }, _univerjs_design.borderBottomClassName),
4530
+ children: [ribbonType === "collapsed" && ribbon.length >= 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultMenu, {
4531
+ ribbon,
4532
+ activatedTab,
4533
+ onSelectTab: handleSelectTab
4534
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4535
+ "data-u-comp": "ribbon-toolbar",
4536
+ ref: containerRef,
4537
+ className: (0, _univerjs_design.clsx)("univer-flex univer-overflow-hidden", _univerjs_design.divideXClassName, { "univer-justify-center": ribbonType === "classic" }),
4538
+ role: "toolbar",
4539
+ "aria-label": localeService.t(activatedTabTitle),
4540
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ToolbarDropdownProvider, { children: [activeGroup.visibleGroups.map((groupItem) => {
4541
+ var _groupItem$children3, _groupItem$children4;
4542
+ 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", {
4543
+ className: "univer-grid univer-shrink-0 univer-grid-flow-col univer-gap-2 univer-px-2 empty:univer-hidden",
4544
+ 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, {
4545
+ ...child.item,
4546
+ preserveStrokeWidth: true
4547
+ }, child.key)))
4548
+ }) }, groupItem.key);
4549
+ }), collapsedIds.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4550
+ className: "univer-pl-2 rtl:univer-pr-2",
4551
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Dropdown, {
4552
+ collisionPadding: {
4553
+ right: 12,
4554
+ left: 12
4555
+ },
4556
+ onOpenAutoFocus: (e) => e.preventDefault(),
4557
+ overlay: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4558
+ className: "univer-box-border univer-grid univer-max-w-[--radix-popper-available-width] univer-gap-2 univer-p-2",
4559
+ children: activeGroup.hiddenGroups.map((groupItem) => {
4560
+ var _groupItem$children5;
4561
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4562
+ className: "univer-flex univer-items-center univer-gap-2",
4563
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4564
+ className: "univer-flex univer-flex-wrap univer-gap-2",
4565
+ children: groupItem.children ? (_groupItem$children5 = groupItem.children) === null || _groupItem$children5 === void 0 ? void 0 : _groupItem$children5.map((child) => child.item && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarItem, {
4566
+ ...child.item,
4567
+ preserveStrokeWidth: true
4568
+ }, child.key)) : groupItem.item && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarItem, {
4569
+ ...groupItem.item,
4570
+ preserveStrokeWidth: true
4571
+ }, groupItem.key)
4572
+ })
4573
+ }, groupItem.key);
4270
4574
  })
4575
+ }),
4576
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4577
+ type: "button",
4578
+ className: toolbarButtonClassName,
4579
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.MoreVerticalIcon, { preserveStrokeWidth: true })
4271
4580
  })
4272
- })] }, effectiveActivatedTab)
4273
- })]
4274
- }),
4275
- ribbonType !== "grid" && fakeToolbar
4276
- ] })
4581
+ })
4582
+ })] }, effectiveActivatedTab)
4583
+ })]
4584
+ }),
4585
+ ribbonType !== "grid" && fakeToolbar
4586
+ ] });
4587
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RibbonOverrideRuntimeProvider, {
4588
+ override: ribbonOverride,
4589
+ children: content
4277
4590
  });
4278
4591
  }
4279
4592
  function RibbonOverrideRuntimeProvider(props) {
@@ -4720,35 +5033,36 @@ function UITinyMenuGroup(props) {
4720
5033
  item.children
4721
5034
  ]);
4722
5035
  if (!item.children) return null;
5036
+ const items = visibleChildren.map((child) => {
5037
+ var _child$item4, _child$item12, _child$item13, _child$item14, _child$item15;
5038
+ const Icon = ((_child$item4 = child.item) === null || _child$item4 === void 0 ? void 0 : _child$item4.icon) ? iconManager.get(child.item.icon) : void 0;
5039
+ if (!Icon) return null;
5040
+ return {
5041
+ key: child.key,
5042
+ onClick: () => {
5043
+ var _child$item5, _child$item6, _child$item7, _child$item8, _child$item9, _child$item10, _child$item11;
5044
+ onOptionSelect === null || onOptionSelect === void 0 || onOptionSelect({
5045
+ label: ((_child$item5 = child.item) === null || _child$item5 === void 0 ? void 0 : _child$item5.id) ?? child.key,
5046
+ commandId: (_child$item6 = child.item) === null || _child$item6 === void 0 ? void 0 : _child$item6.commandId,
5047
+ id: (_child$item7 = child.item) === null || _child$item7 === void 0 ? void 0 : _child$item7.id,
5048
+ params: (_child$item8 = child.item) === null || _child$item8 === void 0 ? void 0 : _child$item8.params,
5049
+ value: (_child$item9 = child.item) === null || _child$item9 === void 0 ? void 0 : _child$item9.value,
5050
+ tooltip: ((_child$item10 = child.item) === null || _child$item10 === void 0 ? void 0 : _child$item10.tooltip) && localeService.t((_child$item11 = child.item) === null || _child$item11 === void 0 ? void 0 : _child$item11.tooltip)
5051
+ });
5052
+ },
5053
+ className: "",
5054
+ iconClassName: ((_child$item12 = child.item) === null || _child$item12 === void 0 ? void 0 : _child$item12.icon) === "TextTypeIcon" ? sizeVariant === "paragraph-t" ? "!univer-size-4" : "!univer-size-3.5" : void 0,
5055
+ Icon,
5056
+ active: resolveMenuItemActiveState((_child$item13 = child.item) === null || _child$item13 === void 0 ? void 0 : _child$item13.id, activeItems.includes(((_child$item14 = child.item) === null || _child$item14 === void 0 ? void 0 : _child$item14.id) ?? ""), activeItemIds),
5057
+ tooltip: ((_child$item15 = child.item) === null || _child$item15 === void 0 ? void 0 : _child$item15.tooltip) ? localeService.t(child.item.tooltip) : void 0
5058
+ };
5059
+ }).filter((child) => child != null);
4723
5060
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DesignTinyMenuGroup, {
4724
5061
  columns,
4725
5062
  sizeVariant,
4726
5063
  layoutVariant,
4727
5064
  hoverSuppressed,
4728
- items: visibleChildren.map((child) => {
4729
- var _child$item4, _child$item12, _child$item13, _child$item14, _child$item15;
4730
- const Icon = ((_child$item4 = child.item) === null || _child$item4 === void 0 ? void 0 : _child$item4.icon) ? iconManager.get(child.item.icon) : void 0;
4731
- if (!Icon) return null;
4732
- return {
4733
- key: child.key,
4734
- onClick: () => {
4735
- var _child$item5, _child$item6, _child$item7, _child$item8, _child$item9, _child$item10, _child$item11;
4736
- onOptionSelect === null || onOptionSelect === void 0 || onOptionSelect({
4737
- label: ((_child$item5 = child.item) === null || _child$item5 === void 0 ? void 0 : _child$item5.id) ?? child.key,
4738
- commandId: (_child$item6 = child.item) === null || _child$item6 === void 0 ? void 0 : _child$item6.commandId,
4739
- id: (_child$item7 = child.item) === null || _child$item7 === void 0 ? void 0 : _child$item7.id,
4740
- params: (_child$item8 = child.item) === null || _child$item8 === void 0 ? void 0 : _child$item8.params,
4741
- value: (_child$item9 = child.item) === null || _child$item9 === void 0 ? void 0 : _child$item9.value,
4742
- tooltip: ((_child$item10 = child.item) === null || _child$item10 === void 0 ? void 0 : _child$item10.tooltip) && localeService.t((_child$item11 = child.item) === null || _child$item11 === void 0 ? void 0 : _child$item11.tooltip)
4743
- });
4744
- },
4745
- className: "",
4746
- iconClassName: ((_child$item12 = child.item) === null || _child$item12 === void 0 ? void 0 : _child$item12.icon) === "TextTypeIcon" ? sizeVariant === "paragraph-t" ? "!univer-size-4" : "!univer-size-3.5" : void 0,
4747
- Icon,
4748
- active: resolveMenuItemActiveState((_child$item13 = child.item) === null || _child$item13 === void 0 ? void 0 : _child$item13.id, activeItems.includes(((_child$item14 = child.item) === null || _child$item14 === void 0 ? void 0 : _child$item14.id) ?? ""), activeItemIds),
4749
- tooltip: ((_child$item15 = child.item) === null || _child$item15 === void 0 ? void 0 : _child$item15.tooltip) ? localeService.t(child.item.tooltip) : void 0
4750
- };
4751
- }).filter((child) => child != null)
5065
+ items
4752
5066
  });
4753
5067
  }
4754
5068
  function UIQuickTileMenuGroup(props) {
@@ -5107,13 +5421,15 @@ function ContextMenuPanel(props) {
5107
5421
  const [menuElement, setMenuElement] = (0, react.useState)(null);
5108
5422
  const [maxMenuHeight, setMaxMenuHeight] = (0, react.useState)(() => {
5109
5423
  if (typeof window === "undefined") return 240;
5110
- return Math.max(120, window.innerHeight - menuViewportPadding * 2);
5424
+ return Math.max(120, window.innerHeight - 16);
5111
5425
  });
5112
5426
  const [hoverSuppressed, setHoverSuppressed] = (0, react.useState)(suppressHoverUntilPointerMove);
5427
+ const menuSchemaVersion$ = (0, react.useMemo)(() => menuManagerService.menuChanged$.pipe((0, rxjs.startWith)(void 0), (0, rxjs.scan)((version) => version + 1, 0)), [menuManagerService]);
5428
+ const menuSchemaVersion = (0, _wendellhu_redi_react_bindings.useObservable)(menuSchemaVersion$, 0);
5113
5429
  const menuItems = (0, react.useMemo)(() => menuType ? menuManagerService.getMenuByPositionKey(menuType) : [], [
5114
5430
  menuManagerService,
5115
5431
  menuType,
5116
- (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => menuManagerService.menuChanged$.pipe((0, rxjs.startWith)(void 0), (0, rxjs.scan)((version) => version + 1, 0)), [menuManagerService]), 0),
5432
+ menuSchemaVersion,
5117
5433
  menuSessionVersion
5118
5434
  ]);
5119
5435
  const submenuPortalContainer = ((_layoutService$rootCo = layoutService.rootContainerElement) === null || _layoutService$rootCo === void 0 || (_layoutService$rootCo = _layoutService$rootCo.ownerDocument) === null || _layoutService$rootCo === void 0 ? void 0 : _layoutService$rootCo.body) ?? (typeof document !== "undefined" ? document.body : null);
@@ -5187,7 +5503,7 @@ function ContextMenuPanel(props) {
5187
5503
  const updateMaxHeight = () => {
5188
5504
  if (frameId) defaultView.cancelAnimationFrame(frameId);
5189
5505
  frameId = defaultView.requestAnimationFrame(() => {
5190
- setMaxMenuHeight(Math.max(120, defaultView.innerHeight - menuViewportPadding * 2));
5506
+ setMaxMenuHeight(Math.max(120, defaultView.innerHeight - 16));
5191
5507
  });
5192
5508
  };
5193
5509
  updateMaxHeight();
@@ -5729,7 +6045,7 @@ function ContextMenuMenuItem(props) {
5729
6045
  });
5730
6046
  }
5731
6047
  function useContextGroupHiddenStates$1(menuSchemas) {
5732
- return (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => {
6048
+ const hiddenStates$ = (0, react.useMemo)(() => {
5733
6049
  const groupStates = menuSchemas.flatMap((menuSchema) => {
5734
6050
  var _menuSchema$children3;
5735
6051
  const hiddenObservables = ((_menuSchema$children3 = menuSchema.children) === null || _menuSchema$children3 === void 0 ? void 0 : _menuSchema$children3.map((childSchema) => {
@@ -5742,7 +6058,8 @@ function useContextGroupHiddenStates$1(menuSchemas) {
5742
6058
  ...states,
5743
6059
  [key]: hidden
5744
6060
  }), {}), (0, rxjs.startWith)({})) : (0, rxjs.of)({});
5745
- }, [menuSchemas]), {});
6061
+ }, [menuSchemas]);
6062
+ return (0, _wendellhu_redi_react_bindings.useObservable)(hiddenStates$, {});
5746
6063
  }
5747
6064
 
5748
6065
  //#endregion
@@ -6404,7 +6721,8 @@ function DesktopWorkbench(props) {
6404
6721
  });
6405
6722
  }
6406
6723
  function mountDesktopWorkbench(injector, options, mountContainer, onRendered) {
6407
- (0, _univerjs_design.render)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)((0, _wendellhu_redi_react_bindings.connectInjector)(DesktopWorkbench, injector), {
6724
+ const ConnectedApp = (0, _wendellhu_redi_react_bindings.connectInjector)(DesktopWorkbench, injector);
6725
+ (0, _univerjs_design.render)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConnectedApp, {
6408
6726
  ...options,
6409
6727
  mountContainer,
6410
6728
  onRendered
@@ -6539,7 +6857,8 @@ function DesktopWorkbenchContent(props) {
6539
6857
  }
6540
6858
  function FloatingContainer() {
6541
6859
  const { mountContainer } = (0, react.useContext)(_univerjs_design.ConfigContext);
6542
- return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, { components: useComponentsOfPart("floating") }, "floating"), mountContainer);
6860
+ const floatingComponents = useComponentsOfPart("floating");
6861
+ return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, { components: floatingComponents }, "floating"), mountContainer);
6543
6862
  }
6544
6863
 
6545
6864
  //#endregion
@@ -6687,7 +7006,7 @@ const IUIController = (0, _univerjs_core.createIdentifier)("univer.ui.ui-control
6687
7006
  //#endregion
6688
7007
  //#region package.json
6689
7008
  var name = "@univerjs/ui";
6690
- var version = "1.0.0-rc.0";
7009
+ var version = "1.0.0";
6691
7010
 
6692
7011
  //#endregion
6693
7012
  //#region src/views/color-picker/interface.ts
@@ -6728,13 +7047,14 @@ const COLOR_PICKER_COMPONENT = "UI_COLOR_PICKER_COMPONENT";
6728
7047
  const CommonLabel = (props) => {
6729
7048
  const { value, selections } = props;
6730
7049
  const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
7050
+ const viewValue = (0, react.useMemo)(() => {
7051
+ var _selections$find;
7052
+ if (value == null) return "";
7053
+ return localeService.t(((_selections$find = selections.find((item) => item.value === value)) === null || _selections$find === void 0 ? void 0 : _selections$find.label) ?? "");
7054
+ }, [value, selections]);
6731
7055
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
6732
7056
  className: "univer-truncate univer-text-sm",
6733
- children: (0, react.useMemo)(() => {
6734
- var _selections$find;
6735
- if (value == null) return "";
6736
- return localeService.t(((_selections$find = selections.find((item) => item.value === value)) === null || _selections$find === void 0 ? void 0 : _selections$find.label) ?? "");
6737
- }, [value, selections])
7057
+ children: viewValue
6738
7058
  });
6739
7059
  };
6740
7060
  const COMMON_LABEL_COMPONENT = "UI_PLUGIN_COMMON_LABEL_COMPONENT";
@@ -22938,10 +23258,11 @@ let FontService = class FontService {
22938
23258
  _defineProperty(this, "fonts$", new rxjs.BehaviorSubject([]));
22939
23259
  const { customFontFamily } = this._configService.getConfig("ui.config") ?? {};
22940
23260
  let fonts = [];
22941
- if (customFontFamily) if (Array.isArray(customFontFamily)) fonts = [...DEFAULT_FONT_LIST, ...customFontFamily];
22942
- else if (customFontFamily.override) fonts = [...customFontFamily.list];
22943
- else fonts = [...DEFAULT_FONT_LIST, ...customFontFamily.list];
22944
- else fonts = [...DEFAULT_FONT_LIST];
23261
+ if (customFontFamily) {
23262
+ if (Array.isArray(customFontFamily)) fonts = [...DEFAULT_FONT_LIST, ...customFontFamily];
23263
+ else if (customFontFamily.override) fonts = [...customFontFamily.list];
23264
+ else fonts = [...DEFAULT_FONT_LIST, ...customFontFamily.list];
23265
+ } else fonts = [...DEFAULT_FONT_LIST];
22945
23266
  this.fonts$.next(fonts);
22946
23267
  }
22947
23268
  dispose() {
@@ -23487,11 +23808,12 @@ function SymbolPicker(props) {
23487
23808
  });
23488
23809
  }
23489
23810
  function SymbolSection(props) {
23811
+ const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
23490
23812
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
23491
23813
  className: "univer-flex univer-flex-col univer-gap-2",
23492
23814
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
23493
23815
  className: "univer-text-sm univer-font-semibold univer-text-gray-900 dark:!univer-text-gray-100",
23494
- children: (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService).t(props.category.titleKey)
23816
+ children: localeService.t(props.category.titleKey)
23495
23817
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
23496
23818
  className: "univer-grid univer-grid-cols-10 univer-gap-1",
23497
23819
  children: props.category.symbols.map((symbol, index) => {
@@ -23608,7 +23930,8 @@ function MobileRibbon(props) {
23608
23930
  const workbenchService = (0, _wendellhu_redi_react_bindings.useDependency)(IWorkbenchService);
23609
23931
  const ribbon = (0, _wendellhu_redi_react_bindings.useObservable)(ribbonService.ribbon$, []);
23610
23932
  const activatedTab = (0, _wendellhu_redi_react_bindings.useObservable)(ribbonService.activatedTab$, "ribbon.start");
23611
- if ((0, _wendellhu_redi_react_bindings.useObservable)(workbenchService.rootUnitType$, null, true) === _univerjs_core.UniverInstanceType.UNIVER_SHEET) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileSheetTopBar, {
23933
+ const rootUnitType = (0, _wendellhu_redi_react_bindings.useObservable)(workbenchService.rootUnitType$, null, true);
23934
+ if (rootUnitType === _univerjs_core.UniverInstanceType.UNIVER_SHEET || rootUnitType === _univerjs_core.UniverInstanceType.UNIVER_DOC) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileCompactTopBar, {
23612
23935
  ribbon,
23613
23936
  headerMenu,
23614
23937
  headerMenuComponents
@@ -23649,11 +23972,12 @@ function MobileRibbonToolbar(props) {
23649
23972
  setCanScrollLeft(scrollLeft > 4);
23650
23973
  setCanScrollRight(scrollLeft + clientWidth < scrollWidth - 4);
23651
23974
  };
23652
- updateScrollState();
23975
+ const animationFrame = requestAnimationFrame(updateScrollState);
23653
23976
  const resizeObserver = new ResizeObserver(updateScrollState);
23654
23977
  resizeObserver.observe(container);
23655
23978
  container.addEventListener("scroll", updateScrollState, { passive: true });
23656
23979
  return () => {
23980
+ cancelAnimationFrame(animationFrame);
23657
23981
  resizeObserver.disconnect();
23658
23982
  container.removeEventListener("scroll", updateScrollState);
23659
23983
  };
@@ -23793,7 +24117,7 @@ function MobileRibbonToolbar(props) {
23793
24117
  })]
23794
24118
  });
23795
24119
  }
23796
- function MobileSheetTopBar(props) {
24120
+ function MobileCompactTopBar(props) {
23797
24121
  var _startGroup$children, _startGroup$children2, _moreTriggerRef$curre, _moreTriggerRef$curre2;
23798
24122
  const { headerMenuComponents, headerMenu = true, ribbon } = props;
23799
24123
  const [moreOpen, setMoreOpen] = (0, react.useState)(false);
@@ -23818,7 +24142,7 @@ function MobileSheetTopBar(props) {
23818
24142
  className: (0, _univerjs_design.clsx)(_univerjs_design.resetButtonClassName, "univer-fixed univer-inset-0 univer-z-[1390] !univer-rounded-none !univer-bg-transparent"),
23819
24143
  onClick: () => setMoreOpen(false)
23820
24144
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
23821
- "data-u-comp": "mobile-sheet-more-menu",
24145
+ "data-u-comp": "mobile-more-menu",
23822
24146
  className: (0, _univerjs_design.clsx)("univer-fixed univer-z-[1400] univer-flex univer-w-60 univer-max-w-[calc(100vw-24px)] univer-flex-col univer-gap-1 univer-rounded-2xl univer-bg-gray-0 univer-p-2 univer-shadow-lg dark:!univer-bg-gray-800", _univerjs_design.borderClassName),
23823
24147
  style: {
23824
24148
  top: ((triggerRect === null || triggerRect === void 0 ? void 0 : triggerRect.bottom) ?? 48) + 8,
@@ -23836,21 +24160,17 @@ function MobileSheetTopBar(props) {
23836
24160
  }, schema.key))
23837
24161
  })] }), mountContainer);
23838
24162
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
23839
- "data-u-comp": "mobile-sheet-top-bar",
24163
+ "data-u-comp": "mobile-compact-top-bar",
23840
24164
  className: (0, _univerjs_design.clsx)("univer-flex univer-h-12 univer-items-center univer-justify-end univer-gap-1 univer-bg-gray-0 univer-px-3 dark:!univer-bg-gray-800", _univerjs_design.borderBottomClassName),
23841
24165
  children: [
23842
24166
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
23843
24167
  className: "univer-flex univer-items-center univer-gap-1 [&_button]:!univer-min-h-10 [&_button]:!univer-min-w-10 [&_button]:!univer-rounded-lg [&_button_svg]:!univer-size-5",
23844
24168
  children: items.map((schema) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileToolbarItem, { ...schema.item }, schema.key))
23845
24169
  }),
23846
- hasHeaderMenu && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
23847
- className: "univer-flex univer-items-center univer-gap-1 [&>*]:univer-m-0 [&>*]:univer-inline-flex [&>*]:univer-min-h-10 [&>*]:univer-min-w-10 [&>*]:univer-items-center [&>*]:univer-justify-center [&>*]:univer-rounded-lg",
23848
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, { components: headerMenuComponents })
23849
- }),
23850
24170
  moreItems.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
23851
24171
  ref: moreTriggerRef,
23852
24172
  type: "button",
23853
- "data-u-comp": "mobile-sheet-more-trigger",
24173
+ "data-u-comp": "mobile-more-trigger",
23854
24174
  "aria-label": localeService.t("ui.ribbon.more"),
23855
24175
  "aria-expanded": moreOpen,
23856
24176
  className: (0, _univerjs_design.clsx)(_univerjs_design.resetButtonClassName, "univer-flex univer-size-10 univer-items-center univer-justify-center univer-rounded-lg univer-text-gray-700 univer-transition-colors active:univer-bg-gray-100 dark:!univer-text-gray-200 dark:active:!univer-bg-gray-700"),
@@ -23859,230 +24179,33 @@ function MobileSheetTopBar(props) {
23859
24179
  className: "univer-size-5",
23860
24180
  preserveStrokeWidth: true
23861
24181
  })
24182
+ }),
24183
+ hasHeaderMenu && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
24184
+ className: "univer-flex univer-items-center univer-gap-1 [&>*]:univer-m-0 [&>*]:univer-inline-flex [&>*]:univer-min-h-10 [&>*]:univer-min-w-10 [&>*]:univer-items-center [&>*]:univer-justify-center [&>*]:univer-rounded-lg",
24185
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, { components: headerMenuComponents })
23862
24186
  })
23863
24187
  ]
23864
24188
  }), moreMenu] });
23865
24189
  }
23866
24190
 
23867
24191
  //#endregion
23868
- //#region src/views/components/mobile-drawer/MobileDrawerCoordinator.tsx
23869
- const MobileDrawerCoordinatorContext = (0, react.createContext)(null);
23870
- function MobileDrawerCoordinatorProvider(props) {
23871
- const entriesRef = (0, react.useRef)([]);
23872
- const [activeDrawerId, setActiveDrawerId] = (0, react.useState)(null);
23873
- const setEntries = (0, react.useCallback)((entries) => {
23874
- entriesRef.current = entries;
23875
- setActiveDrawerId(entries.length ? entries[entries.length - 1].id : null);
23876
- }, []);
23877
- const unregister = (0, react.useCallback)((id) => {
23878
- setEntries(entriesRef.current.filter((entry) => entry.id !== id));
23879
- }, [setEntries]);
23880
- const close = (0, react.useCallback)((id) => {
23881
- const entry = entriesRef.current.find((item) => item.id === id);
23882
- if (!entry) return;
23883
- unregister(id);
23884
- entry.onClose();
23885
- }, [unregister]);
23886
- const register = (0, react.useCallback)((id, mode, onClose) => {
23887
- const entry = {
23888
- id,
23889
- onClose
23890
- };
23891
- if (mode === "push") {
23892
- setEntries([...entriesRef.current, entry]);
23893
- return;
23894
- }
23895
- const previousEntries = entriesRef.current;
23896
- setEntries([entry]);
23897
- for (let i = previousEntries.length - 1; i >= 0; i--) previousEntries[i].onClose();
23898
- }, [setEntries]);
23899
- const value = (0, react.useMemo)(() => ({
23900
- activeDrawerId,
23901
- close,
23902
- register,
23903
- unregister
23904
- }), [
23905
- activeDrawerId,
23906
- close,
23907
- register,
23908
- unregister
23909
- ]);
23910
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileDrawerCoordinatorContext.Provider, {
23911
- value,
23912
- children: props.children
23913
- });
24192
+ //#region src/views/menu/mobile/MobileMenu.tsx
24193
+ function MobileMenu(props) {
24194
+ var _props$schemas;
24195
+ const schemaKey = ((_props$schemas = props.schemas) === null || _props$schemas === void 0 ? void 0 : _props$schemas.map((schema) => schema.key).join("|")) ?? "";
24196
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileMenuContent, { ...props }, `${props.menuType ?? ""}:${schemaKey}`);
23914
24197
  }
23915
-
23916
- //#endregion
23917
- //#region src/views/components/mobile-drawer/MobileDrawer.tsx
23918
- const MOBILE_DRAWER_COMPACT_PERCENT = 40;
23919
- const MOBILE_DRAWER_EXPANDED_PERCENT = 80;
23920
- function resolveMobileDrawerRelease(params) {
23921
- const { snap, deltaY, durationMs, percent } = params;
23922
- const velocity = deltaY / Math.max(durationMs, 1);
23923
- if (deltaY > 48 && velocity > .55 || percent < 20) return "closed";
23924
- if (snap === "expanded" && deltaY > 24) return "compact";
23925
- if (snap === "compact" && deltaY < -24) return "expanded";
23926
- return percent >= 60 ? "expanded" : "compact";
23927
- }
23928
- function MobileDrawer(props) {
23929
- var _globalThis$CSS;
23930
- const { snap, expandLabel, collapseLabel, onSnapChange, onClose, children, header, floatingActions, componentName = "mobile-drawer", panelRef, contentRef, layerRef, openMode = "replace", panelClassName, contentClassName, footer, role, ariaLabel } = props;
23931
- const coordinator = (0, react.useContext)(MobileDrawerCoordinatorContext);
23932
- const registerDrawer = coordinator === null || coordinator === void 0 ? void 0 : coordinator.register;
23933
- const unregisterDrawer = coordinator === null || coordinator === void 0 ? void 0 : coordinator.unregister;
23934
- const panelElementRef = (0, react.useRef)(null);
23935
- const drawerIdRef = (0, react.useRef)(null);
23936
- const onCloseRef = (0, react.useRef)(onClose);
23937
- onCloseRef.current = onClose;
23938
- if (!drawerIdRef.current) drawerIdRef.current = Symbol(componentName);
23939
- const drawerId = drawerIdRef.current;
23940
- const active = !coordinator || coordinator.activeDrawerId === drawerId;
23941
- const [dragPercent, setDragPercent] = (0, react.useState)(null);
23942
- const suppressHandleClickRef = (0, react.useRef)(false);
23943
- const dragRef = (0, react.useRef)(null);
23944
- const drawerPercent = dragPercent ?? (snap === "compact" ? MOBILE_DRAWER_COMPACT_PERCENT : MOBILE_DRAWER_EXPANDED_PERCENT);
23945
- const viewportHeightUnit = ((_globalThis$CSS = globalThis.CSS) === null || _globalThis$CSS === void 0 ? void 0 : _globalThis$CSS.supports("height", "1dvh")) ? "dvh" : "vh";
23946
- (0, react.useImperativeHandle)(panelRef, () => panelElementRef.current);
23947
- (0, react.useLayoutEffect)(() => {
23948
- if (!registerDrawer || !unregisterDrawer) return;
23949
- registerDrawer(drawerId, openMode, () => onCloseRef.current());
23950
- return () => unregisterDrawer(drawerId);
23951
- }, [
23952
- drawerId,
23953
- openMode,
23954
- registerDrawer,
23955
- unregisterDrawer
23956
- ]);
23957
- (0, react.useLayoutEffect)(() => {
23958
- var _panelElementRef$curr;
23959
- const layer = (layerRef === null || layerRef === void 0 ? void 0 : layerRef.current) ?? (layerRef ? (_panelElementRef$curr = panelElementRef.current) === null || _panelElementRef$curr === void 0 ? void 0 : _panelElementRef$curr.parentElement : null);
23960
- if (!layer) return;
23961
- layer.toggleAttribute("hidden", !active);
23962
- }, [active, layerRef]);
23963
- function beginDrag(clientY) {
23964
- dragRef.current = {
23965
- startY: clientY,
23966
- startTime: performance.now(),
23967
- startPercent: drawerPercent,
23968
- currentPercent: drawerPercent,
23969
- moved: false
23970
- };
23971
- }
23972
- function moveDrag(clientY) {
23973
- const drag = dragRef.current;
23974
- if (!drag) return;
23975
- const deltaY = clientY - drag.startY;
23976
- const nextPercent = Math.max(0, Math.min(MOBILE_DRAWER_EXPANDED_PERCENT, drag.startPercent - deltaY / Math.max(window.innerHeight, 1) * 100));
23977
- drag.currentPercent = nextPercent;
23978
- drag.moved ||= Math.abs(deltaY) > 6;
23979
- setDragPercent(nextPercent);
23980
- }
23981
- function endDrag(clientY) {
23982
- const drag = dragRef.current;
23983
- if (!drag) return;
23984
- const result = resolveMobileDrawerRelease({
23985
- snap,
23986
- deltaY: clientY - drag.startY,
23987
- durationMs: performance.now() - drag.startTime,
23988
- percent: drag.currentPercent
23989
- });
23990
- suppressHandleClickRef.current = drag.moved;
23991
- dragRef.current = null;
23992
- setDragPercent(null);
23993
- if (result === "closed") if (coordinator) coordinator.close(drawerId);
23994
- else onClose();
23995
- else onSnapChange(result);
23996
- }
23997
- function handlePointerDown(event) {
23998
- try {
23999
- event.currentTarget.setPointerCapture(event.pointerId);
24000
- } catch {}
24001
- beginDrag(event.clientY);
24002
- }
24003
- function handlePointerMove(event) {
24004
- moveDrag(event.clientY);
24005
- }
24006
- function handlePointerUp(event) {
24007
- endDrag(event.clientY);
24008
- }
24009
- function handlePointerCancel() {
24010
- dragRef.current = null;
24011
- setDragPercent(null);
24012
- }
24013
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [floatingActions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
24014
- className: "univer-pointer-events-none univer-absolute univer-right-4 univer-z-30",
24015
- style: { bottom: `calc(${drawerPercent}${viewportHeightUnit} + 12px)` },
24016
- children: floatingActions
24017
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
24018
- ref: panelElementRef,
24019
- hidden: !active,
24020
- role,
24021
- "aria-modal": role === "dialog" || void 0,
24022
- "aria-label": ariaLabel,
24023
- "data-u-comp": componentName,
24024
- "data-snap": snap,
24025
- className: (0, _univerjs_design.clsx)("univer-absolute univer-inset-x-0 univer-bottom-0 univer-z-20 univer-flex univer-flex-col univer-overflow-hidden univer-rounded-t-[24px] univer-bg-gray-50 univer-shadow-2xl univer-transition-[height] univer-duration-200 dark:!univer-bg-gray-900", dragPercent != null && "!univer-transition-none", panelClassName),
24026
- style: {
24027
- height: `${drawerPercent}${viewportHeightUnit}`,
24028
- paddingBottom: "env(safe-area-inset-bottom, 0px)"
24029
- },
24030
- children: [
24031
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
24032
- className: "univer-relative univer-flex univer-h-14 univer-shrink-0 univer-items-end univer-bg-gray-0 dark:!univer-bg-gray-800",
24033
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
24034
- type: "button",
24035
- "aria-label": snap === "compact" ? expandLabel : collapseLabel,
24036
- className: (0, _univerjs_design.clsx)(_univerjs_design.resetButtonClassName, "univer-absolute univer-left-1/2 univer-top-0 univer-z-10 univer-flex univer-h-6 univer-w-16 -univer-translate-x-1/2 univer-touch-none univer-items-center univer-justify-center"),
24037
- style: { touchAction: "none" },
24038
- onPointerDown: handlePointerDown,
24039
- onPointerMove: handlePointerMove,
24040
- onPointerUp: handlePointerUp,
24041
- onPointerCancel: handlePointerCancel,
24042
- onClick: () => {
24043
- if (suppressHandleClickRef.current) {
24044
- suppressHandleClickRef.current = false;
24045
- return;
24046
- }
24047
- onSnapChange(snap === "compact" ? "expanded" : "compact");
24048
- },
24049
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "univer-h-1 univer-w-10 univer-rounded-full univer-bg-gray-300 dark:!univer-bg-gray-600" })
24050
- }), header]
24051
- }),
24052
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
24053
- ref: contentRef,
24054
- className: (0, _univerjs_design.clsx)("univer-flex-1 univer-overflow-y-auto univer-overflow-x-hidden univer-p-3", _univerjs_design.scrollbarClassName, contentClassName),
24055
- children
24056
- }),
24057
- footer
24058
- ]
24059
- })] });
24060
- }
24061
-
24062
- //#endregion
24063
- //#region src/views/menu/mobile/MobileMenu.tsx
24064
- function MobileMenu(props) {
24198
+ function MobileMenuContent(props) {
24065
24199
  const { menuType, onOptionSelect, schemas: providedSchemas, menuManagerService: providedMenuManagerService, showHeader = true, presentation = "drawer", onNavigationChange } = props;
24066
24200
  const rootMenuManagerService = (0, _wendellhu_redi_react_bindings.useDependency)(IMenuManagerService);
24067
24201
  const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
24068
24202
  const menuManagerService = providedMenuManagerService ?? rootMenuManagerService;
24069
24203
  const [viewStack, setViewStack] = (0, react.useState)([]);
24070
- const providedSchemaKey = providedSchemas === null || providedSchemas === void 0 ? void 0 : providedSchemas.map((schema) => schema.key).join("|");
24071
- const menuSchemas = (0, react.useMemo)(() => {
24072
- if (providedSchemas) return providedSchemas;
24073
- if (!menuType) return [];
24074
- return menuManagerService.getMenuByPositionKey(menuType);
24075
- }, [
24076
- providedSchemas,
24077
- menuManagerService,
24078
- (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => {
24079
- return menuManagerService.menuChanged$.pipe((0, rxjs_operators.scan)((version) => version + 1, 0), (0, rxjs_operators.startWith)(0));
24080
- }, [menuManagerService]), 0),
24081
- menuType
24082
- ]);
24083
- (0, react.useEffect)(() => {
24084
- setViewStack([]);
24085
- }, [menuType, providedSchemaKey]);
24204
+ const menuSchemaVersion$ = (0, react.useMemo)(() => {
24205
+ return menuManagerService.menuChanged$.pipe((0, rxjs_operators.scan)((version) => version + 1, 0), (0, rxjs_operators.startWith)(0));
24206
+ }, [menuManagerService]);
24207
+ (0, _wendellhu_redi_react_bindings.useObservable)(menuSchemaVersion$, 0);
24208
+ const menuSchemas = providedSchemas ?? (menuType ? menuManagerService.getMenuByPositionKey(menuType) : []);
24086
24209
  const currentView = viewStack[viewStack.length - 1] ?? null;
24087
24210
  const closeView = (0, react.useCallback)(() => setViewStack((stack) => stack.slice(0, -1)), []);
24088
24211
  (0, react.useEffect)(() => {
@@ -24113,7 +24236,7 @@ function MobileMenu(props) {
24113
24236
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
24114
24237
  type: "button",
24115
24238
  "aria-label": localeService.t("ui.navigation.back"),
24116
- className: "univer-flex univer-size-8 univer-appearance-none univer-items-center univer-justify-center univer-rounded-full univer-border-0 univer-bg-transparent univer-p-0 univer-text-gray-700 hover:univer-bg-gray-100 active:univer-bg-gray-200 dark:!univer-text-gray-300 dark:hover:!univer-bg-gray-700 dark:active:!univer-bg-gray-600",
24239
+ className: "univer-flex univer-size-8 univer-appearance-none univer-items-center univer-justify-center univer-rounded-full univer-border-0 univer-bg-transparent univer-p-0 univer-text-gray-700 active:univer-bg-gray-200 dark:!univer-text-gray-300 dark:active:!univer-bg-gray-600",
24117
24240
  onClick: closeView,
24118
24241
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.MoreLeftIcon, { className: "univer-text-base" })
24119
24242
  }),
@@ -24185,15 +24308,17 @@ function MobileContextMenuBar(props) {
24185
24308
  behavior: "smooth"
24186
24309
  });
24187
24310
  };
24311
+ const showLeft = Boolean(currentView) || scrollState.left;
24188
24312
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
24189
24313
  role: "menu",
24190
24314
  "data-u-comp": "mobile-context-menu-bar",
24191
- className: "univer-flex univer-h-12 univer-max-w-full univer-items-stretch univer-overflow-hidden univer-rounded-lg univer-bg-gray-0 univer-text-sm univer-text-gray-900 univer-shadow-lg dark:!univer-bg-gray-700 dark:!univer-text-gray-0",
24315
+ style: { maxWidth: "min(100%, calc(100vw - 16px))" },
24316
+ className: "univer-flex univer-h-10 univer-max-w-full univer-items-stretch univer-overflow-hidden univer-rounded-lg univer-bg-gray-0 univer-text-xs univer-text-gray-900 univer-shadow-lg dark:!univer-bg-gray-700 dark:!univer-text-gray-0",
24192
24317
  children: [
24193
- (Boolean(currentView) || scrollState.left) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
24318
+ showLeft && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
24194
24319
  type: "button",
24195
24320
  "aria-label": localeService.t("ui.navigation.back"),
24196
- className: "univer-flex univer-w-11 univer-shrink-0 univer-items-center univer-justify-center univer-border-0 univer-border-r univer-border-solid univer-border-gray-200 univer-bg-transparent univer-text-base univer-text-gray-700 univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 active:univer-bg-gray-100 dark:!univer-border-gray-600 dark:!univer-text-gray-200 dark:active:!univer-bg-gray-600",
24321
+ className: "univer-flex univer-w-9 univer-shrink-0 univer-items-center univer-justify-center univer-border-0 univer-border-r univer-border-solid univer-border-gray-200 univer-bg-transparent univer-text-base univer-text-gray-700 univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 active:univer-bg-gray-100 dark:!univer-border-gray-600 dark:!univer-text-gray-200 dark:active:!univer-bg-gray-600",
24197
24322
  onClick: () => scrollState.left ? scroll(-1) : onBack(),
24198
24323
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.MoreLeftIcon, {})
24199
24324
  }),
@@ -24220,7 +24345,7 @@ function MobileContextMenuBar(props) {
24220
24345
  scrollState.right && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
24221
24346
  type: "button",
24222
24347
  "aria-label": localeService.t("ui.navigation.next"),
24223
- className: "univer-flex univer-w-11 univer-shrink-0 univer-items-center univer-justify-center univer-border-0 univer-border-l univer-border-solid univer-border-gray-200 univer-bg-transparent univer-text-base univer-text-gray-700 univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 active:univer-bg-gray-100 dark:!univer-border-gray-600 dark:!univer-text-gray-200 dark:active:!univer-bg-gray-600",
24348
+ className: "univer-flex univer-w-9 univer-shrink-0 univer-items-center univer-justify-center univer-border-0 univer-border-l univer-border-solid univer-border-gray-200 univer-bg-transparent univer-text-base univer-text-gray-700 univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 active:univer-bg-gray-100 dark:!univer-border-gray-600 dark:!univer-text-gray-200 dark:active:!univer-bg-gray-600",
24224
24349
  onClick: () => scroll(1),
24225
24350
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.MoreRightIcon, {})
24226
24351
  })
@@ -24241,7 +24366,7 @@ function MobileContextMenuItem(props) {
24241
24366
  type: "button",
24242
24367
  role: "menuitem",
24243
24368
  disabled: interaction.disabled,
24244
- className: "univer-flex univer-min-w-[72px] univer-shrink-0 univer-snap-start univer-items-center univer-justify-center univer-border-0 univer-border-r univer-border-solid univer-border-gray-200 univer-bg-transparent univer-px-4 univer-text-sm univer-text-gray-900 univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 enabled:active:univer-bg-gray-100 disabled:univer-opacity-40 dark:!univer-border-gray-600 dark:!univer-text-gray-0 dark:enabled:active:!univer-bg-gray-600",
24369
+ className: "univer-flex univer-min-w-[60px] univer-shrink-0 univer-snap-start univer-items-center univer-justify-center univer-border-0 univer-border-r univer-border-solid univer-border-gray-200 univer-bg-transparent univer-px-3 univer-text-xs univer-text-gray-900 univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 enabled:active:univer-bg-gray-100 disabled:univer-opacity-40 dark:!univer-border-gray-600 dark:!univer-text-gray-0 dark:enabled:active:!univer-bg-gray-600",
24245
24370
  onClick: () => interaction.onPress(onExecute),
24246
24371
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
24247
24372
  className: "univer-whitespace-nowrap",
@@ -24260,13 +24385,13 @@ function MobileContextMenuOption(props) {
24260
24385
  role: "menuitem",
24261
24386
  "aria-pressed": displayValue === currentValue,
24262
24387
  disabled,
24263
- className: "univer-flex univer-min-w-[72px] univer-shrink-0 univer-snap-start univer-items-center univer-justify-center univer-border-0 univer-border-r univer-border-solid univer-border-gray-200 univer-bg-transparent univer-px-4 univer-text-sm univer-text-gray-900 univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 enabled:active:univer-bg-gray-100 disabled:univer-opacity-40 dark:!univer-border-gray-600 dark:!univer-text-gray-0 dark:enabled:active:!univer-bg-gray-600",
24388
+ className: "univer-flex univer-min-w-[60px] univer-shrink-0 univer-snap-start univer-items-center univer-justify-center univer-border-0 univer-border-r univer-border-solid univer-border-gray-200 univer-bg-transparent univer-px-3 univer-text-xs univer-text-gray-900 univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 enabled:active:univer-bg-gray-100 disabled:univer-opacity-40 dark:!univer-border-gray-600 dark:!univer-text-gray-0 dark:enabled:active:!univer-bg-gray-600",
24264
24389
  onClick: () => onExecute === null || onExecute === void 0 ? void 0 : onExecute({
24265
24390
  ...option,
24266
24391
  value: displayValue,
24267
24392
  id: menuItem.id,
24268
24393
  label: menuKey,
24269
- commandId: option.commandId
24394
+ commandId: option.commandId ?? menuItem.selectionsCommandId
24270
24395
  }),
24271
24396
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomLabel, {
24272
24397
  value$: option.value$,
@@ -24301,6 +24426,14 @@ function MobileSchemaList(props) {
24301
24426
  bordered: index !== visibleSchemas.length - 1
24302
24427
  }, schema.key);
24303
24428
  if (!((_schema$children2 = schema.children) === null || _schema$children2 === void 0 ? void 0 : _schema$children2.length)) return null;
24429
+ if (schema.mobileLayout === "grid" || schema.mobileLayout === void 0 && Boolean(schema.quickLayout)) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileQuickSchemaGroup, {
24430
+ schema,
24431
+ menuManagerService,
24432
+ onExecute,
24433
+ onOpenView,
24434
+ inheritedDisabled$,
24435
+ bordered: index !== visibleSchemas.length - 1
24436
+ }, schema.key);
24304
24437
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
24305
24438
  className: (0, _univerjs_design.clsx)("univer-grid", index !== visibleSchemas.length - 1 && _univerjs_design.borderBottomClassName),
24306
24439
  children: [schema.title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -24317,6 +24450,54 @@ function MobileSchemaList(props) {
24317
24450
  }, schema.key);
24318
24451
  }) });
24319
24452
  }
24453
+ function MobileQuickSchemaGroup(props) {
24454
+ var _schema$children3;
24455
+ const { schema, menuManagerService, onExecute, onOpenView, inheritedDisabled$, bordered } = props;
24456
+ const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
24457
+ const columns = Math.max(2, Math.min(schema.quickColumns ?? 4, 5));
24458
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
24459
+ className: (0, _univerjs_design.clsx)("univer-p-3", bordered && _univerjs_design.borderBottomClassName),
24460
+ children: [schema.title && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
24461
+ className: "univer-px-1 univer-pb-2 univer-text-sm univer-font-semibold univer-text-gray-900 dark:!univer-text-gray-100",
24462
+ children: localeService.t(schema.title)
24463
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
24464
+ className: "univer-grid univer-gap-2",
24465
+ style: { gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))` },
24466
+ children: (_schema$children3 = schema.children) === null || _schema$children3 === void 0 ? void 0 : _schema$children3.map((childSchema) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileQuickSchemaItem, {
24467
+ schema: childSchema,
24468
+ menuManagerService,
24469
+ onExecute,
24470
+ onOpenView,
24471
+ inheritedDisabled$,
24472
+ compact: schema.quickLayoutVariant === "compact"
24473
+ }, childSchema.key))
24474
+ })]
24475
+ });
24476
+ }
24477
+ function MobileQuickSchemaItem(props) {
24478
+ const { schema, menuManagerService, onExecute, onOpenView, inheritedDisabled$, compact } = props;
24479
+ const interaction = useMobileSchemaInteraction({
24480
+ schema,
24481
+ menuManagerService,
24482
+ onOpenView,
24483
+ inheritedDisabled$
24484
+ });
24485
+ if (!interaction || interaction.hidden) return null;
24486
+ const { menuItem, activated, disabled, value, onPress } = interaction;
24487
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
24488
+ type: "button",
24489
+ disabled,
24490
+ "aria-pressed": menuItem.type === 2 ? activated : void 0,
24491
+ className: (0, _univerjs_design.clsx)("univer-relative univer-flex univer-w-full univer-appearance-none univer-flex-col univer-items-center univer-justify-center univer-gap-1 univer-rounded-xl univer-border-0 univer-bg-gray-50 univer-p-2 univer-text-center univer-text-gray-900 univer-outline-none focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 enabled:active:univer-scale-[0.98] enabled:active:univer-bg-gray-100 disabled:univer-opacity-40 dark:!univer-bg-gray-700 dark:!univer-text-gray-100 dark:enabled:active:!univer-bg-gray-600 [&>span]:univer-line-clamp-2 [&>span]:univer-text-xs [&>span]:univer-font-medium [&>svg]:univer-size-6 [&>svg]:univer-shrink-0", compact ? "univer-min-h-12" : "univer-min-h-20", activated && "univer-bg-primary-50 univer-text-primary-600 dark:!univer-bg-primary-900 dark:!univer-text-primary-300"),
24492
+ onClick: () => onPress(onExecute),
24493
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(CustomLabel, {
24494
+ value,
24495
+ title: menuItem.title ?? menuItem.tooltip,
24496
+ label: menuItem.label,
24497
+ icon: menuItem.icon
24498
+ }), activated && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.CheckMarkIcon, { className: "univer-absolute univer-right-1.5 univer-top-1.5 univer-size-3.5" })]
24499
+ });
24500
+ }
24320
24501
  function MobileSchemaRow(props) {
24321
24502
  const { schema, menuManagerService, onExecute, onOpenView, inheritedDisabled$, bordered } = props;
24322
24503
  const interaction = useMobileSchemaInteraction({
@@ -24354,7 +24535,7 @@ function MobileSchemaRow(props) {
24354
24535
  });
24355
24536
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
24356
24537
  type: "button",
24357
- className: (0, _univerjs_design.clsx)("univer-flex univer-min-h-12 univer-w-full univer-appearance-none univer-items-center univer-gap-3 univer-border-0 univer-bg-gray-0 univer-px-4 univer-py-2 univer-text-left univer-outline-none univer-transition-colors focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 enabled:hover:univer-bg-gray-50 enabled:active:univer-bg-gray-100 disabled:univer-cursor-not-allowed disabled:univer-opacity-40 dark:!univer-bg-gray-800 dark:hover:!univer-bg-gray-700 dark:active:!univer-bg-gray-600", bordered && _univerjs_design.borderBottomClassName),
24538
+ className: (0, _univerjs_design.clsx)("univer-flex univer-min-h-12 univer-w-full univer-appearance-none univer-items-center univer-gap-3 univer-border-0 univer-bg-gray-0 univer-px-4 univer-py-2 univer-text-left univer-outline-none univer-transition-colors focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 enabled:active:univer-bg-gray-100 disabled:univer-cursor-not-allowed disabled:univer-opacity-40 dark:!univer-bg-gray-800 dark:active:!univer-bg-gray-600", bordered && _univerjs_design.borderBottomClassName),
24358
24539
  "data-u-command": menuItem.id,
24359
24540
  disabled,
24360
24541
  "aria-pressed": menuItem.type === 2 ? activated : void 0,
@@ -24414,7 +24595,7 @@ function MobileSelectionOptionRow(props) {
24414
24595
  value: nextValue,
24415
24596
  id: menuItem.id,
24416
24597
  label: menuKey,
24417
- commandId: option.commandId
24598
+ commandId: option.commandId ?? menuItem.selectionsCommandId
24418
24599
  });
24419
24600
  }
24420
24601
  })
@@ -24422,7 +24603,7 @@ function MobileSelectionOptionRow(props) {
24422
24603
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
24423
24604
  type: "button",
24424
24605
  "aria-pressed": selected,
24425
- className: (0, _univerjs_design.clsx)("univer-relative univer-flex univer-min-h-12 univer-w-full univer-appearance-none univer-items-center univer-gap-3 univer-border-0 univer-bg-gray-0 univer-px-4 univer-py-2 univer-text-left univer-outline-none univer-transition-colors focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 enabled:hover:univer-bg-gray-50 enabled:active:univer-bg-gray-100 disabled:univer-cursor-not-allowed disabled:univer-opacity-40 dark:!univer-bg-gray-800 dark:hover:!univer-bg-gray-700 dark:active:!univer-bg-gray-600", bordered && _univerjs_design.borderBottomClassName),
24606
+ className: (0, _univerjs_design.clsx)("univer-relative univer-flex univer-min-h-12 univer-w-full univer-appearance-none univer-items-center univer-gap-3 univer-border-0 univer-bg-gray-0 univer-px-4 univer-py-2 univer-text-left univer-outline-none univer-transition-colors focus-visible:univer-ring-2 focus-visible:univer-ring-inset focus-visible:univer-ring-primary-500 enabled:active:univer-bg-gray-100 disabled:univer-cursor-not-allowed disabled:univer-opacity-40 dark:!univer-bg-gray-800 dark:active:!univer-bg-gray-600", bordered && _univerjs_design.borderBottomClassName),
24426
24607
  disabled: optionDisabled,
24427
24608
  onClick: () => {
24428
24609
  if (optionDisabled) return;
@@ -24431,7 +24612,7 @@ function MobileSelectionOptionRow(props) {
24431
24612
  value: displayValue,
24432
24613
  id: menuItem.id,
24433
24614
  label: menuKey,
24434
- commandId: option.commandId
24615
+ commandId: option.commandId ?? menuItem.selectionsCommandId
24435
24616
  });
24436
24617
  },
24437
24618
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
@@ -24460,7 +24641,8 @@ function useMobileSchemaInteraction(props) {
24460
24641
  const value = (0, _wendellhu_redi_react_bindings.useObservable)(menuItem === null || menuItem === void 0 ? void 0 : menuItem.value$);
24461
24642
  const selectionsFromObservable = (0, _wendellhu_redi_react_bindings.useObservable)(selectorItem && (0, rxjs.isObservable)(selectorItem.selections) ? selectorItem.selections : void 0);
24462
24643
  const schemaChildren = (0, react.useMemo)(() => schema.children ?? [], [schema.children]);
24463
- const visibleSchemaChildren = (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => getVisibleSchemaCount$(schemaChildren), [schemaChildren]), schemaChildren.length);
24644
+ const visibleSchemaChildren$ = (0, react.useMemo)(() => getVisibleSchemaCount$(schemaChildren), [schemaChildren]);
24645
+ const visibleSchemaChildren = (0, _wendellhu_redi_react_bindings.useObservable)(visibleSchemaChildren$, schemaChildren.length);
24464
24646
  const selections = (0, react.useMemo)(() => {
24465
24647
  if (!selectorItem || (menuItem === null || menuItem === void 0 ? void 0 : menuItem.type) !== 1 && (menuItem === null || menuItem === void 0 ? void 0 : menuItem.type) !== 2) return [];
24466
24648
  if (selectionsFromObservable) return selectionsFromObservable;
@@ -24477,11 +24659,14 @@ function useMobileSchemaInteraction(props) {
24477
24659
  if (!menuItem) return null;
24478
24660
  const hasSubmenu = visibleSchemaChildren > 0 || selections.length > 0 || subMenuItems.length > 0;
24479
24661
  const effectivelyDisabled = disabled || menuItem.type === 3 && !hasSubmenu;
24480
- const currentValueText = typeof value === "string" || typeof value === "number" ? String(value) : "";
24662
+ const selectedOption = selections.find((option) => option.value === value);
24663
+ let currentValueText = "";
24664
+ if (typeof (selectedOption === null || selectedOption === void 0 ? void 0 : selectedOption.label) === "string") currentValueText = localeService.t(selectedOption.label);
24665
+ else if (selections.length === 0 && (typeof value === "string" || typeof value === "number")) currentValueText = String(value);
24481
24666
  const onPress = (onExecute) => {
24482
24667
  if (effectivelyDisabled) return;
24483
24668
  if (schemaChildren.length > 0) {
24484
- const schemas = menuItem.type === 2 && selections.length === 0 ? [{
24669
+ const schemas = menuItem.type === 2 ? [{
24485
24670
  ...schema,
24486
24671
  children: void 0
24487
24672
  }, ...schemaChildren] : schemaChildren;
@@ -24514,65 +24699,500 @@ function useMobileSchemaInteraction(props) {
24514
24699
  });
24515
24700
  return;
24516
24701
  }
24517
- if (menuItem.type !== 0 && menuItem.type !== 2) return;
24518
- onExecute === null || onExecute === void 0 || onExecute({
24519
- commandId: menuItem.commandId,
24520
- value,
24521
- id: menuItem.id,
24522
- label: schema.key,
24523
- params: menuItem.params
24524
- });
24525
- };
24526
- return {
24527
- menuItem,
24528
- activated,
24529
- disabled: effectivelyDisabled,
24530
- hidden,
24531
- value,
24532
- currentValueText,
24533
- hasSubmenu,
24534
- onPress
24535
- };
24536
- }
24537
- function getVisibleSchemaCount$(schemas) {
24538
- const leafSchemas = getLeafItemSchemas(schemas);
24539
- if (leafSchemas.length === 0) return (0, rxjs.of)(0);
24540
- return (0, rxjs.combineLatest)(leafSchemas.map((schema) => {
24541
- var _schema$item;
24542
- return (((_schema$item = schema.item) === null || _schema$item === void 0 ? void 0 : _schema$item.hidden$) ?? (0, rxjs.of)(false)).pipe((0, rxjs_operators.startWith)(false));
24543
- })).pipe((0, rxjs.map)((hiddenStates) => hiddenStates.filter((hidden) => !hidden).length));
24544
- }
24545
- function getMenuSchemaTitle(schema, localeService) {
24546
- const menuItem = schema.item;
24547
- if (typeof (menuItem === null || menuItem === void 0 ? void 0 : menuItem.title) === "string") return localeService.t(menuItem.title);
24548
- if (typeof (menuItem === null || menuItem === void 0 ? void 0 : menuItem.label) === "string") return localeService.t(menuItem.label);
24549
- if (typeof (menuItem === null || menuItem === void 0 ? void 0 : menuItem.tooltip) === "string") return localeService.t(menuItem.tooltip);
24550
- if (typeof schema.title === "string") return localeService.t(schema.title);
24551
- return schema.key;
24552
- }
24553
- function useContextGroupHiddenStates(menuSchemas) {
24554
- return (0, _wendellhu_redi_react_bindings.useObservable)((0, react.useMemo)(() => {
24555
- const groupStates = menuSchemas.flatMap((menuSchema) => {
24556
- var _menuSchema$children;
24557
- const hiddenObservables = ((_menuSchema$children = menuSchema.children) === null || _menuSchema$children === void 0 ? void 0 : _menuSchema$children.length) ? getLeafItemSchemas(menuSchema.children).map((childSchema) => {
24558
- var _childSchema$item;
24559
- return ((_childSchema$item = childSchema.item) === null || _childSchema$item === void 0 ? void 0 : _childSchema$item.hidden$) ?? (0, rxjs.of)(false);
24560
- }) : [];
24561
- return hiddenObservables.length ? [(0, rxjs.combineLatest)(hiddenObservables).pipe((0, rxjs.map)((values) => [menuSchema.key, values.every(Boolean)]))] : [];
24562
- });
24563
- return groupStates.length ? (0, rxjs.merge)(...groupStates).pipe((0, rxjs_operators.scan)((states, [key, hidden]) => ({
24564
- ...states,
24565
- [key]: hidden
24566
- }), {}), (0, rxjs_operators.startWith)({})) : (0, rxjs.of)({});
24567
- }, [menuSchemas]), {});
24568
- }
24569
- function getLeafItemSchemas(schemas) {
24570
- return schemas.reduce((acc, schema) => {
24571
- var _schema$children3;
24572
- if ((_schema$children3 = schema.children) === null || _schema$children3 === void 0 ? void 0 : _schema$children3.length) return [...acc, ...getLeafItemSchemas(schema.children)];
24573
- if (schema.item) return [...acc, schema];
24574
- return acc;
24575
- }, []);
24702
+ if (menuItem.type !== 0 && menuItem.type !== 2) return;
24703
+ onExecute === null || onExecute === void 0 || onExecute({
24704
+ commandId: menuItem.commandId,
24705
+ value,
24706
+ id: menuItem.id,
24707
+ label: schema.key,
24708
+ params: menuItem.params
24709
+ });
24710
+ };
24711
+ return {
24712
+ menuItem,
24713
+ activated,
24714
+ disabled: effectivelyDisabled,
24715
+ hidden,
24716
+ value,
24717
+ currentValueText,
24718
+ hasSubmenu,
24719
+ onPress
24720
+ };
24721
+ }
24722
+ function getVisibleSchemaCount$(schemas) {
24723
+ const leafSchemas = getLeafItemSchemas(schemas);
24724
+ if (leafSchemas.length === 0) return (0, rxjs.of)(0);
24725
+ return (0, rxjs.combineLatest)(leafSchemas.map((schema) => {
24726
+ var _schema$item;
24727
+ return (((_schema$item = schema.item) === null || _schema$item === void 0 ? void 0 : _schema$item.hidden$) ?? (0, rxjs.of)(false)).pipe((0, rxjs_operators.startWith)(false));
24728
+ })).pipe((0, rxjs.map)((hiddenStates) => hiddenStates.filter((hidden) => !hidden).length));
24729
+ }
24730
+ function getMenuSchemaTitle(schema, localeService) {
24731
+ const menuItem = schema.item;
24732
+ if (typeof (menuItem === null || menuItem === void 0 ? void 0 : menuItem.title) === "string") return localeService.t(menuItem.title);
24733
+ if (typeof (menuItem === null || menuItem === void 0 ? void 0 : menuItem.label) === "string") return localeService.t(menuItem.label);
24734
+ if (typeof (menuItem === null || menuItem === void 0 ? void 0 : menuItem.tooltip) === "string") return localeService.t(menuItem.tooltip);
24735
+ if (typeof schema.title === "string") return localeService.t(schema.title);
24736
+ return schema.key;
24737
+ }
24738
+ function useContextGroupHiddenStates(menuSchemas) {
24739
+ const hiddenStates$ = (0, react.useMemo)(() => {
24740
+ const groupStates = menuSchemas.flatMap((menuSchema) => {
24741
+ var _menuSchema$children;
24742
+ const hiddenObservables = ((_menuSchema$children = menuSchema.children) === null || _menuSchema$children === void 0 ? void 0 : _menuSchema$children.length) ? getLeafItemSchemas(menuSchema.children).map((childSchema) => {
24743
+ var _childSchema$item;
24744
+ return ((_childSchema$item = childSchema.item) === null || _childSchema$item === void 0 ? void 0 : _childSchema$item.hidden$) ?? (0, rxjs.of)(false);
24745
+ }) : [];
24746
+ return hiddenObservables.length ? [(0, rxjs.combineLatest)(hiddenObservables).pipe((0, rxjs.map)((values) => [menuSchema.key, values.every(Boolean)]))] : [];
24747
+ });
24748
+ return groupStates.length ? (0, rxjs.merge)(...groupStates).pipe((0, rxjs_operators.scan)((states, [key, hidden]) => ({
24749
+ ...states,
24750
+ [key]: hidden
24751
+ }), {}), (0, rxjs_operators.startWith)({})) : (0, rxjs.of)({});
24752
+ }, [menuSchemas]);
24753
+ return (0, _wendellhu_redi_react_bindings.useObservable)(hiddenStates$, {});
24754
+ }
24755
+ function getLeafItemSchemas(schemas) {
24756
+ return schemas.reduce((acc, schema) => {
24757
+ var _schema$children4;
24758
+ if ((_schema$children4 = schema.children) === null || _schema$children4 === void 0 ? void 0 : _schema$children4.length) return [...acc, ...getLeafItemSchemas(schema.children)];
24759
+ if (schema.item) return [...acc, schema];
24760
+ return acc;
24761
+ }, []);
24762
+ }
24763
+
24764
+ //#endregion
24765
+ //#region src/views/mobile-workbench/MobileCanvasLayout.tsx
24766
+ const MobileCanvasLayoutContext = (0, react.createContext)(null);
24767
+ function MobileCanvasLayoutProvider({ children }) {
24768
+ const [panels, setPanels] = (0, react.useState)([]);
24769
+ const register = (0, react.useCallback)((panel) => {
24770
+ setPanels((current) => [...current, panel]);
24771
+ return () => setPanels((current) => current.filter((item) => item !== panel));
24772
+ }, []);
24773
+ const value = (0, react.useMemo)(() => ({
24774
+ panels,
24775
+ register
24776
+ }), [panels, register]);
24777
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileCanvasLayoutContext.Provider, {
24778
+ value,
24779
+ children
24780
+ });
24781
+ }
24782
+ /** Register the actual surface, not its full-screen portal container. */
24783
+ function useMobileCanvasPanel(ref, layout, dragging = false) {
24784
+ var _useContext;
24785
+ const register = (_useContext = (0, react.useContext)(MobileCanvasLayoutContext)) === null || _useContext === void 0 ? void 0 : _useContext.register;
24786
+ (0, react.useLayoutEffect)(() => {
24787
+ if (ref.current && register) return register({
24788
+ ref,
24789
+ layout,
24790
+ dragging
24791
+ });
24792
+ }, [
24793
+ ref,
24794
+ register,
24795
+ layout,
24796
+ dragging
24797
+ ]);
24798
+ }
24799
+ /** Connect design-layer overlay surfaces to the current workbench layout. */
24800
+ function useMobileOverlayRegistration(layout) {
24801
+ var _useContext2;
24802
+ const register = (_useContext2 = (0, react.useContext)(MobileCanvasLayoutContext)) === null || _useContext2 === void 0 ? void 0 : _useContext2.register;
24803
+ return (0, react.useCallback)((element) => register === null || register === void 0 ? void 0 : register({
24804
+ ref: { current: element },
24805
+ layout,
24806
+ dragging: false
24807
+ }), [register, layout]);
24808
+ }
24809
+ /** Minimal viewport translation in CSS pixels. Large objects keep their leading edge visible. */
24810
+ function getMobileCanvasPanDelta(target, viewport) {
24811
+ const reveal = (start, size, available) => {
24812
+ const margin = Math.min(16, available / 4);
24813
+ const end = start + Math.min(size, available - margin * 2);
24814
+ if (start < margin) return margin - start;
24815
+ return end > available - margin ? available - margin - end : 0;
24816
+ };
24817
+ return {
24818
+ x: reveal(target.left, target.width, viewport.width),
24819
+ y: reveal(target.top, target.height, viewport.height)
24820
+ };
24821
+ }
24822
+ /**
24823
+ * Opt-in canvas host. Panels remain outside the resizable inner element so their
24824
+ * measurement cannot feed back into their own containing block. No focus or zoom
24825
+ * changes are performed here; each renderer owns its viewport translation.
24826
+ */
24827
+ function useMobileCanvasViewport(options) {
24828
+ const { containerRef, canvasRef, enabled = true, panelsOnly = false, onReveal } = options;
24829
+ const context = (0, react.useContext)(MobileCanvasLayoutContext);
24830
+ const revealRef = (0, react.useRef)(onReveal);
24831
+ (0, react.useLayoutEffect)(() => {
24832
+ revealRef.current = onReveal;
24833
+ }, [onReveal]);
24834
+ const previousHeightRef = (0, react.useRef)(null);
24835
+ const needsRevealRef = (0, react.useRef)(false);
24836
+ (0, react.useLayoutEffect)(() => {
24837
+ const container = containerRef.current;
24838
+ const canvas = canvasRef.current;
24839
+ if (!context || !enabled || !container || !canvas) return;
24840
+ const panels = context.panels.flatMap(({ ref, layout, dragging }) => ref.current ? [{
24841
+ element: ref.current,
24842
+ layout,
24843
+ dragging
24844
+ }] : []);
24845
+ if (panelsOnly && !panels.some((panel) => panel.layout === "canvas")) {
24846
+ previousHeightRef.current = null;
24847
+ needsRevealRef.current = false;
24848
+ return;
24849
+ }
24850
+ const viewport = window.visualViewport;
24851
+ let frame = 0;
24852
+ let settleFrame = 0;
24853
+ const originalHeight = canvas.style.height;
24854
+ const originalBottom = canvas.style.bottom;
24855
+ const originalTop = canvas.style.top;
24856
+ const panelStyles = panels.map(({ element }) => ({
24857
+ element,
24858
+ bottom: element.style.bottom,
24859
+ maxHeight: element.style.maxHeight
24860
+ }));
24861
+ const settle = () => {
24862
+ cancelAnimationFrame(settleFrame);
24863
+ settleFrame = requestAnimationFrame(() => {
24864
+ settleFrame = requestAnimationFrame(() => {
24865
+ if (needsRevealRef.current && !panels.some((panel) => panel.dragging)) {
24866
+ needsRevealRef.current = false;
24867
+ revealRef.current();
24868
+ }
24869
+ });
24870
+ });
24871
+ };
24872
+ const measure = () => {
24873
+ const bounds = container.getBoundingClientRect();
24874
+ const modal = panels.some((panel) => panel.layout === "modal");
24875
+ const visibleBottom = viewport ? viewport.offsetTop + viewport.height : window.innerHeight;
24876
+ const top = modal ? bounds.top : Math.max(bounds.top, (viewport === null || viewport === void 0 ? void 0 : viewport.offsetTop) ?? 0);
24877
+ let bottom = modal ? bounds.bottom : Math.min(bounds.bottom, visibleBottom);
24878
+ const panelMaxHeight = Math.max(0, bottom - top) * .6;
24879
+ if (!modal) for (const { element, layout } of panels) {
24880
+ if (layout !== "canvas") continue;
24881
+ const containingBlock = element.offsetParent;
24882
+ const parentBottom = getComputedStyle(element).position === "fixed" || !containingBlock ? window.innerHeight : containingBlock.getBoundingClientRect().bottom;
24883
+ element.style.bottom = `${Math.max(0, parentBottom - visibleBottom)}px`;
24884
+ element.style.maxHeight = `${panelMaxHeight}px`;
24885
+ const rect = element.getBoundingClientRect();
24886
+ if (rect.right > bounds.left && rect.left < bounds.right && rect.bottom > bounds.top) bottom = Math.min(bottom, rect.top);
24887
+ }
24888
+ const height = Math.max(0, bottom - top);
24889
+ const oldHeight = previousHeightRef.current ?? bounds.height;
24890
+ if (modal || height > oldHeight + 1) needsRevealRef.current = false;
24891
+ needsRevealRef.current ||= !modal && height < oldHeight - 1;
24892
+ previousHeightRef.current = height;
24893
+ canvas.style.bottom = "auto";
24894
+ canvas.style.top = `${top - bounds.top}px`;
24895
+ canvas.style.height = `${height}px`;
24896
+ settle();
24897
+ };
24898
+ const schedule = () => {
24899
+ cancelAnimationFrame(frame);
24900
+ frame = requestAnimationFrame(measure);
24901
+ };
24902
+ const observer = new ResizeObserver(schedule);
24903
+ const cancelReveal = () => {
24904
+ needsRevealRef.current = false;
24905
+ };
24906
+ canvas.addEventListener("pointerdown", cancelReveal);
24907
+ observer.observe(container);
24908
+ panels.forEach(({ element }) => observer.observe(element));
24909
+ viewport === null || viewport === void 0 || viewport.addEventListener("resize", schedule);
24910
+ viewport === null || viewport === void 0 || viewport.addEventListener("scroll", schedule);
24911
+ window.addEventListener("resize", schedule);
24912
+ measure();
24913
+ return () => {
24914
+ observer.disconnect();
24915
+ canvas.removeEventListener("pointerdown", cancelReveal);
24916
+ cancelAnimationFrame(frame);
24917
+ cancelAnimationFrame(settleFrame);
24918
+ viewport === null || viewport === void 0 || viewport.removeEventListener("resize", schedule);
24919
+ viewport === null || viewport === void 0 || viewport.removeEventListener("scroll", schedule);
24920
+ window.removeEventListener("resize", schedule);
24921
+ canvas.style.height = originalHeight;
24922
+ canvas.style.bottom = originalBottom;
24923
+ canvas.style.top = originalTop;
24924
+ panelStyles.forEach(({ element, bottom, maxHeight }) => {
24925
+ element.style.bottom = bottom;
24926
+ element.style.maxHeight = maxHeight;
24927
+ });
24928
+ };
24929
+ }, [
24930
+ context,
24931
+ enabled,
24932
+ panelsOnly,
24933
+ containerRef,
24934
+ canvasRef
24935
+ ]);
24936
+ }
24937
+
24938
+ //#endregion
24939
+ //#region src/views/components/mobile-drawer/MobileDrawerCoordinator.tsx
24940
+ const MobileDrawerCoordinatorContext = (0, react.createContext)(null);
24941
+ function MobileDrawerCoordinatorProvider(props) {
24942
+ const entriesRef = (0, react.useRef)([]);
24943
+ const [activeDrawerId, setActiveDrawerId] = (0, react.useState)(null);
24944
+ const setEntries = (0, react.useCallback)((entries) => {
24945
+ entriesRef.current = entries;
24946
+ setActiveDrawerId(entries.length ? entries[entries.length - 1].id : null);
24947
+ }, []);
24948
+ const unregister = (0, react.useCallback)((id) => {
24949
+ setEntries(entriesRef.current.filter((entry) => entry.id !== id));
24950
+ }, [setEntries]);
24951
+ const close = (0, react.useCallback)((id) => {
24952
+ const entry = entriesRef.current.find((item) => item.id === id);
24953
+ if (!entry) return;
24954
+ unregister(id);
24955
+ entry.onClose();
24956
+ }, [unregister]);
24957
+ const register = (0, react.useCallback)((id, mode, onClose) => {
24958
+ const entry = {
24959
+ id,
24960
+ onClose
24961
+ };
24962
+ if (mode === "push") {
24963
+ setEntries([...entriesRef.current, entry]);
24964
+ return;
24965
+ }
24966
+ const previousEntries = entriesRef.current;
24967
+ setEntries([entry]);
24968
+ for (let i = previousEntries.length - 1; i >= 0; i--) previousEntries[i].onClose();
24969
+ }, [setEntries]);
24970
+ const value = (0, react.useMemo)(() => ({
24971
+ activeDrawerId,
24972
+ close,
24973
+ register,
24974
+ unregister
24975
+ }), [
24976
+ activeDrawerId,
24977
+ close,
24978
+ register,
24979
+ unregister
24980
+ ]);
24981
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileDrawerCoordinatorContext.Provider, {
24982
+ value,
24983
+ children: props.children
24984
+ });
24985
+ }
24986
+
24987
+ //#endregion
24988
+ //#region src/views/components/mobile-drawer/MobileDrawer.tsx
24989
+ function assignDrawerRef(ref, element) {
24990
+ if (typeof ref === "function") ref(element);
24991
+ else if (ref) ref.current = element;
24992
+ }
24993
+ const MOBILE_DRAWER_COMPACT_PERCENT = 40;
24994
+ const MOBILE_DRAWER_EXPANDED_PERCENT = 80;
24995
+ const MobileDrawerLayoutContext = (0, react.createContext)("modal");
24996
+ function resolveMobileDrawerRelease(params) {
24997
+ const { snap, deltaY, durationMs, percent } = params;
24998
+ const velocity = deltaY / Math.max(durationMs, 1);
24999
+ if (deltaY > 48 && (snap === "compact" || velocity > .55) || percent < 20) return "closed";
25000
+ if (snap === "expanded" && deltaY > 24) return "compact";
25001
+ if (snap === "compact" && deltaY < -24) return "expanded";
25002
+ return percent >= 60 ? "expanded" : "compact";
25003
+ }
25004
+ function MobileDrawer(props) {
25005
+ var _globalThis$CSS;
25006
+ const { snap, expandLabel, collapseLabel, onSnapChange, onClose, children, header, floatingActions, componentName = "mobile-drawer", panelRef, contentRef, layerRef, openMode = "replace", panelClassName, contentClassName, footer, role, ariaLabel, layout: requestedLayout } = props;
25007
+ const coordinator = (0, react.useContext)(MobileDrawerCoordinatorContext);
25008
+ const registerDrawer = coordinator === null || coordinator === void 0 ? void 0 : coordinator.register;
25009
+ const unregisterDrawer = coordinator === null || coordinator === void 0 ? void 0 : coordinator.unregister;
25010
+ const panelElementRef = (0, react.useRef)(null);
25011
+ const drawerIdRef = (0, react.useRef)(null);
25012
+ const onCloseRef = (0, react.useRef)(onClose);
25013
+ onCloseRef.current = onClose;
25014
+ if (!drawerIdRef.current) drawerIdRef.current = Symbol(componentName);
25015
+ const drawerId = drawerIdRef.current;
25016
+ const active = !coordinator || coordinator.activeDrawerId === drawerId;
25017
+ const inheritedLayout = (0, react.useContext)(MobileDrawerLayoutContext);
25018
+ const layout = requestedLayout ?? inheritedLayout;
25019
+ const registerOverlay = useMobileOverlayRegistration(layout);
25020
+ const viewportHeightUnit = ((_globalThis$CSS = globalThis.CSS) === null || _globalThis$CSS === void 0 ? void 0 : _globalThis$CSS.supports("height", "1dvh")) ? "dvh" : "vh";
25021
+ const overlay = (0, react.useMemo)(() => ({
25022
+ modal: layout === "modal",
25023
+ contentProps: {
25024
+ style: layout === "canvas" ? {
25025
+ height: `${MOBILE_DRAWER_COMPACT_PERCENT}${viewportHeightUnit}`,
25026
+ maxHeight: `${MOBILE_DRAWER_COMPACT_PERCENT}${viewportHeightUnit}`
25027
+ } : void 0,
25028
+ onOpenAutoFocus: layout === "canvas" ? (event) => event.preventDefault() : void 0,
25029
+ onCloseAutoFocus: layout === "canvas" ? (event) => event.preventDefault() : void 0
25030
+ },
25031
+ onMount: registerOverlay
25032
+ }), [
25033
+ layout,
25034
+ registerOverlay,
25035
+ viewportHeightUnit
25036
+ ]);
25037
+ const [dragPercent, setDragPercent] = (0, react.useState)(null);
25038
+ const surfaceRef = (0, react.useRef)(null);
25039
+ const setPanelRef = (0, react.useCallback)((element) => {
25040
+ surfaceRef.current = element;
25041
+ panelElementRef.current = element;
25042
+ assignDrawerRef(panelRef, element);
25043
+ }, [panelRef]);
25044
+ useMobileCanvasPanel(surfaceRef, layout, dragPercent !== null);
25045
+ const suppressHandleClickRef = (0, react.useRef)(false);
25046
+ const dragRef = (0, react.useRef)(null);
25047
+ const drawerPercent = dragPercent ?? (snap === "compact" ? MOBILE_DRAWER_COMPACT_PERCENT : MOBILE_DRAWER_EXPANDED_PERCENT);
25048
+ const keyboardLayout = (0, _univerjs_design.useMobileKeyboardViewportLayout)(panelElementRef);
25049
+ (0, react.useLayoutEffect)(() => {
25050
+ if (!registerDrawer || !unregisterDrawer) return;
25051
+ registerDrawer(drawerId, openMode, () => onCloseRef.current());
25052
+ return () => unregisterDrawer(drawerId);
25053
+ }, [
25054
+ drawerId,
25055
+ openMode,
25056
+ registerDrawer,
25057
+ unregisterDrawer
25058
+ ]);
25059
+ (0, react.useLayoutEffect)(() => {
25060
+ var _panelElementRef$curr;
25061
+ const layer = (layerRef === null || layerRef === void 0 ? void 0 : layerRef.current) ?? (layerRef ? (_panelElementRef$curr = panelElementRef.current) === null || _panelElementRef$curr === void 0 ? void 0 : _panelElementRef$curr.parentElement : null);
25062
+ if (!layer) return;
25063
+ layer.toggleAttribute("hidden", !active);
25064
+ }, [active, layerRef]);
25065
+ function beginDrag(clientY) {
25066
+ dragRef.current = {
25067
+ startY: clientY,
25068
+ startTime: performance.now(),
25069
+ startPercent: drawerPercent,
25070
+ currentPercent: drawerPercent,
25071
+ currentY: clientY,
25072
+ moved: false
25073
+ };
25074
+ }
25075
+ function moveDrag(clientY) {
25076
+ const drag = dragRef.current;
25077
+ if (!drag) return;
25078
+ const deltaY = clientY - drag.startY;
25079
+ const nextPercent = Math.max(0, Math.min(MOBILE_DRAWER_EXPANDED_PERCENT, drag.startPercent - deltaY / Math.max(window.innerHeight, 1) * 100));
25080
+ drag.currentPercent = nextPercent;
25081
+ drag.currentY = clientY;
25082
+ drag.moved ||= Math.abs(deltaY) > 6;
25083
+ setDragPercent(nextPercent);
25084
+ }
25085
+ function endDrag(clientY) {
25086
+ const drag = dragRef.current;
25087
+ if (!drag) return;
25088
+ const result = resolveMobileDrawerRelease({
25089
+ snap,
25090
+ deltaY: clientY - drag.startY,
25091
+ durationMs: performance.now() - drag.startTime,
25092
+ percent: drag.currentPercent
25093
+ });
25094
+ suppressHandleClickRef.current = drag.moved;
25095
+ dragRef.current = null;
25096
+ setDragPercent(null);
25097
+ if (result === "closed") {
25098
+ if (coordinator) coordinator.close(drawerId);
25099
+ else onClose();
25100
+ } else onSnapChange(result);
25101
+ }
25102
+ function handlePointerDown(event) {
25103
+ try {
25104
+ event.currentTarget.setPointerCapture(event.pointerId);
25105
+ } catch {}
25106
+ beginDrag(event.clientY);
25107
+ }
25108
+ function handlePointerMove(event) {
25109
+ moveDrag(event.clientY);
25110
+ }
25111
+ function handlePointerUp(event) {
25112
+ endDrag(event.clientY);
25113
+ }
25114
+ function handlePointerCancel() {
25115
+ const drag = dragRef.current;
25116
+ if (!(drag === null || drag === void 0 ? void 0 : drag.moved)) {
25117
+ dragRef.current = null;
25118
+ setDragPercent(null);
25119
+ return;
25120
+ }
25121
+ endDrag(drag.currentY);
25122
+ }
25123
+ function handleTouchStart(event) {
25124
+ const touch = event.touches[0];
25125
+ if (touch) beginDrag(touch.clientY);
25126
+ }
25127
+ function handleTouchMove(event) {
25128
+ const touch = event.touches[0];
25129
+ if (touch) moveDrag(touch.clientY);
25130
+ }
25131
+ function handleTouchEnd() {
25132
+ const drag = dragRef.current;
25133
+ if (drag) endDrag(drag.currentY);
25134
+ }
25135
+ function handleTouchCancel() {
25136
+ handlePointerCancel();
25137
+ }
25138
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileDrawerLayoutContext.Provider, {
25139
+ value: layout,
25140
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_univerjs_design.MobileOverlayContext.Provider, {
25141
+ value: overlay,
25142
+ children: [floatingActions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
25143
+ className: "univer-pointer-events-none univer-absolute univer-right-4 univer-z-30",
25144
+ style: { bottom: `calc(${drawerPercent}${viewportHeightUnit} + 12px)` },
25145
+ children: floatingActions
25146
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
25147
+ ref: setPanelRef,
25148
+ hidden: !active,
25149
+ role,
25150
+ "aria-modal": layout === "modal" && role === "dialog" || void 0,
25151
+ "aria-label": ariaLabel,
25152
+ "data-u-comp": componentName,
25153
+ "data-snap": snap,
25154
+ className: (0, _univerjs_design.clsx)("univer-absolute univer-inset-x-0 univer-bottom-0 univer-z-20 univer-flex univer-flex-col univer-overflow-hidden univer-rounded-t-[24px] univer-bg-gray-50 univer-shadow-2xl univer-transition-[height] univer-duration-200 dark:!univer-bg-gray-900 [&_input]:!univer-text-base [&_select]:!univer-text-base [&_textarea]:!univer-text-base", "univer-pointer-events-auto", dragPercent != null && "!univer-transition-none", panelClassName),
25155
+ style: {
25156
+ height: `${drawerPercent}${viewportHeightUnit}`,
25157
+ paddingBottom: "env(safe-area-inset-bottom, 0px)"
25158
+ },
25159
+ children: [
25160
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
25161
+ className: "univer-relative univer-flex univer-h-14 univer-shrink-0 univer-items-end univer-bg-gray-0 dark:!univer-bg-gray-800",
25162
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
25163
+ type: "button",
25164
+ "aria-label": snap === "compact" ? expandLabel : collapseLabel,
25165
+ className: (0, _univerjs_design.clsx)(_univerjs_design.resetButtonClassName, "univer-absolute univer-left-1/2 univer-top-0 univer-z-10 univer-flex univer-h-6 univer-w-16 -univer-translate-x-1/2 univer-touch-none univer-items-center univer-justify-center"),
25166
+ style: { touchAction: "none" },
25167
+ onPointerDown: handlePointerDown,
25168
+ onPointerMove: handlePointerMove,
25169
+ onPointerUp: handlePointerUp,
25170
+ onPointerCancel: handlePointerCancel,
25171
+ onTouchStart: handleTouchStart,
25172
+ onTouchMove: handleTouchMove,
25173
+ onTouchEnd: handleTouchEnd,
25174
+ onTouchCancel: handleTouchCancel,
25175
+ onClick: () => {
25176
+ if (suppressHandleClickRef.current) {
25177
+ suppressHandleClickRef.current = false;
25178
+ return;
25179
+ }
25180
+ onSnapChange(snap === "compact" ? "expanded" : "compact");
25181
+ },
25182
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "univer-h-1 univer-w-10 univer-rounded-full univer-bg-gray-300 dark:!univer-bg-gray-600" })
25183
+ }), header]
25184
+ }),
25185
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
25186
+ ref: contentRef,
25187
+ className: (0, _univerjs_design.clsx)("univer-flex-1 univer-overflow-y-auto univer-overflow-x-hidden univer-p-3", _univerjs_design.scrollbarClassName, contentClassName),
25188
+ style: { paddingBottom: keyboardLayout ? `calc(0.75rem + ${keyboardLayout.bottom}px)` : void 0 },
25189
+ children
25190
+ }),
25191
+ footer
25192
+ ]
25193
+ })]
25194
+ })
25195
+ });
24576
25196
  }
24577
25197
 
24578
25198
  //#endregion
@@ -24652,9 +25272,27 @@ function MobileMenuDrawerContent(props) {
24652
25272
  //#endregion
24653
25273
  //#region src/views/components/context-menu/MobileContextMenu.tsx
24654
25274
  const MOBILE_CONTEXT_MENU_HOST_ID = "mobile-context-menu";
25275
+ const MOBILE_CONTEXT_MENU_POINTER_SIZE = 8;
25276
+ const MOBILE_CONTEXT_MENU_POINTER_EDGE_GAP = 12;
25277
+ function resolveMobileCaretMenuPlacement(anchorX, containerLeft, containerWidth, menuWidth) {
25278
+ const relativeAnchorX = anchorX - containerLeft;
25279
+ const menuLeft = Math.min(Math.max(relativeAnchorX - menuWidth / 2, 0), Math.max(containerWidth - menuWidth, 0));
25280
+ return {
25281
+ menuLeft,
25282
+ pointerLeft: Math.min(Math.max(relativeAnchorX - menuLeft - MOBILE_CONTEXT_MENU_POINTER_SIZE / 2, MOBILE_CONTEXT_MENU_POINTER_EDGE_GAP), Math.max(menuWidth - MOBILE_CONTEXT_MENU_POINTER_EDGE_GAP - MOBILE_CONTEXT_MENU_POINTER_SIZE, MOBILE_CONTEXT_MENU_POINTER_EDGE_GAP))
25283
+ };
25284
+ }
25285
+ function shouldUseFloatingMobileContextMenu(_menuType, context) {
25286
+ return (context === null || context === void 0 ? void 0 : context.caretAnchor) === true;
25287
+ }
24655
25288
  function MobileContextMenu() {
24656
25289
  const [visible, setVisible] = (0, react.useState)(false);
24657
25290
  const [menuType, setMenuType] = (0, react.useState)("");
25291
+ const [anchor, setAnchor] = (0, react.useState)({
25292
+ x: 0,
25293
+ y: 0
25294
+ });
25295
+ const floatingMenuRef = (0, react.useRef)(null);
24658
25296
  const [menuContext, setMenuContext] = (0, react.useState)();
24659
25297
  const visibleRef = (0, react.useRef)(visible);
24660
25298
  const contextMenuHostService = (0, _wendellhu_redi_react_bindings.useDependency)(IContextMenuHostService);
@@ -24665,11 +25303,17 @@ function MobileContextMenu() {
24665
25303
  const runtimeScopeService = (0, _wendellhu_redi_react_bindings.useDependency)(IUIRuntimeScopeService);
24666
25304
  const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
24667
25305
  const { mountContainer } = (0, react.useContext)(_univerjs_design.ConfigContext);
25306
+ const isCaretAnchor = (menuContext === null || menuContext === void 0 ? void 0 : menuContext.caretAnchor) === true;
25307
+ const isFloatingContextMenu = shouldUseFloatingMobileContextMenu(menuType, menuContext);
24668
25308
  visibleRef.current = visible;
24669
- const handleContextMenu = (0, react.useCallback)((_event, nextMenuType, context) => {
25309
+ const handleContextMenu = (0, react.useCallback)((event, nextMenuType, context) => {
24670
25310
  contextMenuHostService.activateMenu(MOBILE_CONTEXT_MENU_HOST_ID);
24671
25311
  setMenuType(nextMenuType);
24672
25312
  setMenuContext(context);
25313
+ setAnchor({
25314
+ x: event.clientX,
25315
+ y: event.clientY
25316
+ });
24673
25317
  setVisible(true);
24674
25318
  }, [contextMenuHostService]);
24675
25319
  const handleClose = (0, react.useCallback)(() => {
@@ -24700,6 +25344,50 @@ function MobileContextMenu() {
24700
25344
  handleClose,
24701
25345
  handleContextMenu
24702
25346
  ]);
25347
+ (0, react.useEffect)(() => {
25348
+ if (!visible || !isFloatingContextMenu || !mountContainer) return;
25349
+ const ownerDocument = mountContainer.ownerDocument;
25350
+ const handleOutsidePointerDown = (event) => {
25351
+ var _floatingMenuRef$curr;
25352
+ if (!(event.target instanceof Node) || !((_floatingMenuRef$curr = floatingMenuRef.current) === null || _floatingMenuRef$curr === void 0 ? void 0 : _floatingMenuRef$curr.contains(event.target))) {
25353
+ setVisible(false);
25354
+ contextMenuHostService.deactivateMenu(MOBILE_CONTEXT_MENU_HOST_ID);
25355
+ }
25356
+ };
25357
+ ownerDocument.addEventListener("pointerdown", handleOutsidePointerDown, true);
25358
+ return () => ownerDocument.removeEventListener("pointerdown", handleOutsidePointerDown, true);
25359
+ }, [
25360
+ contextMenuHostService,
25361
+ isFloatingContextMenu,
25362
+ mountContainer,
25363
+ visible
25364
+ ]);
25365
+ (0, react.useLayoutEffect)(() => {
25366
+ if (!visible || !isCaretAnchor) return;
25367
+ const menu = floatingMenuRef.current;
25368
+ const container = menu === null || menu === void 0 ? void 0 : menu.parentElement;
25369
+ if (!menu || !container) return;
25370
+ const updatePlacement = () => {
25371
+ const containerRect = container.getBoundingClientRect();
25372
+ const menuWidth = menu.getBoundingClientRect().width;
25373
+ const { menuLeft, pointerLeft } = resolveMobileCaretMenuPlacement(anchor.x, containerRect.left, containerRect.width, menuWidth);
25374
+ menu.style.left = `${menuLeft}px`;
25375
+ menu.style.setProperty("--univer-mobile-context-menu-pointer-left", `${pointerLeft}px`);
25376
+ };
25377
+ updatePlacement();
25378
+ const resizeObserver = new ResizeObserver(updatePlacement);
25379
+ resizeObserver.observe(container);
25380
+ resizeObserver.observe(menu);
25381
+ return () => {
25382
+ resizeObserver.disconnect();
25383
+ menu.style.removeProperty("left");
25384
+ menu.style.removeProperty("--univer-mobile-context-menu-pointer-left");
25385
+ };
25386
+ }, [
25387
+ anchor.x,
25388
+ isCaretAnchor,
25389
+ visible
25390
+ ]);
24703
25391
  const sheetTitle = (0, react.useMemo)(() => {
24704
25392
  switch (menuType) {
24705
25393
  case "contextMenu.rowHeader": return localeService.t("ui.row");
@@ -24725,6 +25413,40 @@ function MobileContextMenu() {
24725
25413
  activeCommandService.executeCommand(commandId, commandParams);
24726
25414
  handleClose();
24727
25415
  };
25416
+ if (isFloatingContextMenu) {
25417
+ var _mountContainer$owner;
25418
+ const viewportHeight = ((_mountContainer$owner = mountContainer.ownerDocument.defaultView) === null || _mountContainer$owner === void 0 ? void 0 : _mountContainer$owner.innerHeight) ?? 0;
25419
+ const placeBelow = anchor.y < 72;
25420
+ const top = placeBelow ? anchor.y + 12 : Math.min(anchor.y - 56, Math.max(8, viewportHeight - 56));
25421
+ const pointerLeft = `clamp(20px, ${anchor.x - 8}px, calc(100% - 20px))`;
25422
+ return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
25423
+ className: "univer-pointer-events-none univer-fixed univer-inset-x-3 univer-z-[1080] univer-flex univer-justify-center",
25424
+ style: { top },
25425
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
25426
+ ref: floatingMenuRef,
25427
+ className: `
25428
+ univer-pointer-events-auto univer-min-w-0 univer-max-w-[560px]
25429
+ ${isCaretAnchor ? "univer-absolute univer-left-0 univer-top-0 univer-w-fit" : "univer-relative univer-flex-1"}
25430
+ `,
25431
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileMenu, {
25432
+ menuType,
25433
+ menuManagerService: activeMenuManagerService,
25434
+ presentation: "context-bar",
25435
+ onOptionSelect: handleOptionSelect
25436
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
25437
+ "aria-hidden": "true",
25438
+ className: placeBelow ? `
25439
+ univer-absolute -univer-top-1 univer-size-2 univer-rotate-45 univer-bg-gray-0
25440
+ dark:!univer-bg-gray-700
25441
+ ` : `
25442
+ univer-absolute -univer-bottom-1 univer-size-2 univer-rotate-45 univer-bg-gray-0
25443
+ dark:!univer-bg-gray-700
25444
+ `,
25445
+ style: { left: isCaretAnchor ? "var(--univer-mobile-context-menu-pointer-left, calc(50% - 4px))" : pointerLeft }
25446
+ })]
25447
+ })
25448
+ }), mountContainer);
25449
+ }
24728
25450
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileMenuDrawer, {
24729
25451
  visible: true,
24730
25452
  title: sheetTitle,
@@ -24744,14 +25466,18 @@ function MobileSidebar() {
24744
25466
  const layerRef = (0, react.useRef)(null);
24745
25467
  const scrollRef = (0, react.useRef)(null);
24746
25468
  const closeButtonRef = (0, react.useRef)(null);
24747
- const [drawerSnap, setDrawerSnap] = (0, react.useState)("expanded");
25469
+ const [snapOverride, setSnapOverride] = (0, react.useState)(null);
24748
25470
  const options = (0, react.useMemo)(() => renderSidebarOptions(sidebarOptions), [sidebarOptions]);
24749
25471
  (0, react.useEffect)(() => {
24750
- if (options === null || options === void 0 ? void 0 : options.visible) {
25472
+ if ((options === null || options === void 0 ? void 0 : options.visible) && options.layout !== "canvas") {
24751
25473
  var _closeButtonRef$curre;
24752
25474
  (_closeButtonRef$curre = closeButtonRef.current) === null || _closeButtonRef$curre === void 0 || _closeButtonRef$curre.focus();
24753
25475
  }
24754
- }, [options === null || options === void 0 ? void 0 : options.visible]);
25476
+ }, [
25477
+ options === null || options === void 0 ? void 0 : options.visible,
25478
+ options === null || options === void 0 ? void 0 : options.layout,
25479
+ options === null || options === void 0 ? void 0 : options.id
25480
+ ]);
24755
25481
  (0, react.useEffect)(() => {
24756
25482
  const scrollElement = scrollRef.current;
24757
25483
  sidebarService.setContainer(scrollElement ?? void 0);
@@ -24763,23 +25489,28 @@ function MobileSidebar() {
24763
25489
  };
24764
25490
  }, [options === null || options === void 0 ? void 0 : options.visible, sidebarService]);
24765
25491
  if (!(options === null || options === void 0 ? void 0 : options.visible)) return null;
25492
+ const defaultSnap = options.layout === "canvas" ? "compact" : "expanded";
24766
25493
  const close = () => sidebarService.close(sidebarOptions === null || sidebarOptions === void 0 ? void 0 : sidebarOptions.id);
24767
25494
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
24768
25495
  ref: layerRef,
24769
- className: "univer-fixed univer-inset-0 univer-z-[1100]",
25496
+ className: "univer-pointer-events-none univer-fixed univer-inset-0 univer-z-[1100]",
24770
25497
  "data-u-comp": "mobile-sidebar",
24771
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
25498
+ children: [options.layout !== "canvas" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
24772
25499
  type: "button",
24773
25500
  "aria-label": localeService.t("ui.sidebar.close"),
24774
- className: "univer-absolute univer-inset-0 univer-m-0 univer-appearance-none univer-rounded-none univer-border-0 univer-bg-black/35 univer-p-0",
25501
+ className: "univer-pointer-events-auto univer-absolute univer-inset-0 univer-m-0 univer-appearance-none univer-rounded-none univer-border-0 univer-bg-black/35 univer-p-0",
24775
25502
  onClick: close
24776
25503
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileDrawer, {
24777
25504
  layerRef,
25505
+ layout: options.layout,
24778
25506
  componentName: "mobile-sidebar-drawer",
24779
- snap: drawerSnap,
25507
+ snap: snapOverride && snapOverride.id === options.id ? snapOverride.snap : defaultSnap,
24780
25508
  expandLabel: localeService.t("ui.ribbon.more"),
24781
25509
  collapseLabel: localeService.t("ui.ribbon.more"),
24782
- onSnapChange: setDrawerSnap,
25510
+ onSnapChange: (snap) => setSnapOverride({
25511
+ id: options.id,
25512
+ snap
25513
+ }),
24783
25514
  onClose: close,
24784
25515
  role: "dialog",
24785
25516
  ariaLabel: localeService.t("ui.sidebar.panel"),
@@ -24830,8 +25561,17 @@ const MobileKeyboardInsetContext = (0, react.createContext)(0);
24830
25561
 
24831
25562
  //#endregion
24832
25563
  //#region src/views/mobile-workbench/MobileWorkbench.tsx
25564
+ const MOBILE_KEYBOARD_THRESHOLD = 80;
25565
+ function resolveMobileKeyboardInset(stableHeight, visibleBottom, baselineInset) {
25566
+ const keyboardInset = Math.max(0, Math.round(stableHeight - visibleBottom) - baselineInset);
25567
+ return keyboardInset >= MOBILE_KEYBOARD_THRESHOLD ? keyboardInset : 0;
25568
+ }
25569
+ function shouldUpdateMobileStableHeight(stableHeight, nextHeight, stableWidth, nextWidth, editing, keyboardVisible) {
25570
+ return nextWidth !== stableWidth || !editing && !keyboardVisible && stableHeight - nextHeight < MOBILE_KEYBOARD_THRESHOLD;
25571
+ }
24833
25572
  function mountMobileWorkbench(injector, options, mountContainer, onRendered) {
24834
- (0, _univerjs_design.render)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)((0, _wendellhu_redi_react_bindings.connectInjector)(MobileWorkbench, injector), {
25573
+ const ConnectedApp = (0, _wendellhu_redi_react_bindings.connectInjector)(MobileWorkbench, injector);
25574
+ (0, _univerjs_design.render)(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ConnectedApp, {
24835
25575
  ...options,
24836
25576
  mountContainer,
24837
25577
  onRendered
@@ -24845,8 +25585,10 @@ function MobileWorkbench(props) {
24845
25585
  const themeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.ThemeService);
24846
25586
  const themeSwitcherService = (0, _wendellhu_redi_react_bindings.useDependency)(ThemeSwitcherService);
24847
25587
  const contentRef = (0, react.useRef)(null);
25588
+ const canvasContainerRef = (0, react.useRef)(null);
24848
25589
  const viewportRef = (0, react.useRef)(null);
24849
25590
  const [keyboardInset, setKeyboardInset] = (0, react.useState)(0);
25591
+ const [keyboardViewport, setKeyboardViewport] = (0, react.useState)(null);
24850
25592
  const footerComponents = useComponentsOfPart("footer");
24851
25593
  const headerComponents = useComponentsOfPart("header");
24852
25594
  const headerMenuComponents = useComponentsOfPart("header-menu");
@@ -24890,36 +25632,97 @@ function MobileWorkbench(props) {
24890
25632
  if (!viewportElement) return;
24891
25633
  let stableHeight = Math.round(mountContainer.getBoundingClientRect().height || window.innerHeight);
24892
25634
  let stableWidth = Math.round(mountContainer.getBoundingClientRect().width || window.innerWidth);
24893
- const updateKeyboardInset = () => {
24894
- const visibleBottom = visualViewport ? visualViewport.offsetTop + visualViewport.height : window.innerHeight;
24895
- setKeyboardInset(Math.max(0, Math.round(stableHeight - visibleBottom)));
25635
+ let baselineInset = Math.max(0, stableHeight - Math.round(visualViewport ? visualViewport.offsetTop + visualViewport.height : window.innerHeight));
25636
+ let keyboardVisible = false;
25637
+ let initialViewportFrame = null;
25638
+ let revealFrame = null;
25639
+ let revealInnerFrame = null;
25640
+ const isEditing = () => {
25641
+ const activeElement = document.activeElement;
25642
+ return activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement || (activeElement === null || activeElement === void 0 ? void 0 : activeElement.getAttribute("contenteditable")) === "true";
25643
+ };
25644
+ const cancelReveal = () => {
25645
+ if (revealFrame != null) {
25646
+ cancelAnimationFrame(revealFrame);
25647
+ revealFrame = null;
25648
+ }
25649
+ if (revealInnerFrame != null) {
25650
+ cancelAnimationFrame(revealInnerFrame);
25651
+ revealInnerFrame = null;
25652
+ }
25653
+ };
25654
+ const scheduleReveal = (viewport) => {
25655
+ cancelReveal();
25656
+ if (!viewport) return;
25657
+ revealFrame = requestAnimationFrame(() => {
25658
+ revealFrame = null;
25659
+ revealInnerFrame = requestAnimationFrame(() => {
25660
+ revealInnerFrame = null;
25661
+ (0, _univerjs_design.revealFocusedElementInMobileViewport)(document.body, viewport);
25662
+ });
25663
+ });
25664
+ };
25665
+ const updateKeyboardViewport = () => {
25666
+ const visibleTop = (visualViewport === null || visualViewport === void 0 ? void 0 : visualViewport.offsetTop) ?? 0;
25667
+ const visibleHeight = (visualViewport === null || visualViewport === void 0 ? void 0 : visualViewport.height) ?? window.innerHeight;
25668
+ const visibleBottom = visualViewport ? visibleTop + visibleHeight : window.innerHeight;
25669
+ const viewportInset = Math.max(0, Math.round(stableHeight - visibleBottom));
25670
+ const keyboardInset = resolveMobileKeyboardInset(stableHeight, visibleBottom, baselineInset);
25671
+ if (!isEditing()) {
25672
+ keyboardVisible = false;
25673
+ if (keyboardInset === 0) baselineInset = viewportInset;
25674
+ } else if (keyboardInset > 0) keyboardVisible = true;
25675
+ else if (keyboardVisible && keyboardInset === 0) {
25676
+ keyboardVisible = false;
25677
+ baselineInset = viewportInset;
25678
+ }
25679
+ viewportElement.style.setProperty("--univer-mobile-keyboard-inset", `${keyboardVisible ? keyboardInset : 0}px`);
25680
+ const nextKeyboardInset = keyboardVisible ? keyboardInset : 0;
25681
+ const nextKeyboardViewport = keyboardVisible ? {
25682
+ top: Math.round(visibleTop),
25683
+ bottom: Math.round(visibleBottom),
25684
+ height: Math.round(visibleHeight),
25685
+ stableHeight
25686
+ } : null;
25687
+ setKeyboardInset(nextKeyboardInset);
25688
+ setKeyboardViewport(nextKeyboardViewport);
25689
+ scheduleReveal(nextKeyboardViewport);
24896
25690
  };
24897
25691
  const updateStableViewport = () => {
25692
+ const height = Math.round(mountContainer.getBoundingClientRect().height || window.innerHeight);
24898
25693
  const width = Math.round(mountContainer.getBoundingClientRect().width || window.innerWidth);
24899
- const activeElement = document.activeElement;
24900
- if (!(activeElement instanceof HTMLInputElement || activeElement instanceof HTMLTextAreaElement || (activeElement === null || activeElement === void 0 ? void 0 : activeElement.getAttribute("contenteditable")) === "true") || width !== stableWidth) {
24901
- stableHeight = Math.round(mountContainer.getBoundingClientRect().height || window.innerHeight);
25694
+ const editing = isEditing();
25695
+ if (shouldUpdateMobileStableHeight(stableHeight, height, stableWidth, width, editing, keyboardVisible)) {
25696
+ stableHeight = height;
24902
25697
  stableWidth = width;
24903
25698
  viewportElement.style.height = `${stableHeight}px`;
24904
25699
  }
24905
- updateKeyboardInset();
25700
+ updateKeyboardViewport();
24906
25701
  };
24907
25702
  viewportElement.style.height = `${stableHeight}px`;
24908
- updateKeyboardInset();
25703
+ initialViewportFrame = requestAnimationFrame(() => {
25704
+ initialViewportFrame = null;
25705
+ updateKeyboardViewport();
25706
+ });
24909
25707
  window.addEventListener("resize", updateStableViewport);
24910
- visualViewport === null || visualViewport === void 0 || visualViewport.addEventListener("resize", updateKeyboardInset);
24911
- visualViewport === null || visualViewport === void 0 || visualViewport.addEventListener("scroll", updateKeyboardInset);
25708
+ visualViewport === null || visualViewport === void 0 || visualViewport.addEventListener("resize", updateKeyboardViewport);
25709
+ visualViewport === null || visualViewport === void 0 || visualViewport.addEventListener("scroll", updateKeyboardViewport);
25710
+ document.addEventListener("focusin", updateKeyboardViewport);
24912
25711
  return () => {
25712
+ if (initialViewportFrame != null) cancelAnimationFrame(initialViewportFrame);
25713
+ cancelReveal();
24913
25714
  window.removeEventListener("resize", updateStableViewport);
24914
- visualViewport === null || visualViewport === void 0 || visualViewport.removeEventListener("resize", updateKeyboardInset);
24915
- visualViewport === null || visualViewport === void 0 || visualViewport.removeEventListener("scroll", updateKeyboardInset);
25715
+ visualViewport === null || visualViewport === void 0 || visualViewport.removeEventListener("resize", updateKeyboardViewport);
25716
+ visualViewport === null || visualViewport === void 0 || visualViewport.removeEventListener("scroll", updateKeyboardViewport);
25717
+ document.removeEventListener("focusin", updateKeyboardViewport);
24916
25718
  };
24917
25719
  }, [mountContainer]);
24918
25720
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.ConfigProvider, {
24919
25721
  locale: locale === null || locale === void 0 ? void 0 : locale.design,
24920
25722
  direction,
24921
25723
  mountContainer: portalContainer,
24922
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileKeyboardInsetContext.Provider, {
25724
+ mobileKeyboardViewport: keyboardViewport,
25725
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileCanvasLayoutProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileKeyboardInsetContext.Provider, {
24923
25726
  value: keyboardInset,
24924
25727
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(MobileDrawerCoordinatorProvider, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
24925
25728
  ref: viewportRef,
@@ -24945,7 +25748,7 @@ function MobileWorkbench(props) {
24945
25748
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
24946
25749
  className: "univer-relative univer-flex univer-min-h-0 univer-flex-1 univer-flex-col",
24947
25750
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
24948
- className: "univer-grid univer-h-full univer-grid-cols-[auto_1fr_auto] univer-grid-rows-[100%] univer-overflow-hidden",
25751
+ className: "univer-grid univer-min-h-0 univer-flex-1 univer-grid-cols-[auto_1fr_auto] univer-grid-rows-[100%] univer-overflow-hidden",
24949
25752
  children: [
24950
25753
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", {
24951
25754
  className: "univer-h-full",
@@ -24957,16 +25760,29 @@ function MobileWorkbench(props) {
24957
25760
  className: "univer-w-screen",
24958
25761
  children: header && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, { components: headerComponents }, "header")
24959
25762
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("section", {
24960
- ref: contentRef,
24961
- className: "univer-relative univer-overflow-hidden",
24962
- "data-range-selector": true,
24963
- onContextMenu: (e) => e.preventDefault(),
24964
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, { components: contentComponents }, "content")
25763
+ ref: canvasContainerRef,
25764
+ className: "univer-relative univer-min-h-0 univer-overflow-hidden",
25765
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
25766
+ ref: contentRef,
25767
+ className: "univer-absolute univer-inset-0 univer-overflow-hidden",
25768
+ "data-range-selector": true,
25769
+ onContextMenu: (e) => e.preventDefault(),
25770
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, {
25771
+ components: contentComponents,
25772
+ sharedProps: {
25773
+ containerRef: canvasContainerRef,
25774
+ canvasRef: contentRef
25775
+ }
25776
+ }, "content")
25777
+ })
24965
25778
  })]
24966
25779
  }),
24967
25780
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", { className: "univer-h-full" })
24968
25781
  ]
24969
- }), footer && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, { components: footerComponents }, "footer") })]
25782
+ }), footer && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", {
25783
+ className: "univer-shrink-0",
25784
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ComponentContainer, { components: footerComponents }, "footer")
25785
+ })]
24970
25786
  })]
24971
25787
  }), (!ready || externalSkeletonVisible) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(WorkbenchSkeleton, {
24972
25788
  darkMode,
@@ -24982,7 +25798,7 @@ function MobileWorkbench(props) {
24982
25798
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileSidebar, {})
24983
25799
  ]
24984
25800
  })] })
24985
- })
25801
+ }) })
24986
25802
  });
24987
25803
  }
24988
25804
 
@@ -25532,7 +26348,8 @@ function MobileContextConfirm(props) {
25532
26348
  });
25533
26349
  }
25534
26350
  function MobileConfirmPart() {
25535
- return (0, _wendellhu_redi_react_bindings.useObservable)((0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.IConfirmService).confirmOptions$, []).map((options) => {
26351
+ const confirmService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.IConfirmService);
26352
+ return (0, _wendellhu_redi_react_bindings.useObservable)(confirmService.confirmOptions$, []).map((options) => {
25536
26353
  const { children, title, ...restProps } = options;
25537
26354
  const confirmProps = restProps;
25538
26355
  for (const key of ["children", "title"]) {
@@ -25616,16 +26433,26 @@ function toMobileDialogOptions(options) {
25616
26433
  function MobileDialogPart() {
25617
26434
  const dialogService = (0, _wendellhu_redi_react_bindings.useDependency)(IDialogService);
25618
26435
  const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
26436
+ const { locale } = (0, react.useContext)(_univerjs_design.ConfigContext);
25619
26437
  const dialogOptions = (0, _wendellhu_redi_react_bindings.useObservable)(dialogService.getDialogs$(), []);
25620
26438
  const options = (0, react.useMemo)(() => {
25621
26439
  const activeDialogs = dialogOptions.filter((item) => item.open !== false);
25622
26440
  const active = activeDialogs[activeDialogs.length - 1];
25623
26441
  return active ? toMobileDialogOptions(active) : null;
25624
26442
  }, [dialogOptions]);
25625
- const [drawerSnap, setDrawerSnap] = (0, react.useState)("expanded");
26443
+ const [snapOverride, setSnapOverride] = (0, react.useState)(null);
25626
26444
  const layerRef = (0, react.useRef)(null);
25627
26445
  const backdropPointerIdRef = (0, react.useRef)(null);
25628
26446
  if (!options) return null;
26447
+ const defaultSnap = options.layout === "canvas" ? "compact" : "expanded";
26448
+ const footer = options.footer ?? (options.showOk || options.showCancel ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [options.showCancel && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Button, {
26449
+ onClick: options.onCancel,
26450
+ children: locale === null || locale === void 0 ? void 0 : locale.Confirm.cancel
26451
+ }), options.showOk && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Button, {
26452
+ variant: "primary",
26453
+ onClick: options.onOk,
26454
+ children: locale === null || locale === void 0 ? void 0 : locale.Confirm.confirm
26455
+ })] }) : null);
25629
26456
  const close = () => {
25630
26457
  var _options$onClose, _options$onOpenChange;
25631
26458
  dialogService.close(options.id);
@@ -25634,12 +26461,12 @@ function MobileDialogPart() {
25634
26461
  };
25635
26462
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
25636
26463
  ref: layerRef,
25637
- className: "univer-fixed univer-inset-0 univer-z-[1200]",
26464
+ className: "univer-pointer-events-none univer-fixed univer-inset-0 univer-z-[1200]",
25638
26465
  "data-u-comp": "mobile-dialog",
25639
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
26466
+ children: [options.layout !== "canvas" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
25640
26467
  type: "button",
25641
26468
  "aria-label": localeService.t("ui.sidebar.close"),
25642
- className: "univer-absolute univer-inset-0 univer-m-0 univer-appearance-none univer-rounded-none univer-border-0 univer-bg-black/35 univer-p-0",
26469
+ className: "univer-pointer-events-auto univer-absolute univer-inset-0 univer-m-0 univer-appearance-none univer-rounded-none univer-border-0 univer-bg-black/35 univer-p-0",
25643
26470
  onPointerDown: options.maskClosable === false ? void 0 : (event) => {
25644
26471
  backdropPointerIdRef.current = event.pointerId;
25645
26472
  },
@@ -25653,11 +26480,15 @@ function MobileDialogPart() {
25653
26480
  }
25654
26481
  }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MobileDrawer, {
25655
26482
  layerRef,
26483
+ layout: options.layout,
25656
26484
  componentName: "mobile-dialog-drawer",
25657
- snap: drawerSnap,
26485
+ snap: (snapOverride === null || snapOverride === void 0 ? void 0 : snapOverride.id) === options.id ? snapOverride.snap : defaultSnap,
25658
26486
  expandLabel: localeService.t("ui.sidebar.resize"),
25659
26487
  collapseLabel: localeService.t("ui.sidebar.resize"),
25660
- onSnapChange: setDrawerSnap,
26488
+ onSnapChange: (snap) => setSnapOverride({
26489
+ id: options.id,
26490
+ snap
26491
+ }),
25661
26492
  onClose: close,
25662
26493
  role: "dialog",
25663
26494
  panelClassName: "\n univer-bg-gray-0 univer-text-gray-900\n dark:!univer-bg-gray-900 dark:!univer-text-gray-0\n ",
@@ -25675,9 +26506,9 @@ function MobileDialogPart() {
25675
26506
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_icons.CloseIcon, {})
25676
26507
  })]
25677
26508
  }),
25678
- footer: options.footer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", {
26509
+ footer: footer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("footer", {
25679
26510
  className: "univer-shrink-0 univer-border-0 univer-border-t univer-border-solid univer-border-gray-200 univer-p-4 dark:!univer-border-gray-700",
25680
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.MobileActionRowGroup, { children: options.footer })
26511
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.MobileActionRowGroup, { children: footer })
25681
26512
  }) : void 0,
25682
26513
  children: options.children
25683
26514
  })]
@@ -25729,7 +26560,8 @@ function DialogItem(props) {
25729
26560
  });
25730
26561
  }
25731
26562
  function DialogPart() {
25732
- const dialogOptions = (0, _wendellhu_redi_react_bindings.useObservable)((0, _wendellhu_redi_react_bindings.useDependency)(IDialogService).getDialogs$(), []);
26563
+ const dialogService = (0, _wendellhu_redi_react_bindings.useDependency)(IDialogService);
26564
+ const dialogOptions = (0, _wendellhu_redi_react_bindings.useObservable)(dialogService.getDialogs$(), []);
25733
26565
  const attrs = (0, react.useMemo)(() => dialogOptions.map((options) => {
25734
26566
  const { children, title, footer, ...restProps } = options;
25735
26567
  const dialogProps = restProps;
@@ -25859,7 +26691,8 @@ const IGalleryService = (0, _univerjs_core.createIdentifier)("univer.ui.gallery-
25859
26691
  * limitations under the License.
25860
26692
  */
25861
26693
  function GalleryPart() {
25862
- const gallery = (0, _wendellhu_redi_react_bindings.useObservable)((0, _wendellhu_redi_react_bindings.useDependency)(IGalleryService).gallery$);
26694
+ const galleryService = (0, _wendellhu_redi_react_bindings.useDependency)(IGalleryService);
26695
+ const gallery = (0, _wendellhu_redi_react_bindings.useObservable)(galleryService.gallery$);
25863
26696
  if (!gallery) return null;
25864
26697
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Gallery, { ...gallery });
25865
26698
  }
@@ -26208,7 +27041,8 @@ var DesktopLocalStorageService = class {
26208
27041
  */
26209
27042
  function MessageContainer() {
26210
27043
  const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
26211
- const darkMode = (0, _wendellhu_redi_react_bindings.useObservable)((0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.ThemeService).darkMode$);
27044
+ const themeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.ThemeService);
27045
+ const darkMode = (0, _wendellhu_redi_react_bindings.useObservable)(themeService.darkMode$);
26212
27046
  const direction = (0, _wendellhu_redi_react_bindings.useObservable)(localeService.direction$);
26213
27047
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Messager, {
26214
27048
  theme: darkMode ? "dark" : "light",
@@ -26236,7 +27070,8 @@ let DesktopMessageService = class DesktopMessageService extends _univerjs_core.D
26236
27070
  show(options) {
26237
27071
  const id = options.id ?? `message-${Date.now()}-${messageId}`;
26238
27072
  messageId += 1;
26239
- (0, _univerjs_design.message)(Object.assign({}, options, { id }));
27073
+ const op = Object.assign({}, options, { id });
27074
+ (0, _univerjs_design.message)(op);
26240
27075
  return (0, _univerjs_core.toDisposable)(() => (0, _univerjs_design.removeMessage)(id));
26241
27076
  }
26242
27077
  remove(id) {
@@ -26252,22 +27087,28 @@ DesktopMessageService = __decorate([__decorateParam(0, (0, _univerjs_core.Inject
26252
27087
  //#region src/views/notification/Notification.tsx
26253
27088
  function Notification() {
26254
27089
  const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
26255
- const darkMode = (0, _wendellhu_redi_react_bindings.useObservable)((0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.ThemeService).darkMode$);
27090
+ const themeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.ThemeService);
27091
+ const darkMode = (0, _wendellhu_redi_react_bindings.useObservable)(themeService.darkMode$);
26256
27092
  const direction = (0, _wendellhu_redi_react_bindings.useObservable)(localeService.direction$);
26257
27093
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.Toaster, {
26258
27094
  theme: darkMode ? "dark" : "light",
26259
27095
  dir: direction
26260
27096
  });
26261
27097
  }
26262
- const notification = { show: (options) => {
26263
- const { type = "message", title, content, duration, closable = true, position = "top-right" } = options;
26264
- _univerjs_design.toast[type](title, {
26265
- position,
26266
- description: content,
26267
- duration,
26268
- closeButton: closable
26269
- });
26270
- } };
27098
+ const notification = {
27099
+ show: (options) => {
27100
+ const { type = "message", title, content, duration, closable = true, dismissible = true, position = "top-right", action } = options;
27101
+ return _univerjs_design.toast[type](title, {
27102
+ position,
27103
+ description: content,
27104
+ duration,
27105
+ closeButton: closable,
27106
+ dismissible,
27107
+ action
27108
+ });
27109
+ },
27110
+ dismiss: (id) => _univerjs_design.toast.dismiss(id)
27111
+ };
26271
27112
 
26272
27113
  //#endregion
26273
27114
  //#region src/services/notification/desktop-notification.service.ts
@@ -26279,8 +27120,8 @@ let DesktopNotificationService = class DesktopNotificationService extends _unive
26279
27120
  this._initUIPart();
26280
27121
  }
26281
27122
  show(params) {
26282
- notification.show(params);
26283
- return (0, _univerjs_core.toDisposable)(() => {});
27123
+ const notificationID = notification.show(params);
27124
+ return (0, _univerjs_core.toDisposable)(() => notification.dismiss(notificationID));
26284
27125
  }
26285
27126
  _initUIPart() {
26286
27127
  this.disposeWithMe(this._uiPartsService.registerComponent("global", () => (0, _wendellhu_redi_react_bindings.connectInjector)(Notification, this._injector)));
@@ -26513,10 +27354,7 @@ let UniverMobileUIPlugin = class UniverMobileUIPlugin extends _univerjs_core.Plu
26513
27354
  useClass: DesktopSidebarService,
26514
27355
  lazy: true
26515
27356
  }],
26516
- [IMessageService, {
26517
- useClass: DesktopMessageService,
26518
- lazy: true
26519
- }],
27357
+ [IMessageService, { useClass: DesktopMessageService }],
26520
27358
  [_univerjs_core.ILocalStorageService, {
26521
27359
  useClass: DesktopLocalStorageService,
26522
27360
  lazy: true
@@ -26531,6 +27369,8 @@ let UniverMobileUIPlugin = class UniverMobileUIPlugin extends _univerjs_core.Plu
26531
27369
  useFactory: (injector) => injector.createInstance(MobileUIController, this._config),
26532
27370
  deps: [_univerjs_core.Injector]
26533
27371
  }],
27372
+ [FormatPainterSessionService],
27373
+ [FormatPainterController],
26534
27374
  [SharedController],
26535
27375
  [ErrorController]
26536
27376
  ], this._config.override));
@@ -26541,7 +27381,7 @@ let UniverMobileUIPlugin = class UniverMobileUIPlugin extends _univerjs_core.Plu
26541
27381
  ]);
26542
27382
  }
26543
27383
  onReady() {
26544
- (0, _univerjs_core.touchDependencies)(this._injector, [[SharedController]]);
27384
+ (0, _univerjs_core.touchDependencies)(this._injector, [[SharedController], [FormatPainterController]]);
26545
27385
  }
26546
27386
  };
26547
27387
  _defineProperty(UniverMobileUIPlugin, "pluginName", "UNIVER_MOBILE_UI_PLUGIN");
@@ -27274,8 +28114,10 @@ function ObjectPermissionDialog({ target, name, commandId, actions = DEFAULT_ACT
27274
28114
  (0, react.useEffect)(() => {
27275
28115
  const subscription = permissions.unitChanges$.subscribe((changedUnitId) => {
27276
28116
  if (changedUnitId !== unitId) return;
27277
- if (!saving) if (dirty) setConflict(true);
27278
- else setAttempt((value) => value + 1);
28117
+ if (!saving) {
28118
+ if (dirty) setConflict(true);
28119
+ else setAttempt((value) => value + 1);
28120
+ }
27279
28121
  });
27280
28122
  return () => subscription.unsubscribe();
27281
28123
  }, [
@@ -27598,6 +28440,8 @@ let ComponentsController = class ComponentsController extends _univerjs_core.Dis
27598
28440
  }
27599
28441
  _registerIcons() {
27600
28442
  this.disposeWithMe(this._iconManager.register({
28443
+ BrushIcon: _univerjs_icons.BrushIcon,
28444
+ ClearFormatDoubleIcon: _univerjs_icons.ClearFormatDoubleIcon,
27601
28445
  ExpandIcon: _univerjs_icons.ExpandIcon,
27602
28446
  IncreaseIcon: _univerjs_icons.IncreaseIcon,
27603
28447
  KeyboardIcon: _univerjs_icons.KeyboardIcon,
@@ -27682,7 +28526,8 @@ const ContextConfirm = (props) => {
27682
28526
  });
27683
28527
  };
27684
28528
  function ConfirmPart() {
27685
- const props = (0, _wendellhu_redi_react_bindings.useObservable)((0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.IConfirmService).confirmOptions$, []).map((options) => {
28529
+ const confirmService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.IConfirmService);
28530
+ const props = (0, _wendellhu_redi_react_bindings.useObservable)(confirmService.confirmOptions$, []).map((options) => {
27686
28531
  const { children, title, ...restProps } = options;
27687
28532
  const confirmProps = restProps;
27688
28533
  for (const key of ["children", "title"]) {
@@ -27812,10 +28657,7 @@ let UniverUIPlugin = class UniverUIPlugin extends _univerjs_core.Plugin {
27812
28657
  useClass: DesktopSidebarService,
27813
28658
  lazy: true
27814
28659
  }],
27815
- [IMessageService, {
27816
- useClass: DesktopMessageService,
27817
- lazy: true
27818
- }],
28660
+ [IMessageService, { useClass: DesktopMessageService }],
27819
28661
  [_univerjs_core.ILocalStorageService, {
27820
28662
  useClass: DesktopLocalStorageService,
27821
28663
  lazy: true
@@ -27830,6 +28672,8 @@ let UniverUIPlugin = class UniverUIPlugin extends _univerjs_core.Plugin {
27830
28672
  useFactory: (injector) => injector.createInstance(DesktopUIController, this._config),
27831
28673
  deps: [_univerjs_core.Injector]
27832
28674
  }],
28675
+ [FormatPainterSessionService],
28676
+ [FormatPainterController],
27833
28677
  [SharedController],
27834
28678
  [ErrorController],
27835
28679
  [FeatureSearchController],
@@ -27842,7 +28686,11 @@ let UniverUIPlugin = class UniverUIPlugin extends _univerjs_core.Plugin {
27842
28686
  ]);
27843
28687
  }
27844
28688
  onReady() {
27845
- (0, _univerjs_core.touchDependencies)(this._injector, [[SharedController], [FeatureSearchController]]);
28689
+ (0, _univerjs_core.touchDependencies)(this._injector, [
28690
+ [SharedController],
28691
+ [FormatPainterController],
28692
+ [FeatureSearchController]
28693
+ ]);
27846
28694
  }
27847
28695
  onSteady() {
27848
28696
  (0, _univerjs_core.touchDependencies)(this._injector, [[ShortcutPanelController]]);
@@ -28003,11 +28851,13 @@ function handleStringToStyle($dom, cssStyle = "") {
28003
28851
  const s = originStr.toLowerCase();
28004
28852
  const key = textTrim(s.substr(0, s.indexOf(":")));
28005
28853
  const value = textTrim(s.substr(s.indexOf(":") + 1));
28006
- if (key === "font-weight") if (value === "bold" || value === "700") styleList.bl = 1;
28007
- else styleList.bl = 0;
28008
- else if (key === "font-style") if (value === "italic") styleList.it = 1;
28009
- else styleList.it = 0;
28010
- else if (key === "font-family") {
28854
+ if (key === "font-weight") {
28855
+ if (value === "bold" || value === "700") styleList.bl = 1;
28856
+ else styleList.bl = 0;
28857
+ } else if (key === "font-style") {
28858
+ if (value === "italic") styleList.it = 1;
28859
+ else styleList.it = 0;
28860
+ } else if (key === "font-family") {
28011
28861
  const fontFamily = extractFontFamily(textTrim(originStr));
28012
28862
  styleList.ff = fontFamily;
28013
28863
  } else if (key === "font-size") {
@@ -28091,12 +28941,14 @@ function handleStringToStyle($dom, cssStyle = "") {
28091
28941
  }
28092
28942
  }
28093
28943
  if (key === "univer-underline") styleList.ul = { s: 1 };
28094
- if (key === "vertical-align") if (value === "sub") styleList.va = _univerjs_core.BaselineOffset.SUBSCRIPT;
28095
- else if (value === "super") styleList.va = _univerjs_core.BaselineOffset.SUPERSCRIPT;
28096
- else if (value === "top") styleList.vt = 1;
28097
- else if (value === "middle") styleList.vt = 2;
28098
- else if (value === "bottom") styleList.vt = 3;
28099
- else styleList.va = _univerjs_core.BaselineOffset.NORMAL;
28944
+ if (key === "vertical-align") {
28945
+ if (value === "sub") styleList.va = _univerjs_core.BaselineOffset.SUBSCRIPT;
28946
+ else if (value === "super") styleList.va = _univerjs_core.BaselineOffset.SUPERSCRIPT;
28947
+ else if (value === "top") styleList.vt = 1;
28948
+ else if (value === "middle") styleList.vt = 2;
28949
+ else if (value === "bottom") styleList.vt = 3;
28950
+ else styleList.va = _univerjs_core.BaselineOffset.NORMAL;
28951
+ }
28100
28952
  if (key === "transform") {
28101
28953
  const values = value.split(")");
28102
28954
  const index = values.findIndex((item) => item.includes("rotate"));
@@ -28112,11 +28964,13 @@ function handleStringToStyle($dom, cssStyle = "") {
28112
28964
  };
28113
28965
  }
28114
28966
  }
28115
- if (key === "text-align") if (value === "left") styleList.ht = 1;
28116
- else if (value === "center") styleList.ht = 2;
28117
- else if (value === "right") styleList.ht = 3;
28118
- else if (value === "justify") styleList.ht = 4;
28119
- else styleList.ht = 0;
28967
+ if (key === "text-align") {
28968
+ if (value === "left") styleList.ht = 1;
28969
+ else if (value === "center") styleList.ht = 2;
28970
+ else if (value === "right") styleList.ht = 3;
28971
+ else if (value === "justify") styleList.ht = 4;
28972
+ else styleList.ht = 0;
28973
+ }
28120
28974
  if (styleList.tb !== 1) {
28121
28975
  if (key === "overflow-wrap" || key === "word-wrap") {
28122
28976
  if (value === "break-word") styleList.tb = 3;
@@ -28389,20 +29243,22 @@ function handleTableMergeData(data, selection) {
28389
29243
  minC + copyC - 1;
28390
29244
  }
28391
29245
  const mergeData = [];
28392
- for (let i = 0; i < data.length; i++) for (let j = 0; j < data[i].length; j++) if (data[i][j] && typeof data[i][j] === "object" && "mc" in data[i][j]) if (data[i][j].mc) {
28393
- const mc = data[i][j].mc;
28394
- const startRow = mc.r + minH;
28395
- const endRow = startRow + mc.rs;
28396
- const startColumn = mc.c + minC;
28397
- const endColumn = startColumn + mc.cs;
28398
- mergeData.push({
28399
- startRow,
28400
- endRow,
28401
- startColumn,
28402
- endColumn
28403
- });
28404
- delete data[i][j].mc;
28405
- } else data[i][j] = null;
29246
+ for (let i = 0; i < data.length; i++) for (let j = 0; j < data[i].length; j++) if (data[i][j] && typeof data[i][j] === "object" && "mc" in data[i][j]) {
29247
+ if (data[i][j].mc) {
29248
+ const mc = data[i][j].mc;
29249
+ const startRow = mc.r + minH;
29250
+ const endRow = startRow + mc.rs;
29251
+ const startColumn = mc.c + minC;
29252
+ const endColumn = startColumn + mc.cs;
29253
+ mergeData.push({
29254
+ startRow,
29255
+ endRow,
29256
+ startColumn,
29257
+ endColumn
29258
+ });
29259
+ delete data[i][j].mc;
29260
+ } else data[i][j] = null;
29261
+ }
28406
29262
  return {
28407
29263
  data,
28408
29264
  mergeData
@@ -28477,7 +29333,8 @@ function getStyles(styleText) {
28477
29333
  if (!style[i]) continue;
28478
29334
  let attr = style[i].split("{")[0].trim();
28479
29335
  if (attr.includes(".")) attr = attr.slice(1);
28480
- output[attr] = style[i].split("{")[1].trim();
29336
+ const value = style[i].split("{")[1].trim();
29337
+ output[attr] = value;
28481
29338
  }
28482
29339
  return output;
28483
29340
  }
@@ -28492,6 +29349,221 @@ function extractFontFamily(styleStr) {
28492
29349
  return matches ? (matches[1] || matches[2] || matches[3]).trim() : null;
28493
29350
  }
28494
29351
 
29352
+ //#endregion
29353
+ //#region src/utils/mobile-canvas-gesture.ts
29354
+ /** Routes touch browsing separately from the canvas's existing object manipulation. */
29355
+ var MobileCanvasGesture = class extends _univerjs_core.Disposable {
29356
+ constructor(_canvas, _options) {
29357
+ super();
29358
+ this._canvas = _canvas;
29359
+ this._options = _options;
29360
+ _defineProperty(this, "_points", /* @__PURE__ */ new Map());
29361
+ _defineProperty(this, "_objectPointerId", null);
29362
+ _defineProperty(this, "_cancellingObject", false);
29363
+ _defineProperty(this, "_startPoint", null);
29364
+ _defineProperty(this, "_moved", false);
29365
+ _defineProperty(this, "_pinching", false);
29366
+ _defineProperty(this, "_suppressClick", false);
29367
+ _defineProperty(this, "_lastMoveTime", 0);
29368
+ _defineProperty(this, "_velocity", {
29369
+ x: 0,
29370
+ y: 0
29371
+ });
29372
+ _defineProperty(this, "_frame", null);
29373
+ const touchAction = _canvas.style.touchAction;
29374
+ _canvas.style.touchAction = "none";
29375
+ const down = (event) => this._onDown(event);
29376
+ const move = (event) => this._onMove(event);
29377
+ const up = (event) => this._onEnd(event);
29378
+ const blur = () => this._reset();
29379
+ const click = (event) => {
29380
+ if (event.target === _canvas && this._suppressClick) {
29381
+ event.preventDefault();
29382
+ event.stopImmediatePropagation();
29383
+ }
29384
+ };
29385
+ window.addEventListener("pointerdown", down, true);
29386
+ window.addEventListener("pointermove", move, true);
29387
+ window.addEventListener("pointerup", up, true);
29388
+ window.addEventListener("pointercancel", up, true);
29389
+ window.addEventListener("click", click, true);
29390
+ window.addEventListener("blur", blur);
29391
+ this.disposeWithMe((0, _univerjs_core.toDisposable)(() => {
29392
+ this._reset();
29393
+ _canvas.style.touchAction = touchAction;
29394
+ window.removeEventListener("pointerdown", down, true);
29395
+ window.removeEventListener("pointermove", move, true);
29396
+ window.removeEventListener("pointerup", up, true);
29397
+ window.removeEventListener("pointercancel", up, true);
29398
+ window.removeEventListener("click", click, true);
29399
+ window.removeEventListener("blur", blur);
29400
+ }));
29401
+ }
29402
+ _point(event) {
29403
+ const rect = this._canvas.getBoundingClientRect();
29404
+ return {
29405
+ x: event.clientX - rect.left,
29406
+ y: event.clientY - rect.top
29407
+ };
29408
+ }
29409
+ _consume(event) {
29410
+ event.preventDefault();
29411
+ event.stopImmediatePropagation();
29412
+ }
29413
+ _onDown(event) {
29414
+ this._stopInertia();
29415
+ if (event.target !== this._canvas || event.pointerType !== "touch") {
29416
+ this._suppressClick = false;
29417
+ return;
29418
+ }
29419
+ const point = this._point(event);
29420
+ if (this._points.size === 0) {
29421
+ this._suppressClick = false;
29422
+ const action = this._options.start(point);
29423
+ if (action === "ignore") return;
29424
+ this._startPoint = point;
29425
+ this._moved = false;
29426
+ this._lastMoveTime = event.timeStamp;
29427
+ this._points.set(event.pointerId, point);
29428
+ if (action === "object") {
29429
+ this._objectPointerId = event.pointerId;
29430
+ return;
29431
+ }
29432
+ } else {
29433
+ this._points.set(event.pointerId, point);
29434
+ if (!this._pinching) {
29435
+ this._options.finishObjectTransform();
29436
+ this._cancelObjectPointer();
29437
+ this._pinching = true;
29438
+ this._moved = true;
29439
+ }
29440
+ }
29441
+ this._suppressClick = true;
29442
+ this._consume(event);
29443
+ }
29444
+ _onMove(event) {
29445
+ const previous = this._points.get(event.pointerId);
29446
+ if (!previous) return;
29447
+ const point = this._point(event);
29448
+ const previousPoints = Array.from(this._points.values());
29449
+ this._points.set(event.pointerId, point);
29450
+ if (this._pinching) {
29451
+ const points = Array.from(this._points.values());
29452
+ if (points.length >= 2) {
29453
+ const [a, b] = previousPoints;
29454
+ const [c, d] = points;
29455
+ const distance = Math.hypot(a.x - b.x, a.y - b.y);
29456
+ if (distance > 0) this._options.pinch(Math.hypot(c.x - d.x, c.y - d.y) / distance, {
29457
+ x: (a.x + b.x) / 2,
29458
+ y: (a.y + b.y) / 2
29459
+ }, {
29460
+ x: (c.x + d.x) / 2,
29461
+ y: (c.y + d.y) / 2
29462
+ });
29463
+ }
29464
+ this._consume(event);
29465
+ return;
29466
+ }
29467
+ if (this._objectPointerId !== null) return;
29468
+ if (!this._moved && this._startPoint && Math.hypot(point.x - this._startPoint.x, point.y - this._startPoint.y) >= 8) {
29469
+ this._moved = true;
29470
+ this._options.pan({
29471
+ x: point.x - this._startPoint.x,
29472
+ y: point.y - this._startPoint.y
29473
+ });
29474
+ } else if (this._moved) this._options.pan({
29475
+ x: point.x - previous.x,
29476
+ y: point.y - previous.y
29477
+ });
29478
+ const elapsed = Math.max(1, event.timeStamp - this._lastMoveTime);
29479
+ this._velocity = {
29480
+ x: (point.x - previous.x) / elapsed,
29481
+ y: (point.y - previous.y) / elapsed
29482
+ };
29483
+ this._lastMoveTime = event.timeStamp;
29484
+ this._consume(event);
29485
+ }
29486
+ _onEnd(event) {
29487
+ if (this._cancellingObject) return;
29488
+ if (!this._points.has(event.pointerId)) return;
29489
+ this._points.delete(event.pointerId);
29490
+ const objectPointer = this._objectPointerId === event.pointerId;
29491
+ if (objectPointer) this._objectPointerId = null;
29492
+ else this._consume(event);
29493
+ if (this._points.size !== 0) return;
29494
+ if (this._pinching) this._options.endPinch();
29495
+ else if (!objectPointer && event.type !== "pointercancel") {
29496
+ if (!this._moved) this._options.tap(this._point(event));
29497
+ else if (event.timeStamp - this._lastMoveTime < 80) this._startInertia();
29498
+ }
29499
+ this._pinching = false;
29500
+ this._startPoint = null;
29501
+ }
29502
+ _startInertia() {
29503
+ let velocity = {
29504
+ x: Math.max(-3, Math.min(3, this._velocity.x)),
29505
+ y: Math.max(-3, Math.min(3, this._velocity.y))
29506
+ };
29507
+ let previousTime = performance.now();
29508
+ const frame = (time) => {
29509
+ const elapsed = Math.min(32, time - previousTime);
29510
+ previousTime = time;
29511
+ const decay = Math.exp(-.005 * elapsed);
29512
+ this._options.pan({
29513
+ x: velocity.x * (1 - decay) / .005,
29514
+ y: velocity.y * (1 - decay) / .005
29515
+ });
29516
+ velocity = {
29517
+ x: velocity.x * decay,
29518
+ y: velocity.y * decay
29519
+ };
29520
+ this._frame = Math.hypot(velocity.x, velocity.y) > .02 ? requestAnimationFrame(frame) : null;
29521
+ };
29522
+ if (Math.hypot(velocity.x, velocity.y) > .04) this._frame = requestAnimationFrame(frame);
29523
+ }
29524
+ _stopInertia() {
29525
+ if (this._frame !== null) {
29526
+ cancelAnimationFrame(this._frame);
29527
+ this._frame = null;
29528
+ }
29529
+ this._velocity = {
29530
+ x: 0,
29531
+ y: 0
29532
+ };
29533
+ }
29534
+ _reset() {
29535
+ this._stopInertia();
29536
+ if (this._objectPointerId !== null) {
29537
+ this._options.finishObjectTransform();
29538
+ this._cancelObjectPointer();
29539
+ }
29540
+ if (this._pinching) this._options.endPinch();
29541
+ this._points.clear();
29542
+ this._objectPointerId = null;
29543
+ this._pinching = false;
29544
+ this._startPoint = null;
29545
+ }
29546
+ _cancelObjectPointer() {
29547
+ const pointerId = this._objectPointerId;
29548
+ const point = pointerId === null ? null : this._points.get(pointerId);
29549
+ if (pointerId === null || !point) return;
29550
+ const rect = this._canvas.getBoundingClientRect();
29551
+ this._objectPointerId = null;
29552
+ this._cancellingObject = true;
29553
+ try {
29554
+ this._canvas.dispatchEvent(new PointerEvent("pointercancel", {
29555
+ bubbles: true,
29556
+ pointerId,
29557
+ pointerType: "touch",
29558
+ clientX: rect.left + point.x,
29559
+ clientY: rect.top + point.y
29560
+ }));
29561
+ } finally {
29562
+ this._cancellingObject = false;
29563
+ }
29564
+ }
29565
+ };
29566
+
28495
29567
  //#endregion
28496
29568
  //#region src/views/components/dom/Print.tsx
28497
29569
  const PrintFloatDomSingle = (0, react.memo)((props) => {
@@ -28595,6 +29667,104 @@ function HoverTrack(props) {
28595
29667
  });
28596
29668
  }
28597
29669
 
29670
+ //#endregion
29671
+ //#region src/views/components/mobile-zoom-indicator/mobile-zoom-indicator.ts
29672
+ /**
29673
+ * Copyright 2023-present DreamNum Co., Ltd.
29674
+ *
29675
+ * Licensed under the Apache License, Version 2.0 (the "License");
29676
+ * you may not use this file except in compliance with the License.
29677
+ * You may obtain a copy of the License at
29678
+ *
29679
+ * http://www.apache.org/licenses/LICENSE-2.0
29680
+ *
29681
+ * Unless required by applicable law or agreed to in writing, software
29682
+ * distributed under the License is distributed on an "AS IS" BASIS,
29683
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29684
+ * See the License for the specific language governing permissions and
29685
+ * limitations under the License.
29686
+ */
29687
+ var MobileZoomIndicator = class extends _univerjs_core.Disposable {
29688
+ constructor(_canvasElement) {
29689
+ super();
29690
+ this._canvasElement = _canvasElement;
29691
+ _defineProperty(this, "_element", void 0);
29692
+ _defineProperty(this, "_hideTimer", null);
29693
+ const element = document.createElement("div");
29694
+ element.className = [
29695
+ "univer-absolute",
29696
+ "univer-left-1/2",
29697
+ "univer-top-1/2",
29698
+ "-univer-translate-x-1/2",
29699
+ "-univer-translate-y-1/2",
29700
+ "univer-select-none",
29701
+ "univer-rounded-lg",
29702
+ "univer-bg-gray-900",
29703
+ "univer-px-6",
29704
+ "univer-py-3",
29705
+ "univer-text-2xl",
29706
+ "univer-font-bold",
29707
+ "univer-text-gray-0",
29708
+ "univer-shadow-lg"
29709
+ ].join(" ");
29710
+ element.style.opacity = "0";
29711
+ element.style.pointerEvents = "none";
29712
+ element.style.transition = "opacity 150ms ease-in-out";
29713
+ element.style.zIndex = "10000";
29714
+ this._element = element;
29715
+ this._mount();
29716
+ }
29717
+ show(percentage) {
29718
+ this._mount();
29719
+ if (this._hideTimer != null) {
29720
+ window.clearTimeout(this._hideTimer);
29721
+ this._hideTimer = null;
29722
+ }
29723
+ this._element.textContent = `${percentage}%`;
29724
+ this._element.style.opacity = "1";
29725
+ }
29726
+ hide() {
29727
+ if (this._hideTimer != null) window.clearTimeout(this._hideTimer);
29728
+ this._hideTimer = window.setTimeout(() => {
29729
+ this._hideTimer = null;
29730
+ this._element.style.opacity = "0";
29731
+ }, 300);
29732
+ }
29733
+ dispose() {
29734
+ if (this._hideTimer != null) {
29735
+ window.clearTimeout(this._hideTimer);
29736
+ this._hideTimer = null;
29737
+ }
29738
+ this._element.remove();
29739
+ super.dispose();
29740
+ }
29741
+ _mount() {
29742
+ const container = this._canvasElement.parentElement;
29743
+ if (container == null || this._element.parentElement === container) return;
29744
+ if (window.getComputedStyle(container).position === "static") container.style.position = "relative";
29745
+ container.appendChild(this._element);
29746
+ }
29747
+ };
29748
+
29749
+ //#endregion
29750
+ //#region src/views/font-family/MobileFontFamilyDropdown.tsx
29751
+ function MobileFontFamilyDropdown(props) {
29752
+ const localeService = (0, _wendellhu_redi_react_bindings.useDependency)(_univerjs_core.LocaleService);
29753
+ const disabled = (0, _wendellhu_redi_react_bindings.useObservable)(props.disabled$);
29754
+ const { fonts } = useFontList();
29755
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_univerjs_design.MobileSelect, {
29756
+ "aria-label": props.ariaLabel,
29757
+ className: (0, _univerjs_design.clsx)("univer-h-12 univer-w-full univer-min-w-0 univer-text-base", props.className),
29758
+ value: props.value,
29759
+ disabled: !!(props.disabled || disabled),
29760
+ options: fonts.map((font) => ({
29761
+ value: font.value,
29762
+ label: localeService.t(font.label)
29763
+ })),
29764
+ onChange: props.onChange
29765
+ });
29766
+ }
29767
+
28598
29768
  //#endregion
28599
29769
  //#region src/views/progress-bar/ProgressBar.tsx
28600
29770
  /**
@@ -28616,19 +29786,20 @@ function ProgressBar(props) {
28616
29786
  const { barColor, progress, onTerminate, onClearProgress } = props;
28617
29787
  const { count, done, label = "" } = progress;
28618
29788
  const progressBarInnerRef = (0, react.useRef)(null);
28619
- const [visible, setVisible] = (0, react.useState)(false);
29789
+ const [completedProgress, setCompletedProgress] = (0, react.useState)();
29790
+ const visible = count > 0 && completedProgress !== progress;
28620
29791
  (0, react.useEffect)(() => {
28621
29792
  const progressBarInner = progressBarInnerRef.current;
29793
+ let animationFrame;
28622
29794
  if (count === 0 && done === 0) {
28623
- setVisible(false);
28624
29795
  progressBarInner.style.width = "0%";
28625
29796
  return;
28626
- } else if (count > 0) {
28627
- setVisible(true);
29797
+ }
29798
+ if (count > 0) {
28628
29799
  const width = Math.floor(done / count * 100);
28629
- if (done === count) requestAnimationFrame(() => {
29800
+ if (done === count) animationFrame = requestAnimationFrame(() => {
28630
29801
  progressBarInner.style.width = `${width - 1}%`;
28631
- requestAnimationFrame(() => {
29802
+ animationFrame = requestAnimationFrame(() => {
28632
29803
  progressBarInner.style.width = `${width}%`;
28633
29804
  });
28634
29805
  });
@@ -28636,15 +29807,21 @@ function ProgressBar(props) {
28636
29807
  }
28637
29808
  const handleTransitionEnd = () => {
28638
29809
  if (done === count) {
28639
- setVisible(false);
29810
+ setCompletedProgress(progress);
28640
29811
  onClearProgress && onClearProgress();
28641
29812
  }
28642
29813
  };
28643
29814
  progressBarInner.addEventListener("transitionend", handleTransitionEnd);
28644
29815
  return () => {
29816
+ if (animationFrame !== void 0) cancelAnimationFrame(animationFrame);
28645
29817
  progressBarInner.removeEventListener("transitionend", handleTransitionEnd);
28646
29818
  };
28647
- }, [count, done]);
29819
+ }, [
29820
+ count,
29821
+ done,
29822
+ progress,
29823
+ onClearProgress
29824
+ ]);
28648
29825
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
28649
29826
  className: (0, _univerjs_design.clsx)("univer-mx-2 univer-flex univer-items-center univer-gap-2", {
28650
29827
  "univer-flex": visible,
@@ -28803,6 +29980,7 @@ Object.defineProperty(exports, 'FontService', {
28803
29980
  }
28804
29981
  });
28805
29982
  exports.FontSize = FontSize;
29983
+ exports.FormatPainterSessionService = FormatPainterSessionService;
28806
29984
  exports.HEADING_ITEM_COMPONENT = HEADING_ITEM_COMPONENT;
28807
29985
  exports.HEADING_LIST = HEADING_LIST;
28808
29986
  exports.HOVER_TRACK_HOST_CLASS_NAME = HOVER_TRACK_HOST_CLASS_NAME;
@@ -28850,6 +30028,7 @@ Object.defineProperty(exports, 'MenuManagerService', {
28850
30028
  }
28851
30029
  });
28852
30030
  exports.MetaKeys = MetaKeys;
30031
+ exports.MobileCanvasGesture = MobileCanvasGesture;
28853
30032
  exports.MobileContextMenu = MobileContextMenu;
28854
30033
  Object.defineProperty(exports, 'MobileDialogService', {
28855
30034
  enumerable: true,
@@ -28858,8 +30037,10 @@ Object.defineProperty(exports, 'MobileDialogService', {
28858
30037
  }
28859
30038
  });
28860
30039
  exports.MobileDrawer = MobileDrawer;
30040
+ exports.MobileFontFamilyDropdown = MobileFontFamilyDropdown;
28861
30041
  exports.MobileKeyboardInsetContext = MobileKeyboardInsetContext;
28862
30042
  exports.MobileMenu = MobileMenu;
30043
+ exports.MobileZoomIndicator = MobileZoomIndicator;
28863
30044
  exports.MockMessageService = MockMessageService;
28864
30045
  exports.NativeTextEditorShortcutBehavior = NativeTextEditorShortcutBehavior;
28865
30046
  exports.ObjectPermissionButton = ObjectPermissionButton;
@@ -28969,6 +30150,7 @@ Object.defineProperty(exports, 'WorkbenchService', {
28969
30150
  });
28970
30151
  exports.ZIndexManager = ZIndexManager;
28971
30152
  exports.ZoomInput = ZoomInput;
30153
+ exports.bindFormatPainterCanvas = bindFormatPainterCanvas;
28972
30154
  Object.defineProperty(exports, 'connectDependencies', {
28973
30155
  enumerable: true,
28974
30156
  get: function () {
@@ -28989,6 +30171,7 @@ exports.getEmojiLocaleData = getEmojiLocaleData;
28989
30171
  exports.getHeaderFooterMenuHiddenObservable = getHeaderFooterMenuHiddenObservable;
28990
30172
  exports.getLocalizedEmojiTitle = getLocalizedEmojiTitle;
28991
30173
  exports.getMenuHiddenObservable = getMenuHiddenObservable;
30174
+ exports.getMobileCanvasPanDelta = getMobileCanvasPanDelta;
28992
30175
  exports.getRandomEmoji = getRandomEmoji;
28993
30176
  exports.handelExcelToJson = handelExcelToJson;
28994
30177
  exports.handelTableToJson = handelTableToJson;
@@ -29032,6 +30215,8 @@ Object.defineProperty(exports, 'useInjector', {
29032
30215
  return _wendellhu_redi_react_bindings.useInjector;
29033
30216
  }
29034
30217
  });
30218
+ exports.useMobileCanvasPanel = useMobileCanvasPanel;
30219
+ exports.useMobileCanvasViewport = useMobileCanvasViewport;
29035
30220
  Object.defineProperty(exports, 'useObservable', {
29036
30221
  enumerable: true,
29037
30222
  get: function () {