@casualoffice/sheets 0.17.0 → 0.19.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 (52) hide show
  1. package/dist/chrome.cjs +3339 -244
  2. package/dist/chrome.cjs.map +1 -1
  3. package/dist/chrome.js +3298 -203
  4. package/dist/chrome.js.map +1 -1
  5. package/dist/embed/embed-runtime.js +203 -157
  6. package/dist/index.cjs +5971 -1572
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.js +5961 -1548
  9. package/dist/index.js.map +1 -1
  10. package/dist/sheets.cjs +4937 -538
  11. package/dist/sheets.cjs.map +1 -1
  12. package/dist/sheets.js +4945 -532
  13. package/dist/sheets.js.map +1 -1
  14. package/package.json +8 -7
  15. package/src/charts/ChartContextMenu.tsx +264 -0
  16. package/src/charts/ChartLayer.tsx +333 -0
  17. package/src/charts/ChartOverlay.tsx +293 -0
  18. package/src/charts/ChartsPanel.tsx +211 -0
  19. package/src/charts/FormatChartDialog.tsx +419 -0
  20. package/src/charts/InsertChartDialog.tsx +478 -0
  21. package/src/charts/build-option.ts +476 -0
  22. package/src/charts/charts-context.tsx +205 -0
  23. package/src/charts/echarts-init.ts +58 -0
  24. package/src/charts/hit-test.ts +130 -0
  25. package/src/charts/insert-chart.ts +106 -0
  26. package/src/charts/naming.ts +38 -0
  27. package/src/charts/render-to-png.ts +117 -0
  28. package/src/charts/resources.ts +108 -0
  29. package/src/charts/types.ts +239 -0
  30. package/src/charts/univer-dom.ts +102 -0
  31. package/src/chrome/CommentsPanel.tsx +427 -0
  32. package/src/chrome/ConditionalFormattingDialog.tsx +534 -0
  33. package/src/chrome/CustomSortDialog.tsx +357 -0
  34. package/src/chrome/DataValidationDialog.tsx +536 -0
  35. package/src/chrome/DeleteCellsDialog.tsx +183 -0
  36. package/src/chrome/GoalSeekDialog.tsx +370 -0
  37. package/src/chrome/HistoryPanel.tsx +319 -0
  38. package/src/chrome/InsertCellsDialog.tsx +185 -0
  39. package/src/chrome/InsertChartDialog.tsx +490 -0
  40. package/src/chrome/InsertFunctionDialog.tsx +493 -0
  41. package/src/chrome/InsertPivotDialog.tsx +488 -0
  42. package/src/chrome/InsertSparklineDialog.tsx +344 -0
  43. package/src/chrome/NameManagerDialog.tsx +378 -0
  44. package/src/chrome/PanelHost.tsx +55 -0
  45. package/src/chrome/PanelRail.tsx +90 -0
  46. package/src/chrome/PasteSpecialDialog.tsx +286 -0
  47. package/src/chrome/PivotFieldsPanel.tsx +1052 -0
  48. package/src/chrome/TablesPanel.tsx +301 -0
  49. package/src/chrome/dialog-context.tsx +24 -0
  50. package/src/chrome/panel-context.tsx +55 -0
  51. package/src/chrome/panel-registry.ts +48 -0
  52. package/src/sheets/CasualSheets.tsx +60 -34
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/chrome/index.ts","../src/chrome/Toolbar.tsx","../src/chrome/Icon.tsx","../src/chrome/fonts.ts","../src/chrome/ColorPicker.tsx","../src/chrome/BordersPicker.tsx","../src/chrome/AutoSumPicker.tsx","../src/chrome/dialog-context.tsx","../src/chrome/FormatCellsDialog.tsx","../src/chrome/Dialog.tsx","../src/chrome/dialog-styles.ts","../src/chrome/FormulaBar.tsx","../src/chrome/NameBox.tsx","../src/chrome/StatusBar.tsx","../src/chrome/MenuBar.tsx","../src/chrome/openExternal.ts","../src/univer/lazy-plugins.ts","../src/chrome/menu-model.ts","../src/chrome/SheetTabs.tsx","../src/chrome/FindReplace.tsx","../src/chrome/ChromeTop.tsx","../src/chrome/ChromeBottom.tsx"],"sourcesContent":["/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Chrome — the Office shell as slot components for `<CasualSheets chrome>`.\n *\n * First slice (SDK_MIGRATION_PIPELINE Phase 1 step 2): a minimal built-in\n * `Toolbar`. The rich shell (FormulaBar, MenuBar, TitleBar, StatusBar) lifts\n * from `apps/web/src/shell/` here in later slices, behind `chrome=\"full\"`.\n */\nexport { Toolbar, type ToolbarProps } from './Toolbar';\nexport { FormulaBar, type FormulaBarProps } from './FormulaBar';\nexport { StatusBar, type StatusBarProps } from './StatusBar';\nexport { Icon, type IconProps } from './Icon';\nexport { ensureChromeFonts } from './fonts';\nexport { ColorPicker, type ColorPickerProps } from './ColorPicker';\nexport { BordersPicker, type BordersPickerProps } from './BordersPicker';\nexport { AutoSumPicker, type AutoSumPickerProps } from './AutoSumPicker';\nexport { MenuBar, type MenuBarProps, type MenuDialogKind } from './MenuBar';\nexport { NameBox, type NameBoxProps } from './NameBox';\nexport { SheetTabs, type SheetTabsProps } from './SheetTabs';\nexport { FindReplace, type FindReplaceProps } from './FindReplace';\n// Dialog foundation: the modal primitive, the dialog host/registry, the\n// extension API, and the built-in reference dialogs.\nexport { Dialog, type DialogProps } from './Dialog';\nexport { FormatCellsDialog } from './FormatCellsDialog';\nexport {\n DialogProvider,\n useDialogs,\n hasBuiltInDialog,\n type DialogKind,\n type DialogController,\n type DialogProviderProps,\n} from './dialog-context';\nexport type {\n ChromeExtensions,\n ToolbarExtension,\n MenuExtension,\n PanelExtension,\n DialogExtension,\n DialogComponentProps,\n PanelComponentProps,\n MenuTarget,\n} from './extensions';\n// Lazy-loaded shells: chrome above (ChromeTop) and below (ChromeBottom) the grid,\n// imported on demand by `<CasualSheets>` via the `@casualoffice/sheets/chrome`\n// subpath so `chrome=\"none\"` consumers don't bundle the chrome JS.\nexport { ChromeTop } from './ChromeTop';\nexport { ChromeBottom } from './ChromeBottom';\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Toolbar — the rich built-in formatting toolbar for `<CasualSheets chrome>`.\n *\n * Drives the editor purely through `CasualSheetsAPI.executeCommand` + the FUniver\n * facade (`api.univer`), with Material Symbols icons + design-system tokens. No\n * app context, no title/logo row (the host frames the editor with its own bar).\n * Commands grouped with dividers, Office-style — mirrors the app shell's\n * `apps/web/src/shell/Toolbar.tsx` + `RibbonControls.tsx` group/order/icons,\n * replicating `home-tab-actions.ts` logic inline against `api` / `api.univer`.\n *\n * Covered (parity with the app's Home tab):\n * history (undo/redo) · clipboard (paste/cut/copy/paste-values) · format\n * painter · font family/size + grow/shrink · bold/italic/underline/strike ·\n * text + fill colour (ColorPicker) · borders (BordersPicker) · horizontal +\n * vertical align · wrap · merge/unmerge · number-format dropdown +\n * currency/percent/decimals · AutoSum (AutoSumPicker) · clear formatting.\n *\n * Reflects the active cell — toggles light up, dropdowns show the current font /\n * number format — via a command-execution subscription.\n *\n * Dialog-only controls (Format Cells, Insert Chart, PivotTable) have no SDK\n * dialog: when the host passes `onDialogRequest` they render and call it so the\n * host can render its own; without it, they are omitted entirely (no fake\n * dialog). Each group/control can also be hidden via the `features` flag map.\n */\n\nimport { useEffect, useState, type CSSProperties } from 'react';\nimport { ICommandService } from '@univerjs/core';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\nimport { ensureChromeFonts } from './fonts';\nimport { ColorPicker } from './ColorPicker';\nimport { BordersPicker } from './BordersPicker';\nimport { AutoSumPicker } from './AutoSumPicker';\nimport { useDialogs } from './dialog-context';\nimport type { ChromeExtensions, ToolbarExtension } from './extensions';\n\ninterface ActiveStyle {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strike: boolean;\n ht: number; // HorizontalAlign of the active cell (0 = unset)\n vt: number; // VerticalAlign of the active cell (0 = unset)\n tb: number; // WrapStrategy of the active cell (0 = unset, 3 = wrap)\n ff: string;\n fs: number;\n nf: string; // number-format pattern ('' = General)\n}\n\nconst NO_STYLE: ActiveStyle = {\n bold: false,\n italic: false,\n underline: false,\n strike: false,\n ht: 0,\n vt: 0,\n tb: 0,\n ff: '',\n fs: 0,\n nf: '',\n};\n\nfunction readActiveStyle(api: CasualSheetsAPI): ActiveStyle {\n const sel = api.getSelection();\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sel || !sheet) return NO_STYLE;\n const range = sheet.getRange(sel.range.startRow, sel.range.startColumn);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const s = (range.getCellStyleData?.() ?? null) as any;\n return {\n bold: s?.bl === 1,\n italic: s?.it === 1,\n underline: s?.ul?.s === 1,\n strike: s?.st?.s === 1,\n ht: typeof s?.ht === 'number' ? s.ht : 0,\n vt: typeof s?.vt === 'number' ? s.vt : 0,\n tb: typeof s?.tb === 'number' ? s.tb : 0,\n ff: typeof s?.ff === 'string' ? s.ff : '',\n fs: typeof s?.fs === 'number' ? s.fs : 0,\n nf: typeof s?.n?.pattern === 'string' ? s.n.pattern : '',\n };\n}\n\nconst FONT_FAMILIES = [\n 'Calibri',\n 'Arial',\n 'Helvetica',\n 'Inter',\n 'Times New Roman',\n 'Georgia',\n 'Verdana',\n 'Courier New',\n 'JetBrains Mono',\n];\nconst FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 48, 72];\n\n/**\n * Number-format presets, mirroring the app's `home-tab-actions`\n * `NUMBER_FORMAT_PATTERNS`. The dropdown applies a pattern via the facade\n * (`FRange.setNumberFormat`, a runtime numfmt-facade extension) so it lands as a\n * normal numfmt mutation — same path the app uses.\n */\nconst NUMBER_FORMAT_PATTERNS = {\n general: '',\n integer: '#,##0',\n number: '#,##0.00',\n currency: '\"$\"#,##0.00',\n accounting: '_(\"$\"* #,##0.00_);_(\"$\"* (#,##0.00);_(\"$\"* \"-\"??_);_(@_)',\n percent: '0.00%',\n date: 'yyyy-mm-dd',\n time: 'hh:mm:ss',\n scientific: '0.00E+00',\n text: '@',\n} as const;\n\ntype NumberFormatKey = keyof typeof NUMBER_FORMAT_PATTERNS;\n\nconst NUMBER_FORMAT_OPTIONS: { value: NumberFormatKey; label: string }[] = [\n { value: 'general', label: 'General' },\n { value: 'integer', label: 'Number (no decimals)' },\n { value: 'number', label: 'Number (2 decimals)' },\n { value: 'currency', label: 'Currency' },\n { value: 'accounting', label: 'Accounting' },\n { value: 'percent', label: 'Percent' },\n { value: 'date', label: 'Date (yyyy-mm-dd)' },\n { value: 'time', label: 'Time (hh:mm:ss)' },\n { value: 'scientific', label: 'Scientific' },\n { value: 'text', label: 'Text' },\n];\n\nfunction detectFormatKey(pattern: string): NumberFormatKey {\n for (const k of Object.keys(NUMBER_FORMAT_PATTERNS) as NumberFormatKey[]) {\n if (NUMBER_FORMAT_PATTERNS[k] === pattern) return k;\n }\n return 'general';\n}\n\ninterface ToolbarAction {\n id: string;\n label: string;\n command: string;\n icon: string;\n params?: object;\n /** Feature key gating this action; defaults to the owning group's key. */\n feature?: string;\n}\n\n/**\n * Each entry is a feature-gated group. The `feature` key lets a host hide the\n * whole group (and per-action `feature` keys gate individual buttons). Order +\n * icons mirror the app shell's Home tab.\n *\n * HorizontalAlign enum (@univerjs/core): LEFT=1, CENTER=2, RIGHT=3.\n * VerticalAlign enum (@univerjs/core): TOP=1, MIDDLE=2, BOTTOM=3.\n * WrapStrategy enum (@univerjs/core): OVERFLOW=1, CLIP=2, WRAP=3.\n *\n * Clipboard command ids: `univer.command.{paste,cut,copy}` (matches\n * `home-tab-actions.ts`). Paste values-only uses the base paste command with a\n * predefined hook `value` (`special-paste-value`), same as the app's\n * `pasteSpecial`.\n */\nconst GROUPS: { feature: string; actions: ToolbarAction[] }[] = [\n {\n feature: 'history',\n actions: [\n { id: 'undo', label: 'Undo (Ctrl+Z)', command: 'univer.command.undo', icon: 'undo' },\n { id: 'redo', label: 'Redo (Ctrl+Y)', command: 'univer.command.redo', icon: 'redo' },\n ],\n },\n {\n feature: 'clipboard',\n actions: [\n {\n id: 'paste',\n label: 'Paste (Ctrl+V)',\n command: 'univer.command.paste',\n icon: 'content_paste',\n },\n { id: 'cut', label: 'Cut (Ctrl+X)', command: 'univer.command.cut', icon: 'content_cut' },\n { id: 'copy', label: 'Copy (Ctrl+C)', command: 'univer.command.copy', icon: 'content_copy' },\n {\n id: 'paste-values',\n label: 'Paste values only',\n command: 'univer.command.paste',\n icon: 'content_paste_go',\n params: { value: 'special-paste-value' },\n },\n ],\n },\n {\n feature: 'format-painter',\n actions: [\n {\n id: 'format-painter',\n label: 'Format Painter',\n command: 'sheet.command.set-once-format-painter',\n icon: 'format_paint',\n },\n ],\n },\n {\n feature: 'font-style',\n actions: [\n {\n id: 'bold',\n label: 'Bold (Ctrl+B)',\n command: 'sheet.command.set-range-bold',\n icon: 'format_bold',\n },\n {\n id: 'italic',\n label: 'Italic (Ctrl+I)',\n command: 'sheet.command.set-range-italic',\n icon: 'format_italic',\n },\n {\n id: 'underline',\n label: 'Underline (Ctrl+U)',\n command: 'sheet.command.set-range-underline',\n icon: 'format_underlined',\n },\n {\n id: 'strikethrough',\n label: 'Strikethrough',\n command: 'sheet.command.set-range-stroke',\n icon: 'format_strikethrough',\n },\n ],\n },\n {\n feature: 'alignment',\n actions: [\n {\n id: 'align-left',\n label: 'Align left',\n command: 'sheet.command.set-horizontal-text-align',\n icon: 'format_align_left',\n params: { value: 1 },\n },\n {\n id: 'align-center',\n label: 'Align center',\n command: 'sheet.command.set-horizontal-text-align',\n icon: 'format_align_center',\n params: { value: 2 },\n },\n {\n id: 'align-right',\n label: 'Align right',\n command: 'sheet.command.set-horizontal-text-align',\n icon: 'format_align_right',\n params: { value: 3 },\n },\n {\n id: 'wrap-text',\n label: 'Wrap text',\n command: 'sheet.command.set-text-wrap',\n icon: 'wrap_text',\n params: { value: 3 },\n },\n ],\n },\n {\n feature: 'alignment',\n actions: [\n {\n id: 'align-top',\n label: 'Align top',\n command: 'sheet.command.set-vertical-text-align',\n icon: 'vertical_align_top',\n params: { value: 1 },\n },\n {\n id: 'align-middle',\n label: 'Align middle',\n command: 'sheet.command.set-vertical-text-align',\n icon: 'vertical_align_center',\n params: { value: 2 },\n },\n {\n id: 'align-bottom',\n label: 'Align bottom',\n command: 'sheet.command.set-vertical-text-align',\n icon: 'vertical_align_bottom',\n params: { value: 3 },\n },\n ],\n },\n {\n feature: 'merge',\n actions: [\n {\n id: 'merge',\n label: 'Merge cells',\n command: 'sheet.command.add-worksheet-merge-all',\n icon: 'cell_merge',\n },\n {\n id: 'unmerge',\n label: 'Unmerge cells',\n command: 'sheet.command.remove-worksheet-merge',\n icon: 'splitscreen_vertical_add',\n },\n ],\n },\n {\n feature: 'number',\n actions: [\n {\n id: 'currency',\n label: 'Currency format',\n command: 'sheet.command.numfmt.set.currency',\n icon: 'attach_money',\n },\n {\n id: 'percent',\n label: 'Percent format',\n command: 'sheet.command.numfmt.set.percent',\n icon: 'percent',\n },\n {\n id: 'decimal-increase',\n label: 'Increase decimals',\n command: 'sheet.command.numfmt.add.decimal.command',\n icon: 'decimal_increase',\n },\n {\n id: 'decimal-decrease',\n label: 'Decrease decimals',\n command: 'sheet.command.numfmt.subtract.decimal.command',\n icon: 'decimal_decrease',\n },\n ],\n },\n {\n feature: 'clear-format',\n actions: [\n {\n id: 'clear-format',\n label: 'Clear formatting',\n command: 'sheet.command.clear-selection-format',\n icon: 'format_clear',\n },\n ],\n },\n];\n\nconst BAR_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n padding: '4px 8px',\n borderBottom: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-bg, #eef1f5)',\n flex: '0 0 auto',\n userSelect: 'none',\n flexWrap: 'wrap',\n};\n\nconst BTN_STYLE: CSSProperties = {\n width: 30,\n height: 30,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n padding: 0,\n};\n\nconst DIVIDER_STYLE: CSSProperties = {\n width: 1,\n height: 18,\n margin: '0 4px',\n background: 'var(--cs-chrome-border, #cdd3db)',\n flex: '0 0 auto',\n};\n\nconst SELECT_STYLE: CSSProperties = {\n height: 26,\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n padding: '0 4px',\n cursor: 'pointer',\n};\n\nexport interface ToolbarProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n /**\n * Per-control / per-group feature flags. A key set to `false` hides that\n * control or group; omitted keys default to enabled. Keys:\n * history · clipboard · format-painter · font · font-style · color ·\n * borders · alignment · merge · number · autosum · clear-format ·\n * format-cells · insert-chart · pivot-table\n */\n features?: Record<string, boolean>;\n /** Host chrome extensions — only `extensions.toolbar` is read here. */\n extensions?: ChromeExtensions;\n}\n\n/** A feature is on unless explicitly set to `false`. */\nfunction enabled(features: Record<string, boolean> | undefined, key: string): boolean {\n return features?.[key] !== false;\n}\n\n// Which actions reflect an active state, keyed off the active cell's style.\nfunction isActive(id: string, s: ActiveStyle): boolean {\n switch (id) {\n case 'bold':\n return s.bold;\n case 'italic':\n return s.italic;\n case 'underline':\n return s.underline;\n case 'strikethrough':\n return s.strike;\n case 'align-left':\n return s.ht === 1;\n case 'align-center':\n return s.ht === 2;\n case 'align-right':\n return s.ht === 3;\n case 'align-top':\n return s.vt === 1;\n case 'align-middle':\n return s.vt === 2;\n case 'align-bottom':\n return s.vt === 3;\n case 'wrap-text':\n return s.tb === 3;\n default:\n return false;\n }\n}\n\nexport function Toolbar({ api, features, extensions }: ToolbarProps) {\n const dialogs = useDialogs();\n const [active, setActive] = useState<ActiveStyle>(NO_STYLE);\n\n useEffect(() => {\n ensureChromeFonts();\n }, []);\n\n // Reflect the active cell: subscribe to command activity (covers selection\n // moves + style mutations) and re-read the style.\n useEffect(() => {\n if (!api) return;\n const refresh = () => setActive(readActiveStyle(api));\n refresh();\n const injector = (api.univer as unknown as { _injector?: { get(t: unknown): unknown } })\n ._injector;\n const cmd = injector?.get(ICommandService) as\n | { onCommandExecuted: (cb: () => void) => { dispose: () => void } }\n | undefined;\n const sub = cmd?.onCommandExecuted(() => refresh());\n return () => sub?.dispose();\n }, [api]);\n\n const dispatch = (command: string, params?: object) => void api?.executeCommand(command, params);\n\n /**\n * Apply a font size via the dedicated command (matches the app's\n * `set-range-fontsize`). Used by the size dropdown + grow/shrink.\n */\n const applyFontSize = (size: number) => {\n if (!Number.isFinite(size) || size <= 0) return;\n dispatch('sheet.command.set-range-fontsize', { value: size });\n };\n\n /**\n * Grow / shrink the active cell's font size by `delta`, mirroring the app's\n * `adjustFontSize` (read current off the active cell, fall back to 11, clamp\n * to [6, 72]). Reads the size we already track in `active`.\n */\n const adjustFontSize = (delta: number) => {\n const current = active.fs && active.fs > 0 ? active.fs : 11;\n const next = Math.max(6, Math.min(72, current + delta));\n if (next === current) return;\n applyFontSize(next);\n };\n\n /**\n * Apply a number-format pattern via the FUniver facade — `FRange.setNumberFormat`\n * is a runtime numfmt-facade extension (added via `FUniver.extend()`), so a\n * runtime cast is the cleanest way to reach it. Same approach as the app's\n * `home-tab-actions.setNumberFormat`.\n */\n const applyNumberFormat = (pattern: string) => {\n const sheet = api?.univer.getActiveWorkbook()?.getActiveSheet();\n const range = (sheet as unknown as { getActiveRange?: () => unknown })?.getActiveRange?.() as\n | { setNumberFormat?: (p: string) => unknown }\n | undefined;\n range?.setNumberFormat?.(pattern);\n };\n\n // Reflect current font in the dropdowns; surface a non-listed value too.\n const familyValue = active.ff || 'Calibri';\n const familyOptions =\n active.ff && !FONT_FAMILIES.includes(active.ff) ? [active.ff, ...FONT_FAMILIES] : FONT_FAMILIES;\n const sizeValue = active.fs || 11;\n const sizeOptions =\n active.fs && !FONT_SIZES.includes(active.fs) ? [active.fs, ...FONT_SIZES] : FONT_SIZES;\n const numberFormatValue = detectFormatKey(active.nf);\n\n const renderActionButton = (a: ToolbarAction) => {\n const on = isActive(a.id, active);\n const baseBg = on ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent';\n return (\n <button\n key={a.id}\n type=\"button\"\n title={a.label}\n aria-label={a.label}\n aria-pressed={on}\n data-action={a.id}\n data-testid={`cs-${a.id}`}\n data-active={on ? 'true' : undefined}\n disabled={!api}\n style={{\n ...BTN_STYLE,\n background: baseBg,\n color: on ? 'var(--cs-chrome-active-fg, #0e7490)' : BTN_STYLE.color,\n }}\n // mousedown (not click) so the grid's selection isn't lost first.\n onMouseDown={(e) => {\n e.preventDefault();\n dispatch(a.command, a.params);\n }}\n onMouseEnter={(e) => {\n if (!on) e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = baseBg;\n }}\n >\n <Icon name={a.icon} size={20} />\n </button>\n );\n };\n\n // A plain (non-command) icon button — used for grow/shrink + dialog requests.\n const renderIconButton = (\n id: string,\n label: string,\n icon: string,\n onPress: () => void,\n testid: string,\n ) => (\n <button\n key={id}\n type=\"button\"\n title={label}\n aria-label={label}\n data-action={id}\n data-testid={testid}\n disabled={!api}\n style={BTN_STYLE}\n onMouseDown={(e) => {\n e.preventDefault();\n onPress();\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n >\n <Icon name={icon} size={20} />\n </button>\n );\n\n // Render the static command groups, skipping any whose feature is off and any\n // group left empty after per-action filtering. A leading divider separates a\n // group from whatever rendered before it.\n let firstGroupRendered = false;\n const groupNodes = GROUPS.map((group, gi) => {\n if (!enabled(features, group.feature)) return null;\n const visible = group.actions.filter((a) => enabled(features, a.feature ?? group.feature));\n if (visible.length === 0) return null;\n const showDivider = firstGroupRendered;\n firstGroupRendered = true;\n return (\n <span key={gi} style={{ display: 'inline-flex', alignItems: 'center' }}>\n {showDivider && <span style={DIVIDER_STYLE} aria-hidden />}\n {visible.map(renderActionButton)}\n </span>\n );\n });\n\n const showFont = enabled(features, 'font');\n const showColor = enabled(features, 'color');\n const showBorders = enabled(features, 'borders');\n const showAutoSum = enabled(features, 'autosum');\n const showNumberDropdown = enabled(features, 'number');\n\n // Dialog-backed controls: render when the chrome can open them — Format Cells\n // is a built-in (always available); Insert Chart / PivotTable open only when a\n // host registered/handles them.\n const showFormatCells = enabled(features, 'format-cells') && dialogs.canOpen('format-cells');\n const showInsertChart = enabled(features, 'insert-chart') && dialogs.canOpen('insert-chart');\n const showPivotTable = enabled(features, 'pivot-table') && dialogs.canOpen('insert-pivot');\n const showDialogGroup = showFormatCells || showInsertChart || showPivotTable;\n\n // Host toolbar extensions — appended after the built-in groups.\n const toolbarExt = (extensions?.toolbar ?? []).filter(\n (e) => !e.isVisible || (api ? e.isVisible(api) : false),\n );\n const runExt = (e: ToolbarExtension) => {\n if (!api) return;\n if (e.command) void api.executeCommand(e.command, e.commandParams);\n else e.onClick?.(api);\n };\n\n return (\n <div style={BAR_STYLE} data-testid=\"casual-sheets-toolbar\" role=\"toolbar\" aria-label=\"Editor\">\n {showFont && (\n <>\n <select\n aria-label=\"Font family\"\n data-testid=\"cs-font-family\"\n style={{ ...SELECT_STYLE, width: 130 }}\n value={familyValue}\n disabled={!api}\n onChange={(e) =>\n dispatch('sheet.command.set-range-font-family', { value: e.target.value })\n }\n >\n {familyOptions.map((f) => (\n <option key={f} value={f}>\n {f}\n </option>\n ))}\n </select>\n <select\n aria-label=\"Font size\"\n data-testid=\"cs-font-size\"\n style={{ ...SELECT_STYLE, width: 56, marginLeft: 4 }}\n value={sizeValue}\n disabled={!api}\n onChange={(e) => applyFontSize(Number(e.target.value))}\n >\n {sizeOptions.map((s) => (\n <option key={s} value={s}>\n {s}\n </option>\n ))}\n </select>\n {renderIconButton(\n 'font-size-up',\n 'Increase font size',\n 'text_increase',\n () => adjustFontSize(+1),\n 'cs-font-size-up',\n )}\n {renderIconButton(\n 'font-size-down',\n 'Decrease font size',\n 'text_decrease',\n () => adjustFontSize(-1),\n 'cs-font-size-down',\n )}\n <span style={DIVIDER_STYLE} aria-hidden />\n </>\n )}\n\n {groupNodes}\n\n {(showColor || showBorders) && <span style={DIVIDER_STYLE} aria-hidden />}\n {showColor && <ColorPicker api={api} />}\n {showBorders && <BordersPicker api={api} />}\n\n {showNumberDropdown && (\n <>\n <span style={DIVIDER_STYLE} aria-hidden />\n <select\n aria-label=\"Number format\"\n data-testid=\"cs-number-format\"\n style={{ ...SELECT_STYLE, width: 124 }}\n value={numberFormatValue}\n disabled={!api}\n onChange={(e) =>\n applyNumberFormat(NUMBER_FORMAT_PATTERNS[e.target.value as NumberFormatKey])\n }\n >\n {NUMBER_FORMAT_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </>\n )}\n\n {showAutoSum && (\n <>\n <span style={DIVIDER_STYLE} aria-hidden />\n <AutoSumPicker api={api} />\n </>\n )}\n\n {showDialogGroup && (\n <>\n <span style={DIVIDER_STYLE} aria-hidden />\n {showFormatCells &&\n renderIconButton(\n 'format-cells',\n 'Format Cells…',\n 'format_shapes',\n () => dialogs.openDialog('format-cells'),\n 'cs-format-cells',\n )}\n {showInsertChart &&\n renderIconButton(\n 'insert-chart',\n 'Insert chart',\n 'bar_chart',\n () => dialogs.openDialog('insert-chart'),\n 'cs-insert-chart',\n )}\n {showPivotTable &&\n renderIconButton(\n 'pivot-table',\n 'Insert PivotTable',\n 'pivot_table_chart',\n () => dialogs.openDialog('insert-pivot'),\n 'cs-pivot-table',\n )}\n </>\n )}\n\n {toolbarExt.length > 0 && (\n <>\n <span style={DIVIDER_STYLE} aria-hidden />\n {toolbarExt.map((e) =>\n renderIconButton(e.id, e.label, e.icon, () => runExt(e), `cs-ext-${e.id}`),\n )}\n </>\n )}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Icon — a Material Symbols Outlined glyph for the chrome.\n *\n * Names are Material Symbols ids (https://fonts.google.com/icons), e.g.\n * `format_bold`. Requires the Material Symbols font (loaded via\n * `ensureChromeFonts`); if it isn't present the ligature text shows instead,\n * which is harmless. Icon-only buttons must carry their own `aria-label`.\n */\n\nimport type { CSSProperties } from 'react';\n\nexport interface IconProps {\n name: string;\n size?: number;\n style?: CSSProperties;\n}\n\nexport function Icon({ name, size = 20, style }: IconProps) {\n return (\n <span\n className=\"material-symbols-outlined\"\n aria-hidden\n style={{\n fontFamily: \"'Material Symbols Outlined'\",\n fontWeight: 'normal',\n fontStyle: 'normal',\n fontSize: size,\n lineHeight: 1,\n letterSpacing: 'normal',\n textTransform: 'none',\n display: 'inline-block',\n whiteSpace: 'nowrap',\n wordWrap: 'normal',\n direction: 'ltr',\n // Hint the variable-font axes so weight/optical-size are consistent.\n fontVariationSettings: \"'opsz' 20, 'wght' 400, 'FILL' 0, 'GRAD' 0\",\n ...style,\n }}\n >\n {name}\n </span>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Ensures the chrome's webfonts (Inter for UI, Material Symbols Outlined for\n * icons) are loaded. The design system standardises on these; the rich\n * `chrome=\"full\"` toolbar/menus render Material Symbols ligatures.\n *\n * Idempotent + safe to call repeatedly: it no-ops if the links already exist\n * (e.g. a host that already loads them, like our own app). Injected lazily only\n * when chrome is actually shown, so bare-grid SDK consumers pull nothing.\n *\n * Hosts with a strict CSP (no fonts.googleapis.com) can pre-load the fonts\n * themselves or self-host them; this is best-effort, not required for the editor\n * to function (icons fall back to the ligature text).\n */\n\nconst LINKS: Array<{ id: string; href: string }> = [\n {\n id: 'cs-font-inter',\n href: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap',\n },\n {\n id: 'cs-font-material-symbols',\n href: 'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,300..700,0..1,-50..200&display=block',\n },\n];\n\nlet done = false;\n\nexport function ensureChromeFonts(): void {\n if (done || typeof document === 'undefined') return;\n done = true;\n const head = document.head;\n for (const { id, href } of LINKS) {\n if (document.getElementById(id)) continue;\n // Skip if the host already loaded the same family by any <link>.\n // Match on the `family=<name>` segment, NOT the bare `/css2` path — both\n // Google Fonts URLs share `/css2`, so splitting on `?` made the second\n // family (Material Symbols) collide with the first (Inter) and never get\n // injected, leaving `chrome=\"full\"` icons as raw ligature text.\n const familyKey = href.match(/family=[^:&]+/)?.[0] ?? href.split('?')[0];\n if (document.querySelector(`link[href*=\"${familyKey}\"]`)) continue;\n const link = document.createElement('link');\n link.id = id;\n link.rel = 'stylesheet';\n link.href = href;\n head.appendChild(link);\n }\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * ColorPicker — text-colour + fill-colour swatch pickers for `<CasualSheets chrome>`.\n *\n * Two icon buttons (text colour, fill colour). Clicking one toggles a swatch\n * popover; picking a swatch dispatches the matching Univer command on the active\n * selection and closes the popover. A \"None\" entry resets the colour.\n *\n * Drives the editor purely through `CasualSheetsAPI.executeCommand`. Commands:\n * text colour : `sheet.command.set-range-text-color` { value: '#rrggbb' | null }\n * fill colour : `sheet.command.set-background-color` { value: '#rrggbb' }\n * fill reset : `sheet.command.reset-background-color` (no params)\n * (`set-background-color` rejects a null value, so reset uses its own command.)\n */\n\nimport { useEffect, useRef, useState, type CSSProperties } from 'react';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\n\ntype Kind = 'text' | 'fill';\n\n// A tasteful 14-swatch palette: neutrals + a spread of hues, teal = brand.\nconst SWATCHES: { hex: string; label: string }[] = [\n { hex: '#000000', label: 'Black' },\n { hex: '#5f6368', label: 'Dark gray' },\n { hex: '#9aa0a6', label: 'Gray' },\n { hex: '#d9dce0', label: 'Light gray' },\n { hex: '#ffffff', label: 'White' },\n { hex: '#d13438', label: 'Red' },\n { hex: '#e8710a', label: 'Orange' },\n { hex: '#f2c811', label: 'Yellow' },\n { hex: '#107c10', label: 'Green' },\n { hex: '#0e7490', label: 'Teal' },\n { hex: '#1a73e8', label: 'Blue' },\n { hex: '#5b2a86', label: 'Purple' },\n { hex: '#c2185b', label: 'Magenta' },\n { hex: '#795548', label: 'Brown' },\n];\n\nconst ROW_STYLE: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n position: 'relative',\n};\n\nconst BTN_STYLE: CSSProperties = {\n width: 30,\n height: 30,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n padding: 0,\n};\n\nconst POPOVER_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: 4,\n zIndex: 1000,\n padding: 8,\n borderRadius: 8,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.18)',\n};\n\nconst GRID_STYLE: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: 'repeat(7, 22px)',\n gap: 6,\n};\n\nconst SWATCH_STYLE: CSSProperties = {\n width: 22,\n height: 22,\n borderRadius: 4,\n border: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.18))',\n cursor: 'pointer',\n padding: 0,\n};\n\nconst NONE_STYLE: CSSProperties = {\n marginTop: 8,\n width: '100%',\n height: 26,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 4,\n border: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.18))',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 12,\n cursor: 'pointer',\n};\n\nexport interface ColorPickerProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function ColorPicker({ api }: ColorPickerProps) {\n const [open, setOpen] = useState<Kind | null>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Close on Escape and on any pointerdown outside the picker root.\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: PointerEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(null);\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(null);\n };\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n const pick = (kind: Kind, hex: string | null) => {\n if (api) {\n if (kind === 'text') {\n void api.executeCommand('sheet.command.set-range-text-color', { value: hex });\n } else if (hex === null) {\n void api.executeCommand('sheet.command.reset-background-color');\n } else {\n void api.executeCommand('sheet.command.set-background-color', { value: hex });\n }\n }\n setOpen(null);\n };\n\n const toggle = (kind: Kind) => setOpen((cur) => (cur === kind ? null : kind));\n\n const renderButton = (kind: Kind, icon: string, label: string, testid: string) => {\n const on = open === kind;\n const baseBg = on ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent';\n return (\n <button\n type=\"button\"\n title={label}\n aria-label={label}\n aria-haspopup=\"true\"\n aria-expanded={on}\n data-testid={testid}\n style={{\n ...BTN_STYLE,\n background: baseBg,\n color: on ? 'var(--cs-chrome-active-fg, #0e7490)' : BTN_STYLE.color,\n }}\n // mousedown (not click) so the grid's selection isn't lost first.\n onMouseDown={(e) => {\n e.preventDefault();\n toggle(kind);\n }}\n onMouseEnter={(e) => {\n if (!on) e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = baseBg;\n }}\n >\n <Icon name={icon} size={20} />\n </button>\n );\n };\n\n const renderPopover = (kind: Kind) => (\n <div style={POPOVER_STYLE} data-testid=\"cs-color-popover\" role=\"menu\">\n <div style={GRID_STYLE}>\n {SWATCHES.map((s) => (\n <button\n key={s.hex}\n type=\"button\"\n role=\"menuitem\"\n title={s.label}\n aria-label={s.label}\n data-color={s.hex}\n style={{ ...SWATCH_STYLE, background: s.hex }}\n onMouseDown={(e) => {\n e.preventDefault();\n pick(kind, s.hex);\n }}\n />\n ))}\n </div>\n <button\n type=\"button\"\n role=\"menuitem\"\n data-color=\"none\"\n style={NONE_STYLE}\n onMouseDown={(e) => {\n e.preventDefault();\n pick(kind, null);\n }}\n >\n <Icon name=\"format_color_reset\" size={16} />\n None\n </button>\n </div>\n );\n\n return (\n <div ref={rootRef} style={ROW_STYLE} data-testid=\"cs-color-picker\">\n {renderButton('text', 'format_color_text', 'Text color', 'cs-color-text')}\n {renderButton('fill', 'format_color_fill', 'Fill color', 'cs-color-fill')}\n {open && renderPopover(open)}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * BordersPicker — border-position dropdown for `<CasualSheets chrome>`.\n *\n * One toolbar button that opens a popover of Excel-style border options (All,\n * Outside, Inside, Top, Bottom, Left, Right, None). Picking one dispatches\n * `sheet.command.set-border-position` with the matching `BorderType` against the\n * active selection, using Univer's current border style/colour (thin black by\n * default). Drives the editor purely through `CasualSheetsAPI.executeCommand`.\n */\n\nimport { useEffect, useRef, useState, type CSSProperties } from 'react';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\n\n// BorderType is a string enum in @univerjs/core ('all' | 'outside' | …); use the\n// literal values directly so this component needs no Univer value import.\nconst OPTIONS: { value: string; icon: string; label: string }[] = [\n { value: 'all', icon: 'border_all', label: 'All borders' },\n { value: 'outside', icon: 'border_outer', label: 'Outside borders' },\n { value: 'inside', icon: 'border_inner', label: 'Inside borders' },\n { value: 'top', icon: 'border_top', label: 'Top border' },\n { value: 'bottom', icon: 'border_bottom', label: 'Bottom border' },\n { value: 'left', icon: 'border_left', label: 'Left border' },\n { value: 'right', icon: 'border_right', label: 'Right border' },\n { value: 'none', icon: 'border_clear', label: 'No border' },\n];\n\nconst ROW_STYLE: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n position: 'relative',\n};\n\nconst BTN_STYLE: CSSProperties = {\n width: 30,\n height: 30,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n padding: 0,\n};\n\nconst POPOVER_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: 4,\n zIndex: 1000,\n padding: 4,\n minWidth: 168,\n borderRadius: 8,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.18)',\n};\n\nconst ITEM_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n width: '100%',\n height: 28,\n padding: '0 8px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n textAlign: 'left',\n};\n\nexport interface BordersPickerProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function BordersPicker({ api }: BordersPickerProps) {\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Close on Escape and on any pointerdown outside the picker root.\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: PointerEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n const pick = (value: string) => {\n void api?.executeCommand('sheet.command.set-border-position', { value });\n setOpen(false);\n };\n\n const on = open;\n const baseBg = on ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent';\n\n return (\n <div ref={rootRef} style={ROW_STYLE} data-testid=\"cs-borders\">\n <button\n type=\"button\"\n title=\"Borders\"\n aria-label=\"Borders\"\n aria-haspopup=\"true\"\n aria-expanded={on}\n data-testid=\"cs-borders-button\"\n disabled={!api}\n style={{\n ...BTN_STYLE,\n background: baseBg,\n color: on ? 'var(--cs-chrome-active-fg, #0e7490)' : BTN_STYLE.color,\n }}\n // mousedown (not click) so the grid's selection isn't lost first.\n onMouseDown={(e) => {\n e.preventDefault();\n setOpen((v) => !v);\n }}\n onMouseEnter={(e) => {\n if (!on) e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = baseBg;\n }}\n >\n <Icon name=\"border_all\" size={20} />\n </button>\n {open && (\n <div style={POPOVER_STYLE} data-testid=\"cs-borders-popover\" role=\"menu\">\n {OPTIONS.map((o) => (\n <button\n key={o.value}\n type=\"button\"\n role=\"menuitem\"\n data-border={o.value}\n data-testid={`cs-border-${o.value}`}\n style={ITEM_STYLE}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n pick(o.value);\n }}\n >\n <Icon name={o.icon} size={18} />\n {o.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * AutoSumPicker — Excel-style AutoSum dropdown for `<CasualSheets chrome>`.\n *\n * One toolbar button (Σ) opening Sum / Average / Count / Max / Min. Picking one\n * inserts `=FN(<selection>)` one row below a multi-cell selection (and activates\n * that cell), or `=FN()` into a single active cell so the user can type the\n * range. Pure facade — no command, no Univer UI dependency — so it works in the\n * SDK's embedded mount.\n */\n\nimport { useEffect, useRef, useState, type CSSProperties } from 'react';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\n\nconst FUNCS: { fn: string; label: string }[] = [\n { fn: 'SUM', label: 'Sum' },\n { fn: 'AVERAGE', label: 'Average' },\n { fn: 'COUNT', label: 'Count numbers' },\n { fn: 'MAX', label: 'Max' },\n { fn: 'MIN', label: 'Min' },\n];\n\nconst ROW_STYLE: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n position: 'relative',\n};\n\nconst BTN_STYLE: CSSProperties = {\n width: 30,\n height: 30,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n padding: 0,\n};\n\nconst POPOVER_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: 4,\n zIndex: 1000,\n padding: 4,\n minWidth: 160,\n borderRadius: 8,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.18)',\n};\n\nconst ITEM_STYLE: CSSProperties = {\n display: 'block',\n width: '100%',\n textAlign: 'left',\n height: 28,\n padding: '0 10px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyRange = any;\n\nexport interface AutoSumPickerProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function AutoSumPicker({ api }: AutoSumPickerProps) {\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: PointerEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n const apply = (fn: string) => {\n setOpen(false);\n const sheet = api?.univer.getActiveWorkbook()?.getActiveSheet();\n const range = (sheet as unknown as { getActiveRange?: () => AnyRange })?.getActiveRange?.();\n if (!sheet || !range) return;\n const multi = range.getWidth() * range.getHeight() > 1;\n if (multi) {\n // Drop the formula one row below the selection, same column as its start.\n const target = sheet.getRange(range.getRow() + range.getHeight(), range.getColumn());\n target.setValue({ f: `=${fn}(${range.getA1Notation()})` });\n (target as AnyRange).activate?.();\n } else {\n // Single cell — leave the cursor inside the parens for the user to fill.\n sheet.getRange(range.getRow(), range.getColumn()).setValue({ f: `=${fn}()` });\n }\n };\n\n const on = open;\n const baseBg = on ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent';\n\n return (\n <div ref={rootRef} style={ROW_STYLE} data-testid=\"cs-autosum\">\n <button\n type=\"button\"\n title=\"AutoSum\"\n aria-label=\"AutoSum\"\n aria-haspopup=\"true\"\n aria-expanded={on}\n data-testid=\"cs-autosum-button\"\n disabled={!api}\n style={{\n ...BTN_STYLE,\n background: baseBg,\n color: on ? 'var(--cs-chrome-active-fg, #0e7490)' : BTN_STYLE.color,\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n setOpen((v) => !v);\n }}\n onMouseEnter={(e) => {\n if (!on) e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = baseBg;\n }}\n >\n <Icon name=\"functions\" size={20} />\n </button>\n {open && (\n <div style={POPOVER_STYLE} data-testid=\"cs-autosum-popover\" role=\"menu\">\n {FUNCS.map((f) => (\n <button\n key={f.fn}\n type=\"button\"\n role=\"menuitem\"\n data-fn={f.fn}\n data-testid={`cs-autosum-${f.fn}`}\n style={ITEM_STYLE}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n apply(f.fn);\n }}\n >\n {f.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Dialog host + registry for `<CasualSheets chrome>`.\n *\n * The model: a chrome control (menu item, toolbar button) calls\n * `openDialog(kind, context)`. By default that opens the SDK's BUILT-IN dialog\n * for that kind (rendered by `<DialogHost>`). A host can OVERRIDE any kind — or\n * add novel kinds — via `extensions.dialogs`, and can additionally route\n * specific kinds to its legacy `onDialogRequest` callback (back-compat).\n *\n * Resolution order in `openDialog(kind)`:\n * 1. host registered `extensions.dialogs[kind]` → render host dialog\n * 2. host opted `kind` to `onDialogRequest` (no built-in, or host wants it)\n * → emit onDialogRequest\n * 3. SDK has a built-in dialog for `kind` → render built-in\n * 4. else, if `onDialogRequest` provided → emit onDialogRequest\n * 5. else → no-op\n *\n * `onDialogRequest` stays fully supported: if a host passes it and DOESN'T\n * register a built-in override, kinds the SDK has no built-in for fall through\n * to it (3→4), matching the previous behaviour.\n */\n\nimport { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from 'react';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport type { ChromeExtensions, DialogComponentProps } from './extensions';\nimport { FormatCellsDialog } from './FormatCellsDialog';\n\n/**\n * All dialog kinds the chrome knows about. Mirrors `MenuDialogKind` in MenuBar\n * (kept in sync) and is the key space for `extensions.dialogs`. Kinds with a\n * built-in renderer are listed in `BUILT_IN_DIALOGS`; the rest need a host\n * override or `onDialogRequest` to do anything.\n */\nexport type DialogKind =\n | 'format-cells'\n | 'find-replace'\n | 'insert-cells'\n | 'delete-cells'\n | 'paste-special'\n | 'insert-chart'\n | 'insert-pivot'\n | 'insert-sparkline'\n | 'insert-function'\n | 'name-manager'\n | 'goal-seek'\n | 'data-validation'\n | 'conditional-formatting'\n | 'custom-sort'\n | 'properties'\n | 'about'\n | 'keyboard-shortcuts';\n\n/**\n * SDK built-in dialog components, keyed by kind. Anything NOT here has no\n * built-in UI and falls through to a host override / onDialogRequest.\n *\n * `find-replace` is intentionally NOT here — it's the self-managing\n * `<FindReplace>` panel (Ctrl+F/H), wired separately in ChromeTop and opened\n * imperatively; `DialogHost` only owns the modal-style built-ins.\n */\nconst BUILT_IN_DIALOGS: Partial<Record<DialogKind, React.ComponentType<DialogComponentProps>>> = {\n 'format-cells': FormatCellsDialog,\n};\n\n/** Kinds the chrome can open without a host (built-in modal or self-managing). */\nexport function hasBuiltInDialog(kind: DialogKind): boolean {\n return kind in BUILT_IN_DIALOGS || kind === 'find-replace';\n}\n\ninterface ActiveDialog {\n kind: DialogKind;\n context?: unknown;\n}\n\nexport interface DialogController {\n /** Open a dialog (built-in by default; host override / onDialogRequest wins per rules). */\n openDialog: (kind: DialogKind, context?: unknown) => void;\n /** Close the currently-open built-in/override dialog. */\n closeDialog: () => void;\n /** True when the chrome can open `kind` itself OR a host registered/handles it. */\n canOpen: (kind: DialogKind) => boolean;\n}\n\nconst DialogContext = createContext<DialogController | null>(null);\n\n/** Access the dialog controller from any chrome component under the provider. */\nexport function useDialogs(): DialogController {\n const ctx = useContext(DialogContext);\n if (!ctx) {\n // Defensive — should never happen inside the chrome tree. A no-op keeps a\n // mis-mounted control from throwing.\n return {\n openDialog: () => {},\n closeDialog: () => {},\n canOpen: () => false,\n };\n }\n return ctx;\n}\n\nexport interface DialogProviderProps {\n api: CasualSheetsAPI | null;\n extensions?: ChromeExtensions;\n /**\n * Legacy host hook. When set, kinds the host opts to handle (no built-in, or\n * explicitly listed in `hostOwnedDialogs`) emit through it instead of\n * rendering a built-in. Back-compat: still fires for non-built-in kinds.\n */\n onDialogRequest?: (kind: DialogKind, context?: unknown) => void;\n /**\n * Kinds the host wants to own via `onDialogRequest` even though the SDK has a\n * built-in. Lets a host keep the SDK chrome but its own Format Cells, say,\n * without registering a React component.\n */\n hostOwnedDialogs?: DialogKind[];\n /**\n * Bridge for the self-managing find-replace panel. `find-replace` isn't a\n * modal `<DialogHost>` renders — it's the `<FindReplace>` panel — so the\n * provider delegates opening it to the chrome (which owns the panel's open\n * signal) instead of setting `active`.\n */\n onOpenFindReplace?: (replaceMode: boolean) => void;\n children: ReactNode;\n}\n\n/**\n * Provides `openDialog`/`closeDialog` to the chrome tree and renders the active\n * built-in/override dialog via `<DialogHost>` (mounted internally).\n */\nexport function DialogProvider({\n api,\n extensions,\n onDialogRequest,\n hostOwnedDialogs,\n onOpenFindReplace,\n children,\n}: DialogProviderProps) {\n const [active, setActive] = useState<ActiveDialog | null>(null);\n\n const overrides = extensions?.dialogs;\n const hostOwned = useMemo(() => new Set(hostOwnedDialogs ?? []), [hostOwnedDialogs]);\n\n const openDialog = useCallback(\n (kind: DialogKind, context?: unknown) => {\n // 1. Host-registered React override → render it.\n if (overrides?.[kind]) {\n setActive({ kind, context });\n return;\n }\n // 2. Host explicitly owns this kind via onDialogRequest.\n if (onDialogRequest && hostOwned.has(kind)) {\n onDialogRequest(kind, context);\n return;\n }\n // find-replace is the self-managing panel, not a DialogHost modal — bridge\n // to the chrome's open signal.\n if (kind === 'find-replace') {\n onOpenFindReplace?.(false);\n return;\n }\n // 3. SDK built-in.\n if (hasBuiltInDialog(kind)) {\n setActive({ kind, context });\n return;\n }\n // 4. Fall through to onDialogRequest for kinds with no built-in.\n if (onDialogRequest) {\n onDialogRequest(kind, context);\n return;\n }\n // 5. No way to fulfil — no-op (the control shouldn't have rendered).\n },\n [overrides, onDialogRequest, hostOwned, onOpenFindReplace],\n );\n\n const closeDialog = useCallback(() => setActive(null), []);\n\n const canOpen = useCallback(\n (kind: DialogKind) =>\n !!overrides?.[kind] || hasBuiltInDialog(kind) || !!onDialogRequest || hostOwned.has(kind),\n [overrides, onDialogRequest, hostOwned],\n );\n\n const controllerCanOpen = useCallback(\n (kind: DialogKind) =>\n kind === 'find-replace' ? !!onOpenFindReplace || canOpen(kind) : canOpen(kind),\n [canOpen, onOpenFindReplace],\n );\n\n const controller = useMemo<DialogController>(\n () => ({ openDialog, closeDialog, canOpen: controllerCanOpen }),\n [openDialog, closeDialog, controllerCanOpen],\n );\n\n return (\n <DialogContext.Provider value={controller}>\n {children}\n <DialogHost api={api} active={active} overrides={overrides} onClose={closeDialog} />\n </DialogContext.Provider>\n );\n}\n\ninterface DialogHostProps {\n api: CasualSheetsAPI | null;\n active: ActiveDialog | null;\n overrides?: ChromeExtensions['dialogs'];\n onClose: () => void;\n}\n\n/**\n * Renders the currently-active modal dialog — a host override if registered for\n * the kind, otherwise the SDK built-in. `find-replace` is excluded (the\n * self-managing FindReplace panel owns it). Renders nothing when no dialog is\n * open or the API isn't ready.\n */\nfunction DialogHost({ api, active, overrides, onClose }: DialogHostProps) {\n if (!active || !api) return null;\n if (active.kind === 'find-replace') return null;\n const Component = overrides?.[active.kind] ?? BUILT_IN_DIALOGS[active.kind];\n if (!Component) return null;\n return <Component api={api} onClose={onClose} context={active.context} />;\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * FormatCellsDialog — the SDK chrome's built-in Format Cells modal.\n *\n * Ported from `apps/web/src/shell/FormatCellsDialog.tsx`, reimplemented against\n * the `CasualSheetsAPI` + FUniver facade ONLY (no app context: no use-univer, no\n * useActiveCellState, no home-tab-actions). Tabs: Number · Alignment · Font ·\n * Border · Fill. Reads the active cell's current style off the snapshot to seed\n * the form, and applies via the same facade calls the app uses\n * (`setFontWeight` / `setHorizontalAlignment` / `setNumberFormat` / `setBorder`\n * / `setBackground` / …), so behaviour matches the real app exactly.\n *\n * Mounted by `<DialogHost>` when `openDialog('format-cells')` is called and no\n * host override is registered.\n */\n\nimport { useEffect, useMemo, useState, type CSSProperties } from 'react';\nimport { BorderStyleTypes, BorderType } from '@univerjs/core';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_INPUT_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\ntype TabId = 'number' | 'alignment' | 'font' | 'border' | 'fill';\n\ntype HAlign = 'left' | 'center' | 'right';\ntype VAlign = 'top' | 'middle' | 'bottom';\ntype BorderChoice = 'all' | 'outside' | 'top' | 'bottom' | 'left' | 'right' | 'none';\n\nconst DEFAULT_BORDER_COLOR = '#000000';\n\n/** Number-format presets — patterns copied verbatim from the app's\n * `home-tab-actions.NUMBER_FORMAT_PATTERNS`. */\nconst NUMBER_FORMAT_PATTERNS = {\n general: '',\n number: '#,##0.00',\n integer: '#,##0',\n currency: '\"$\"#,##0.00',\n accounting: '_(\"$\"* #,##0.00_);_(\"$\"* (#,##0.00);_(\"$\"* \"-\"??_);_(@_)',\n percent: '0.00%',\n date: 'yyyy-mm-dd',\n time: 'hh:mm:ss',\n scientific: '0.00E+00',\n text: '@',\n} as const;\ntype NumberFormatKey = keyof typeof NUMBER_FORMAT_PATTERNS;\n\nconst WEIGHT_TO_STYLE: BorderStyleTypes = BorderStyleTypes.THIN;\n\ninterface DialogState {\n numberFormatKey: NumberFormatKey;\n numberPattern: string;\n align: HAlign;\n vAlign: VAlign;\n wrap: boolean;\n fontFamily: string;\n fontSize: string;\n bold: boolean;\n italic: boolean;\n underline: boolean;\n borderChoice: BorderChoice;\n borderColor: string;\n fillColor: string;\n}\n\nconst TABS: Array<{ id: TabId; label: string }> = [\n { id: 'number', label: 'Number' },\n { id: 'alignment', label: 'Alignment' },\n { id: 'font', label: 'Font' },\n { id: 'border', label: 'Border' },\n { id: 'fill', label: 'Fill' },\n];\n\nconst FONT_FAMILIES = [\n 'Calibri',\n 'Arial',\n 'Helvetica',\n 'Inter',\n 'Times New Roman',\n 'Georgia',\n 'Verdana',\n 'Courier New',\n 'JetBrains Mono',\n];\n\nconst NUMBER_FORMAT_OPTIONS: Array<{ value: NumberFormatKey; label: string }> = [\n { value: 'general', label: 'General' },\n { value: 'integer', label: 'Number (no decimals)' },\n { value: 'number', label: 'Number (2 decimals)' },\n { value: 'currency', label: 'Currency' },\n { value: 'accounting', label: 'Accounting' },\n { value: 'percent', label: 'Percent' },\n { value: 'date', label: 'Date' },\n { value: 'time', label: 'Time' },\n { value: 'scientific', label: 'Scientific' },\n { value: 'text', label: 'Text' },\n];\n\nfunction detectFormatKey(pattern: string): NumberFormatKey {\n for (const key of Object.keys(NUMBER_FORMAT_PATTERNS) as NumberFormatKey[]) {\n if (NUMBER_FORMAT_PATTERNS[key] === pattern) return key;\n }\n return 'general';\n}\n\n/** Univer style shape we read off the active cell (subset). */\ninterface CellStyle {\n ff?: string;\n fs?: number;\n bl?: number; // bold (1)\n it?: number; // italic (1)\n ul?: { s?: number } | number; // underline\n ht?: number; // horizontal: 1 left, 2 center, 3 right\n vt?: number; // vertical: 1 top, 2 middle, 3 bottom\n tb?: number; // text wrap: 3 wrap\n bg?: { rgb?: string };\n n?: { pattern?: string };\n bd?: Record<string, unknown>;\n}\n\n/**\n * Resolve the active cell's style from the snapshot. Styles can be an inline\n * object or a string key into the workbook's style table — mirror the app's\n * `getCellData()` + styles-table lookup, but off the SDK snapshot.\n */\nfunction readActiveStyle(api: CasualSheetsAPI): CellStyle | null {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const snap = api.getSnapshot() as any;\n if (!snap) return null;\n const sel = api.getSelection();\n const sheetId = sel?.sheetId ?? api.univer.getActiveWorkbook()?.getActiveSheet()?.getSheetId();\n if (!sheetId) return null;\n const sheet = snap.sheets?.[sheetId];\n if (!sheet) return null;\n const row = sel?.range.startRow ?? 0;\n const col = sel?.range.startColumn ?? 0;\n const cell = sheet.cellData?.[row]?.[col];\n if (!cell) return null;\n const s = cell.s;\n if (typeof s === 'string') return (snap.styles?.[s] as CellStyle) ?? null;\n return (s as CellStyle) ?? null;\n}\n\nfunction buildInitialState(style: CellStyle | null): DialogState {\n const pattern = style?.n?.pattern ?? '';\n const underline =\n typeof style?.ul === 'number' ? style.ul === 1 : !!(style?.ul && style.ul.s === 1);\n return {\n numberFormatKey: detectFormatKey(pattern),\n numberPattern: pattern,\n align: style?.ht === 2 ? 'center' : style?.ht === 3 ? 'right' : 'left',\n vAlign: style?.vt === 1 ? 'top' : style?.vt === 2 ? 'middle' : 'bottom',\n wrap: style?.tb === 3,\n fontFamily: style?.ff || 'Calibri',\n fontSize: String(style?.fs || 11),\n bold: style?.bl === 1,\n italic: style?.it === 1,\n underline,\n borderChoice: style?.bd && Object.keys(style.bd).length > 0 ? 'outside' : 'none',\n borderColor: DEFAULT_BORDER_COLOR,\n fillColor: style?.bg?.rgb || '#ffffff',\n };\n}\n\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/** Apply every section of the form via the facade — same calls as the app. */\nfunction applyFormat(api: CasualSheetsAPI, s: DialogState): void {\n const range = activeRange(api);\n if (!range) return;\n\n // Number format — sheets-numfmt facade extension (runtime-added to FRange).\n (range as unknown as { setNumberFormat?: (p: string) => unknown }).setNumberFormat?.(\n s.numberPattern,\n );\n\n // Univer's facade uses 'normal' for right-aligned (FHorizontalAlignment).\n range.setHorizontalAlignment(s.align === 'right' ? 'normal' : s.align);\n range.setVerticalAlignment(s.vAlign);\n range.setWrap(s.wrap);\n\n range.setFontFamily(s.fontFamily || null);\n const size = Number(s.fontSize);\n if (Number.isFinite(size) && size > 0) range.setFontSize(size);\n range.setFontWeight(s.bold ? 'bold' : 'normal');\n range.setFontStyle(s.italic ? 'italic' : 'normal');\n range.setFontLine(s.underline ? 'underline' : 'none');\n\n // Borders — map the preset to a Univer BorderType + thin style (matches the\n // app's setBorders default weight).\n const type =\n s.borderChoice === 'all'\n ? BorderType.ALL\n : s.borderChoice === 'outside'\n ? BorderType.OUTSIDE\n : s.borderChoice === 'top'\n ? BorderType.TOP\n : s.borderChoice === 'bottom'\n ? BorderType.BOTTOM\n : s.borderChoice === 'left'\n ? BorderType.LEFT\n : s.borderChoice === 'right'\n ? BorderType.RIGHT\n : BorderType.NONE;\n const borderStyle = s.borderChoice === 'none' ? BorderStyleTypes.NONE : WEIGHT_TO_STYLE;\n range.setBorder(type, borderStyle, s.borderColor);\n\n range.setBackground(s.fillColor);\n}\n\nconst TABS_ROW_STYLE: CSSProperties = {\n display: 'flex',\n gap: 2,\n borderBottom: '1px solid var(--cs-chrome-border, #edeff3)',\n marginBottom: 14,\n};\n\nfunction tabStyle(activeTab: boolean): CSSProperties {\n return {\n padding: '6px 12px',\n border: 'none',\n borderBottom: `2px solid ${activeTab ? 'var(--cs-chrome-active-fg, #0e7490)' : 'transparent'}`,\n background: 'transparent',\n color: activeTab ? 'var(--cs-chrome-active-fg, #0e7490)' : 'var(--cs-chrome-muted, #605e5c)',\n font: 'inherit',\n fontSize: 13,\n fontWeight: activeTab ? 600 : 400,\n cursor: 'pointer',\n };\n}\n\nconst CHECK_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n marginBottom: 8,\n cursor: 'pointer',\n};\n\nconst COLOR_INPUT_STYLE: CSSProperties = {\n width: 48,\n height: 30,\n padding: 2,\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n cursor: 'pointer',\n};\n\nexport function FormatCellsDialog({ api, onClose }: DialogComponentProps) {\n const [tab, setTab] = useState<TabId>('number');\n // Seed once from the active cell when the dialog mounts.\n const initial = useMemo(() => buildInitialState(readActiveStyle(api)), [api]);\n const [state, setState] = useState<DialogState>(initial);\n\n // Re-seed if the active cell changes while open (rare, but keeps it honest).\n useEffect(() => {\n setState(buildInitialState(readActiveStyle(api)));\n }, [api]);\n\n const update = <K extends keyof DialogState>(key: K, value: DialogState[K]) =>\n setState((prev) => ({ ...prev, [key]: value }));\n\n const apply = () => {\n applyFormat(api, state);\n onClose();\n };\n\n return (\n <Dialog\n title=\"Format Cells\"\n onClose={onClose}\n width={480}\n data-testid=\"cs-format-cells-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-format-cells-apply\"\n onClick={apply}\n >\n Apply\n </button>\n </>\n }\n >\n <div style={TABS_ROW_STYLE} role=\"tablist\" aria-label=\"Format sections\">\n {TABS.map((t) => (\n <button\n key={t.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={tab === t.id}\n data-testid={`cs-format-cells-tab-${t.id}`}\n style={tabStyle(tab === t.id)}\n onClick={() => setTab(t.id)}\n >\n {t.label}\n </button>\n ))}\n </div>\n\n <div role=\"tabpanel\">\n {tab === 'number' && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Preset</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-number-preset\"\n value={state.numberFormatKey}\n onChange={(e) => {\n const key = e.target.value as NumberFormatKey;\n update('numberFormatKey', key);\n update('numberPattern', NUMBER_FORMAT_PATTERNS[key]);\n }}\n >\n {NUMBER_FORMAT_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Pattern</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-number-pattern\"\n value={state.numberPattern}\n onChange={(e) => update('numberPattern', e.target.value)}\n />\n </label>\n </>\n )}\n\n {tab === 'alignment' && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Horizontal</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-align\"\n value={state.align}\n onChange={(e) => update('align', e.target.value as HAlign)}\n >\n <option value=\"left\">Left</option>\n <option value=\"center\">Center</option>\n <option value=\"right\">Right</option>\n </select>\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Vertical</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-valign\"\n value={state.vAlign}\n onChange={(e) => update('vAlign', e.target.value as VAlign)}\n >\n <option value=\"top\">Top</option>\n <option value=\"middle\">Middle</option>\n <option value=\"bottom\">Bottom</option>\n </select>\n </label>\n <label style={CHECK_STYLE} data-testid=\"cs-format-cells-wrap-label\">\n <input\n type=\"checkbox\"\n data-testid=\"cs-format-cells-wrap\"\n checked={state.wrap}\n onChange={(e) => update('wrap', e.target.checked)}\n />\n <span>Wrap text</span>\n </label>\n </>\n )}\n\n {tab === 'font' && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Font</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-font-family\"\n value={state.fontFamily}\n onChange={(e) => update('fontFamily', e.target.value)}\n >\n {FONT_FAMILIES.map((family) => (\n <option key={family} value={family}>\n {family}\n </option>\n ))}\n </select>\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Size</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-font-size\"\n type=\"number\"\n min={6}\n max={72}\n value={state.fontSize}\n onChange={(e) => update('fontSize', e.target.value)}\n />\n </label>\n <label style={CHECK_STYLE}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-format-cells-bold\"\n checked={state.bold}\n onChange={(e) => update('bold', e.target.checked)}\n />\n <span>Bold</span>\n </label>\n <label style={CHECK_STYLE}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-format-cells-italic\"\n checked={state.italic}\n onChange={(e) => update('italic', e.target.checked)}\n />\n <span>Italic</span>\n </label>\n <label style={CHECK_STYLE}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-format-cells-underline\"\n checked={state.underline}\n onChange={(e) => update('underline', e.target.checked)}\n />\n <span>Underline</span>\n </label>\n </>\n )}\n\n {tab === 'border' && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Preset</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-border-choice\"\n value={state.borderChoice}\n onChange={(e) => update('borderChoice', e.target.value as BorderChoice)}\n >\n <option value=\"none\">No border</option>\n <option value=\"all\">All borders</option>\n <option value=\"outside\">Outside border</option>\n <option value=\"top\">Top border</option>\n <option value=\"bottom\">Bottom border</option>\n <option value=\"left\">Left border</option>\n <option value=\"right\">Right border</option>\n </select>\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Color</span>\n <input\n style={COLOR_INPUT_STYLE}\n data-testid=\"cs-format-cells-border-color\"\n type=\"color\"\n value={state.borderColor}\n onChange={(e) => update('borderColor', e.target.value)}\n />\n </label>\n </>\n )}\n\n {tab === 'fill' && (\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Fill color</span>\n <input\n style={COLOR_INPUT_STYLE}\n data-testid=\"cs-format-cells-fill-color\"\n type=\"color\"\n value={state.fillColor}\n onChange={(e) => update('fillColor', e.target.value)}\n />\n </label>\n )}\n </div>\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Dialog — the SDK chrome's modal primitive for `<CasualSheets chrome>`.\n *\n * Ported from `apps/web/src/shell/Dialog.tsx`, but decoupled from the app: it\n * uses ONLY React + the chrome's `--cs-chrome-*` token approach (inline styles\n * with DS-token-backed CSS-var fallbacks, the same pattern as FindReplace), so\n * it renders standalone and themes light/dark via the `data-theme` wrapper\n * `<CasualSheets>` already sets. No app CSS classes, no app context.\n *\n * - Click-backdrop and Escape close it.\n * - Body scroll is locked while open.\n * - Focus is trapped (Tab/Shift+Tab cycle within the dialog) and restored to\n * the opener on close — the WAI-ARIA dialog pattern.\n * - Portaled to `document.body` so it escapes the chrome's stacking contexts\n * and the Univer canvas can't intercept clicks meant for the dialog.\n */\n\nimport { useEffect, useRef, type CSSProperties, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Icon } from './Icon';\n\nexport interface DialogProps {\n /** Heading shown in the dialog header. */\n title: string;\n /** Close request (backdrop click, Escape, the × button, or a footer action). */\n onClose: () => void;\n /** Optional footer node — typically Cancel / primary-action buttons. */\n footer?: ReactNode;\n children: ReactNode;\n /** Max width of the dialog card. Default 460. */\n width?: number;\n ['data-testid']?: string;\n}\n\nconst FOCUSABLE_SELECTOR =\n 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex]:not([tabindex=\"-1\"]), [contenteditable=\"true\"]';\n\nconst BACKDROP_STYLE: CSSProperties = {\n position: 'fixed',\n inset: 0,\n zIndex: 1200,\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'center',\n padding: '8vh 16px 16px',\n background: 'rgba(15, 23, 42, 0.35)',\n overflow: 'auto',\n};\n\nconst CARD_STYLE: CSSProperties = {\n width: '100%',\n background: 'var(--cs-chrome-input-bg, #ffffff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n borderRadius: 10,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n boxShadow: '0 18px 48px rgba(0, 0, 0, 0.28)',\n font: 'inherit',\n fontSize: 13,\n display: 'flex',\n flexDirection: 'column',\n maxHeight: '84vh',\n};\n\nconst HEADER_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 8,\n padding: '12px 16px',\n borderBottom: '1px solid var(--cs-chrome-border, #edeff3)',\n};\n\nconst TITLE_STYLE: CSSProperties = {\n margin: 0,\n fontSize: 15,\n fontWeight: 600,\n color: 'var(--cs-chrome-fg, #201f1e)',\n};\n\nconst CLOSE_STYLE: CSSProperties = {\n width: 28,\n height: 28,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-muted, #605e5c)',\n cursor: 'pointer',\n padding: 0,\n};\n\nconst BODY_STYLE: CSSProperties = {\n padding: 16,\n overflow: 'auto',\n};\n\nconst FOOTER_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: 8,\n padding: '12px 16px',\n borderTop: '1px solid var(--cs-chrome-border, #edeff3)',\n};\n\nexport function Dialog({ title, onClose, footer, children, width = 460, ...rest }: DialogProps) {\n const dialogRef = useRef<HTMLDivElement>(null);\n const openerRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n // Remember who had focus before us so we can restore it on close.\n openerRef.current = (document.activeElement as HTMLElement) ?? null;\n\n // Lock body scroll; pad for the disappearing scrollbar so the grid doesn't\n // shift when the dialog opens.\n const prevOverflow = document.body.style.overflow;\n const prevPaddingRight = document.body.style.paddingRight;\n const scrollbarW = window.innerWidth - document.documentElement.clientWidth;\n document.body.style.overflow = 'hidden';\n if (scrollbarW > 0) document.body.style.paddingRight = `${scrollbarW}px`;\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation();\n onClose();\n return;\n }\n if (e.key !== 'Tab') return;\n const root = dialogRef.current;\n if (!root) return;\n const focusables = Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n (el) => !el.hasAttribute('disabled') && el.offsetParent !== null,\n );\n if (focusables.length === 0) return;\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = document.activeElement as HTMLElement | null;\n if (e.shiftKey && (active === first || !root.contains(active))) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && (active === last || !root.contains(active))) {\n e.preventDefault();\n first.focus();\n }\n };\n document.addEventListener('keydown', onKey);\n\n const first = dialogRef.current?.querySelector<HTMLElement>(FOCUSABLE_SELECTOR);\n first?.focus();\n\n return () => {\n document.removeEventListener('keydown', onKey);\n document.body.style.overflow = prevOverflow;\n document.body.style.paddingRight = prevPaddingRight;\n const opener = openerRef.current;\n if (opener && document.contains(opener)) opener.focus();\n };\n }, [onClose]);\n\n return createPortal(\n <div\n style={BACKDROP_STYLE}\n data-testid=\"cs-dialog-backdrop\"\n onMouseDown={(e) => {\n if (e.target === e.currentTarget) onClose();\n }}\n >\n <div\n style={{ ...CARD_STYLE, maxWidth: width }}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n ref={dialogRef}\n data-testid={rest['data-testid']}\n >\n <div style={HEADER_STYLE}>\n <h2 style={TITLE_STYLE}>{title}</h2>\n <button\n type=\"button\"\n style={CLOSE_STYLE}\n data-testid=\"cs-dialog-close\"\n aria-label=\"Close\"\n onClick={onClose}\n >\n <Icon name=\"close\" size={18} />\n </button>\n </div>\n <div style={BODY_STYLE}>{children}</div>\n {footer && <div style={FOOTER_STYLE}>{footer}</div>}\n </div>\n </div>,\n document.body,\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Shared inline styles for built-in SDK dialogs. Kept in their own module (not\n * in Dialog.tsx) so the component files stay component-only for React Fast\n * Refresh. Every value reads a `--cs-chrome-*` token with a hardcoded fallback,\n * matching the chrome's theming approach (light/dark via the `data-theme`\n * wrapper `<CasualSheets>` sets).\n */\n\nimport type { CSSProperties } from 'react';\n\nexport const DIALOG_FIELD_STYLE: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n marginBottom: 12,\n};\n\nexport const DIALOG_LABEL_STYLE: CSSProperties = {\n fontSize: 12,\n fontWeight: 500,\n color: 'var(--cs-chrome-muted, #605e5c)',\n};\n\nexport const DIALOG_INPUT_STYLE: CSSProperties = {\n height: 30,\n padding: '0 8px',\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n boxSizing: 'border-box',\n};\n\nexport const DIALOG_BTN_PRIMARY_STYLE: CSSProperties = {\n height: 30,\n padding: '0 14px',\n border: 'none',\n borderRadius: 6,\n background: 'var(--cs-chrome-active-fg, #0e7490)',\n color: '#fff',\n font: 'inherit',\n fontSize: 13,\n fontWeight: 500,\n cursor: 'pointer',\n};\n\nexport const DIALOG_BTN_SECONDARY_STYLE: CSSProperties = {\n height: 30,\n padding: '0 14px',\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n};\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * FormulaBar — minimal built-in formula bar for `<CasualSheets chrome>`.\n *\n * The formula bar: a NameBox (active-cell ref + go-to navigation) and an editable\n * input that shows the active cell's formula (or value) and commits edits through\n * the facade — `=…` as a formula, a number as a number, else text. Typing a\n * function name after `=` shows an autocomplete dropdown (arrows + Enter/Tab to\n * complete, Escape to dismiss). Self-contained: drives the editor only via\n * `CasualSheetsAPI`.\n */\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n} from 'react';\nimport { ICommandService } from '@univerjs/core';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { NameBox } from './NameBox';\n\n// Curated common spreadsheet functions for the autocomplete dropdown. (Univer\n// ships ~530; this covers what people actually type without bundling them all.)\nconst FUNCTIONS = [\n 'ABS',\n 'AND',\n 'AVERAGE',\n 'AVERAGEIF',\n 'AVERAGEIFS',\n 'CEILING',\n 'CHOOSE',\n 'COLUMN',\n 'COLUMNS',\n 'CONCAT',\n 'CONCATENATE',\n 'COUNT',\n 'COUNTA',\n 'COUNTBLANK',\n 'COUNTIF',\n 'COUNTIFS',\n 'DATE',\n 'DATEDIF',\n 'DAY',\n 'EDATE',\n 'EOMONTH',\n 'EXACT',\n 'FILTER',\n 'FIND',\n 'FLOOR',\n 'HLOOKUP',\n 'HOUR',\n 'IF',\n 'IFERROR',\n 'IFNA',\n 'IFS',\n 'INDEX',\n 'INDIRECT',\n 'INT',\n 'ISBLANK',\n 'ISERROR',\n 'ISNA',\n 'ISNUMBER',\n 'ISTEXT',\n 'LEFT',\n 'LEN',\n 'LOOKUP',\n 'LOWER',\n 'MATCH',\n 'MAX',\n 'MAXIFS',\n 'MEDIAN',\n 'MID',\n 'MIN',\n 'MINIFS',\n 'MINUTE',\n 'MOD',\n 'MONTH',\n 'NETWORKDAYS',\n 'NOT',\n 'NOW',\n 'OFFSET',\n 'OR',\n 'POWER',\n 'PRODUCT',\n 'PROPER',\n 'RAND',\n 'RANDBETWEEN',\n 'RANK',\n 'REPLACE',\n 'REPT',\n 'RIGHT',\n 'ROUND',\n 'ROUNDDOWN',\n 'ROUNDUP',\n 'ROW',\n 'ROWS',\n 'SEARCH',\n 'SECOND',\n 'SORT',\n 'SQRT',\n 'SUBSTITUTE',\n 'SUM',\n 'SUMIF',\n 'SUMIFS',\n 'SUMPRODUCT',\n 'SWITCH',\n 'TEXT',\n 'TEXTJOIN',\n 'TODAY',\n 'TRANSPOSE',\n 'TRIM',\n 'UNIQUE',\n 'UPPER',\n 'VALUE',\n 'VLOOKUP',\n 'WEEKDAY',\n 'WORKDAY',\n 'XLOOKUP',\n 'XMATCH',\n 'YEAR',\n];\n\nconst TOKEN_RE = /([A-Za-z][A-Za-z0-9._]*)$/;\n\n/** Function suggestions for the trailing identifier of a formula draft. */\nfunction suggestFor(draft: string | null): string[] {\n if (!draft || !draft.startsWith('=')) return [];\n const m = TOKEN_RE.exec(draft);\n if (!m) return [];\n const prefix = m[1].toUpperCase();\n return FUNCTIONS.filter((f) => f.startsWith(prefix) && f !== prefix).slice(0, 8);\n}\n\n/** A1 column letters from a 0-based column index (0→A, 26→AA). */\nfunction colToLetters(col: number): string {\n let s = '';\n let n = col;\n do {\n s = String.fromCharCode(65 + (n % 26)) + s;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n return s;\n}\n\ninterface ActiveCell {\n a1: string;\n /** Formula text (`=…`) if the cell has one, else the raw value as a string. */\n text: string;\n}\n\nfunction readActiveCell(api: CasualSheetsAPI): ActiveCell | null {\n const sel = api.getSelection();\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sel || !sheet) return null;\n const { startRow, startColumn } = sel.range;\n const range = sheet.getRange(startRow, startColumn);\n const formula = range.getFormula?.() || '';\n const raw = range.getValue?.();\n return {\n a1: colToLetters(startColumn) + (startRow + 1),\n text: formula || (raw == null ? '' : String(raw)),\n };\n}\n\nconst BAR_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n padding: '3px 6px',\n borderBottom: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.12))',\n background: 'var(--cs-chrome-bg, #f8f9fa)',\n flex: '0 0 auto',\n font: 'inherit',\n fontSize: 13,\n};\n\nconst FX_STYLE: CSSProperties = {\n flex: '0 0 auto',\n fontStyle: 'italic',\n color: 'var(--cs-chrome-muted, #6b7280)',\n};\n\nconst INPUT_STYLE: CSSProperties = {\n width: '100%',\n height: 24,\n padding: '0 8px',\n border: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.18))',\n borderRadius: 4,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #1f2329)',\n font: 'inherit',\n fontSize: 13,\n boxSizing: 'border-box',\n};\n\nconst INPUT_WRAP_STYLE: CSSProperties = { position: 'relative', flex: '1 1 auto', minWidth: 0 };\n\nconst AC_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: 2,\n minWidth: 200,\n maxHeight: 240,\n overflowY: 'auto',\n zIndex: 1000,\n padding: 4,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n borderRadius: 8,\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.16)',\n};\n\nconst AC_ITEM_STYLE: CSSProperties = {\n display: 'block',\n width: '100%',\n textAlign: 'left',\n height: 26,\n padding: '0 8px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n};\n\nexport interface FormulaBarProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function FormulaBar({ api }: FormulaBarProps) {\n const [cell, setCell] = useState<ActiveCell | null>(null);\n // null = mirror the active cell; a string = the user is editing.\n const [draft, setDraft] = useState<string | null>(null);\n const draftRef = useRef<string | null>(null);\n draftRef.current = draft;\n // Autocomplete: active suggestion index + a dismissed flag (Escape closes the\n // dropdown without cancelling the edit).\n const [acIdx, setAcIdx] = useState(0);\n const [acDismissed, setAcDismissed] = useState(false);\n\n useEffect(() => {\n if (!api) return;\n const refresh = () => {\n // Don't clobber an in-progress edit on unrelated command activity.\n if (draftRef.current !== null) return;\n setCell(readActiveCell(api));\n };\n refresh();\n const injector = (api.univer as unknown as { _injector?: { get(t: unknown): unknown } })\n ._injector;\n const cmd = injector?.get(ICommandService) as\n | { onCommandExecuted: (cb: () => void) => { dispose: () => void } }\n | undefined;\n const sub = cmd?.onCommandExecuted(() => refresh());\n return () => sub?.dispose();\n }, [api]);\n\n const suggestions = useMemo(() => suggestFor(draft), [draft]);\n const acOpen = !acDismissed && suggestions.length > 0;\n\n const commit = (text: string) => {\n setDraft(null);\n setAcDismissed(false);\n if (!api) return;\n const sel = api.getSelection();\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sel || !sheet) return;\n const range = sheet.getRange(sel.range.startRow, sel.range.startColumn);\n const t = text.trim();\n if (t.startsWith('=')) range.setValue({ f: t });\n else if (t !== '' && !Number.isNaN(Number(t))) range.setValue(Number(t));\n else range.setValue(t);\n };\n\n const onType = (v: string) => {\n setDraft(v);\n setAcIdx(0);\n setAcDismissed(false);\n };\n\n // Replace the trailing identifier with the chosen function + '('.\n const complete = (fn: string) => {\n const base = draft ?? '';\n setDraft(base.replace(TOKEN_RE, `${fn}(`));\n setAcIdx(0);\n };\n\n const onKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (acOpen) {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setAcIdx((i) => Math.min(i + 1, suggestions.length - 1));\n return;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n setAcIdx((i) => Math.max(i - 1, 0));\n return;\n }\n if (e.key === 'Enter' || e.key === 'Tab') {\n e.preventDefault();\n complete(suggestions[acIdx] ?? suggestions[0]);\n return;\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n setAcDismissed(true);\n return;\n }\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n commit((e.target as HTMLInputElement).value);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setDraft(null);\n (e.target as HTMLInputElement).blur();\n }\n };\n\n const shown = draft ?? cell?.text ?? '';\n\n return (\n <div style={BAR_STYLE} data-testid=\"casual-sheets-formula-bar\">\n <NameBox api={api} />\n <span style={FX_STYLE} aria-hidden>\n fx\n </span>\n <div style={INPUT_WRAP_STYLE}>\n <input\n type=\"text\"\n aria-label=\"Formula bar\"\n data-testid=\"casual-sheets-formula-input\"\n style={INPUT_STYLE}\n value={shown}\n onChange={(e) => onType(e.target.value)}\n onKeyDown={onKeyDown}\n onBlur={(e) => {\n if (draftRef.current !== null) commit(e.target.value);\n }}\n disabled={!api}\n />\n {acOpen && (\n <div style={AC_STYLE} data-testid=\"cs-formula-suggestions\" role=\"listbox\">\n {suggestions.map((fn, i) => (\n <button\n key={fn}\n type=\"button\"\n role=\"option\"\n aria-selected={i === acIdx}\n data-testid={`cs-formula-suggestion-${fn}`}\n style={{\n ...AC_ITEM_STYLE,\n background: i === acIdx ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent',\n color: i === acIdx ? 'var(--cs-chrome-active-fg, #0e7490)' : AC_ITEM_STYLE.color,\n }}\n // mousedown+preventDefault so the input keeps focus (no blur-commit).\n onMouseDown={(e) => {\n e.preventDefault();\n complete(fn);\n }}\n onMouseEnter={() => setAcIdx(i)}\n >\n {fn}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * NameBox — the Excel \"Name Box\" for `<CasualSheets chrome>`.\n *\n * A small editable box that mirrors the active cell's A1 reference live, and\n * lets you navigate by typing a reference (e.g. `B5` or `A1:C3`) + Enter. Self-\n * contained: reads the active selection through `CasualSheetsAPI` and navigates\n * through the FUniver facade (`getRange(a1).activate()`) — no app context, no\n * named-range support (defined names land with the rich name-box later).\n *\n * The orchestrator uses this to replace the static name-box span currently\n * inside FormulaBar.tsx; this component does NOT edit FormulaBar.\n */\n\nimport { useEffect, useRef, useState, type CSSProperties, type KeyboardEvent } from 'react';\nimport { ICommandService } from '@univerjs/core';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\n\n/** A defined name as surfaced by the FWorkbook facade. */\ninterface DefinedNameEntry {\n name: string;\n ref: string;\n}\n\n/**\n * Read the active workbook's defined names through the FWorkbook facade\n * (`getDefinedNames()` → `FDefinedName[]`, each with `getName()` +\n * `getFormulaOrRefString()`). Returns [] when the facade/API is unavailable —\n * never invents an API.\n */\nfunction readDefinedNames(api: CasualSheetsAPI | null): DefinedNameEntry[] {\n if (!api) return [];\n try {\n const wb = api.univer.getActiveWorkbook() as unknown as {\n getDefinedNames?: () => Array<{\n getName?: () => string;\n getFormulaOrRefString?: () => string;\n }>;\n } | null;\n const names = wb?.getDefinedNames?.();\n if (!names) return [];\n return names\n .map((dn) => ({\n name: dn.getName?.() ?? '',\n ref: dn.getFormulaOrRefString?.() ?? '',\n }))\n .filter((e) => e.name !== '');\n } catch {\n return [];\n }\n}\n\n/** A1 column letters from a 0-based column index (0→A, 26→AA). */\nfunction colToLetters(col: number): string {\n let s = '';\n let n = col;\n do {\n s = String.fromCharCode(65 + (n % 26)) + s;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n return s;\n}\n\n/** The active selection's top-left A1 reference, or '' when unavailable. */\nfunction readActiveRef(api: CasualSheetsAPI): string {\n const sel = api.getSelection();\n if (!sel) return '';\n const { startRow, startColumn } = sel.range;\n return colToLetters(startColumn) + (startRow + 1);\n}\n\nconst BOX_STYLE: CSSProperties = {\n flex: '0 0 auto',\n width: 80,\n height: 24,\n padding: '0 8px',\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n borderRadius: 4,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n textAlign: 'center',\n boxSizing: 'border-box',\n};\n\nconst ROOT_STYLE: CSSProperties = {\n flex: '0 0 auto',\n display: 'inline-flex',\n alignItems: 'center',\n position: 'relative',\n};\n\nconst DROPDOWN_BTN_STYLE: CSSProperties = {\n flex: '0 0 auto',\n width: 20,\n height: 24,\n marginLeft: 2,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 4,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n cursor: 'pointer',\n padding: 0,\n};\n\nconst MENU_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: 4,\n zIndex: 1000,\n minWidth: 160,\n maxHeight: 280,\n overflowY: 'auto',\n padding: 4,\n borderRadius: 8,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.18)',\n};\n\nconst MENU_ITEM_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'baseline',\n justifyContent: 'space-between',\n gap: 12,\n width: '100%',\n height: 28,\n padding: '0 8px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n textAlign: 'left',\n cursor: 'pointer',\n boxSizing: 'border-box',\n};\n\nconst MENU_EMPTY_STYLE: CSSProperties = {\n padding: '6px 8px',\n color: 'var(--cs-chrome-muted, #8a8886)',\n fontSize: 12,\n whiteSpace: 'nowrap',\n};\n\nconst ITEM_REF_STYLE: CSSProperties = {\n color: 'var(--cs-chrome-muted, #8a8886)',\n fontSize: 11,\n flex: '0 0 auto',\n};\n\nexport interface NameBoxProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function NameBox({ api }: NameBoxProps) {\n // The A1 reference of the active cell.\n const [ref, setRef] = useState('');\n // null = mirror the active cell; a string = the user is typing.\n const [draft, setDraft] = useState<string | null>(null);\n const draftRef = useRef<string | null>(null);\n draftRef.current = draft;\n const inputRef = useRef<HTMLInputElement>(null);\n // The defined-names dropdown: open state, current entries, and a root ref for\n // outside-pointerdown detection (mirrors ColorPicker's popover pattern).\n const [open, setOpen] = useState(false);\n const [names, setNames] = useState<DefinedNameEntry[]>([]);\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Reflect the active cell: subscribe to command activity (covers selection\n // moves) and re-read the reference — unless the user is mid-edit.\n useEffect(() => {\n if (!api) return;\n const refresh = () => {\n if (draftRef.current !== null) return;\n setRef(readActiveRef(api));\n };\n refresh();\n const injector = (api.univer as unknown as { _injector?: { get(t: unknown): unknown } })\n ._injector;\n const cmd = injector?.get(ICommandService) as\n | { onCommandExecuted: (cb: () => void) => { dispose: () => void } }\n | undefined;\n const sub = cmd?.onCommandExecuted(() => refresh());\n return () => sub?.dispose();\n }, [api]);\n\n // While the dropdown is open, close it on Escape or any outside pointerdown.\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: PointerEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n };\n const onKeyDown = (e: globalThis.KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n /** Navigate to the typed A1 reference / range. Invalid input is ignored. */\n const navigate = (text: string) => {\n const t = text.trim();\n setDraft(null);\n if (!api || t === '') {\n setRef(readActiveRef(api ?? ({} as CasualSheetsAPI)));\n return;\n }\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sheet) return;\n try {\n // FRange.getRange parses an A1 string (\"B5\") or range (\"A1:C3\").\n const range = (sheet as unknown as { getRange(a1: string): { activate(): void } }).getRange(\n t,\n );\n range.activate();\n } catch {\n // Invalid reference — fall back to the current selection.\n setRef(readActiveRef(api));\n }\n };\n\n // Open the dropdown: refresh the defined-name list from the live workbook,\n // then toggle. mousedown (not click) so the grid selection isn't lost first.\n const toggleDropdown = () => {\n setOpen((cur) => {\n const next = !cur;\n if (next) setNames(readDefinedNames(api));\n return next;\n });\n };\n\n // Navigate to a defined name's range. The ref may carry a sheet prefix\n // (\"Sheet1!$A$1\") and absolute `$` markers — strip both, then reuse the same\n // getRange(...).activate() path the typed-reference navigation uses.\n const navigateName = (entry: DefinedNameEntry) => {\n setOpen(false);\n const raw = entry.ref.trim();\n if (raw === '') return;\n const afterSheet = raw.includes('!') ? raw.slice(raw.lastIndexOf('!') + 1) : raw;\n const a1 = afterSheet.replace(/\\$/g, '');\n navigate(a1);\n };\n\n const onKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n navigate((e.target as HTMLInputElement).value);\n (e.target as HTMLInputElement).blur();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setDraft(null);\n setRef(api ? readActiveRef(api) : '');\n (e.target as HTMLInputElement).blur();\n }\n };\n\n const shown = draft ?? ref;\n\n return (\n <div ref={rootRef} style={ROOT_STYLE}>\n <input\n ref={inputRef}\n type=\"text\"\n aria-label=\"Name box\"\n title=\"Name box\"\n data-testid=\"cs-namebox-input\"\n style={BOX_STYLE}\n value={shown}\n disabled={!api}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n onFocus={(e) => e.currentTarget.select()}\n onBlur={() => {\n // Abandon any uncommitted edit without navigating.\n if (draftRef.current !== null) {\n setDraft(null);\n setRef(api ? readActiveRef(api) : '');\n }\n }}\n />\n <button\n type=\"button\"\n title=\"Defined names\"\n aria-label=\"Defined names\"\n aria-haspopup=\"true\"\n aria-expanded={open}\n data-testid=\"cs-namebox-dropdown\"\n style={{\n ...DROPDOWN_BTN_STYLE,\n background: open ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent',\n color: open ? 'var(--cs-chrome-active-fg, #0e7490)' : DROPDOWN_BTN_STYLE.color,\n }}\n disabled={!api}\n // mousedown (not click) so the grid's selection isn't lost first.\n onMouseDown={(e) => {\n e.preventDefault();\n toggleDropdown();\n }}\n >\n <Icon name=\"expand_more\" size={18} />\n </button>\n {open && (\n <div style={MENU_STYLE} role=\"menu\" data-testid=\"cs-namebox-menu\">\n {names.length === 0 ? (\n <div style={MENU_EMPTY_STYLE}>No names</div>\n ) : (\n names.map((entry, i) => (\n <button\n key={entry.name}\n type=\"button\"\n role=\"menuitem\"\n title={entry.ref || entry.name}\n data-testid={`cs-namebox-name-${i}`}\n style={MENU_ITEM_STYLE}\n onMouseDown={(e) => {\n e.preventDefault();\n navigateName(entry);\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n >\n <span>{entry.name}</span>\n {entry.ref && <span style={ITEM_REF_STYLE}>{entry.ref}</span>}\n </button>\n ))\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * StatusBar — built-in status bar for `<CasualSheets chrome>`.\n *\n * Self-contained: reads the active selection through `CasualSheetsAPI` and shows\n * Excel-style aggregates over it (Average / Count / Numerical Count / Min / Max\n * / Sum), plus a zoom control on the right (− / level / +, click the level to\n * reset to 100%). Drives the editor only through the facade + commands.\n *\n * Count = non-empty cells (any type); Numerical Count = numeric cells; the\n * numeric aggregates (Average/Min/Max/Sum) run over the numeric cells only —\n * matching Excel's status-bar semantics.\n *\n * Zoom dispatches the OPERATION `sheet.operation.set-zoom-ratio` (not the\n * `set-zoom-ratio` / `change-zoom-ratio` commands, which bail when Univer's\n * always-present formula-bar editor unit reports visible). The operation's\n * render controller registers in sheets-ui's `onRendered` lifecycle — i.e. a\n * frame or two after `onReady` — so the buttons just no-op until the grid has\n * painted; in practice the user can't click that fast.\n */\n\nimport { useEffect, useState, type CSSProperties } from 'react';\nimport { ICommandService } from '@univerjs/core';\nimport type { CasualSheetsAPI } from '../sheets/api';\n\ninterface Stats {\n /** Non-empty cells (any type). */\n count: number;\n /** Numeric cells. */\n numCount: number;\n sum: number;\n avg: number;\n min: number;\n max: number;\n}\n\nfunction readStats(api: CasualSheetsAPI): Stats | null {\n const sel = api.getSelection();\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sel || !sheet) return null;\n const { startRow, startColumn, endRow, endColumn } = sel.range;\n // Single cell → nothing to aggregate (matches Excel).\n if (startRow === endRow && startColumn === endColumn) return null;\n const values = sheet.getRange(sel.range).getValues?.() as unknown[][] | undefined;\n if (!values) return null;\n let count = 0;\n let numCount = 0;\n let sum = 0;\n let min = Infinity;\n let max = -Infinity;\n for (const row of values) {\n for (const v of row) {\n if (v == null || v === '') continue;\n count += 1;\n if (typeof v === 'number' && Number.isFinite(v)) {\n numCount += 1;\n sum += v;\n if (v < min) min = v;\n if (v > max) max = v;\n }\n }\n }\n if (count === 0) return null;\n return { count, numCount, sum, avg: numCount ? sum / numCount : 0, min, max };\n}\n\n/** Current zoom as a fraction (1 = 100%). Reads the live worksheet config via\n * the facade's `getSheet()` escape hatch; falls back to 1. */\nfunction readZoom(api: CasualSheetsAPI): number {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ws = (sheet as any)?.getSheet?.();\n const z = ws?.getConfig?.().zoomRatio;\n return typeof z === 'number' && z > 0 ? z : 1;\n}\n\n// Trim float noise without locking to a fixed precision.\nfunction fmt(n: number): string {\n return Number(n.toFixed(10)).toLocaleString();\n}\n\nconst BAR_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: 16,\n height: 24,\n padding: '0 12px',\n borderTop: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.12))',\n background: 'var(--cs-chrome-bg, #f8f9fa)',\n color: 'var(--cs-chrome-muted, #4b5563)',\n flex: '0 0 auto',\n font: 'inherit',\n fontSize: 12,\n userSelect: 'none',\n};\n\nconst ZOOM_GROUP_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n};\n\nconst ZOOM_BTN_STYLE: CSSProperties = {\n width: 20,\n height: 18,\n border: 'none',\n borderRadius: 4,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n cursor: 'pointer',\n fontSize: 14,\n lineHeight: 1,\n padding: 0,\n};\n\nconst ZOOM_LEVEL_STYLE: CSSProperties = {\n minWidth: 40,\n height: 18,\n border: 'none',\n borderRadius: 4,\n background: 'transparent',\n color: 'var(--cs-chrome-muted, #4b5563)',\n cursor: 'pointer',\n font: 'inherit',\n fontSize: 12,\n textAlign: 'center',\n};\n\nexport interface StatusBarProps {\n api: CasualSheetsAPI | null;\n}\n\nexport function StatusBar({ api }: StatusBarProps) {\n const [stats, setStats] = useState<Stats | null>(null);\n const [zoom, setZoom] = useState(1);\n\n useEffect(() => {\n if (!api) return;\n const refresh = () => {\n setStats(readStats(api));\n setZoom(readZoom(api));\n };\n refresh();\n const injector = (api.univer as unknown as { _injector?: { get(t: unknown): unknown } })\n ._injector;\n const cmd = injector?.get(ICommandService) as\n | { onCommandExecuted: (cb: () => void) => { dispose: () => void } }\n | undefined;\n const sub = cmd?.onCommandExecuted(() => refresh());\n return () => sub?.dispose();\n }, [api]);\n\n // Drive the zoom OPERATION directly — see file header for why not the commands.\n const setZoomRatio = (ratio: number) => {\n const wb = api?.univer.getActiveWorkbook();\n const sheet = wb?.getActiveSheet();\n if (!wb || !sheet) return;\n const clamped = Math.min(4, Math.max(0.1, ratio));\n void api?.executeCommand('sheet.operation.set-zoom-ratio', {\n unitId: wb.getId(),\n subUnitId: sheet.getSheetId(),\n zoomRatio: clamped,\n });\n // Optimistic local update — the onCommandExecuted refresh will reconcile.\n setZoom(clamped);\n };\n const zoomBy = (delta: number) => setZoomRatio(Math.round((zoom + delta) * 100) / 100);\n const resetZoom = () => setZoomRatio(1);\n\n return (\n <div style={BAR_STYLE} data-testid=\"casual-sheets-status-bar\">\n {stats && (\n <>\n {stats.numCount > 0 && <span data-stat=\"average\">Average: {fmt(stats.avg)}</span>}\n <span data-stat=\"count\">Count: {stats.count}</span>\n {stats.numCount > 0 && (\n <>\n <span data-stat=\"num-count\">Numerical Count: {stats.numCount}</span>\n <span data-stat=\"min\">Min: {fmt(stats.min)}</span>\n <span data-stat=\"max\">Max: {fmt(stats.max)}</span>\n <span data-stat=\"sum\">Sum: {fmt(stats.sum)}</span>\n </>\n )}\n </>\n )}\n <span style={ZOOM_GROUP_STYLE} data-testid=\"cs-zoom\">\n <button\n type=\"button\"\n style={ZOOM_BTN_STYLE}\n aria-label=\"Zoom out\"\n title=\"Zoom out\"\n data-testid=\"cs-zoom-out\"\n disabled={!api}\n onMouseDown={(e) => {\n e.preventDefault();\n zoomBy(-0.1);\n }}\n >\n −\n </button>\n <button\n type=\"button\"\n style={ZOOM_LEVEL_STYLE}\n aria-label=\"Reset zoom to 100%\"\n title=\"Reset zoom to 100%\"\n data-testid=\"cs-zoom-level\"\n disabled={!api}\n onMouseDown={(e) => {\n e.preventDefault();\n resetZoom();\n }}\n >\n {Math.round(zoom * 100)}%\n </button>\n <button\n type=\"button\"\n style={ZOOM_BTN_STYLE}\n aria-label=\"Zoom in\"\n title=\"Zoom in\"\n data-testid=\"cs-zoom-in\"\n disabled={!api}\n onMouseDown={(e) => {\n e.preventDefault();\n zoomBy(0.1);\n }}\n >\n +\n </button>\n </span>\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * MenuBar — the built-in dropdown menu row for `<CasualSheets chrome>`.\n *\n * Office / Google-Sheets-style horizontal menu strip (no logo, no title — the\n * host frames the editor with its own bar): File · Edit · View · Insert ·\n * Format · Data · Help. Each top-level button opens a dropdown of items that\n * either dispatch a verified Univer command / facade call through the\n * `CasualSheetsAPI` (no app context), or — for actions that need a dialog the\n * SDK doesn't ship — route through the optional `onDialogRequest` host hook.\n *\n * This mirrors `apps/web/src/shell/MenuBar.tsx`, but reimplements every action\n * INLINE against `api` / `api.univer` (the FUniver facade) + `api.executeCommand`.\n * The command ids + facade logic are copied verbatim from\n * `apps/web/src/shell/home-tab-actions.ts` + `tab-actions.ts` so behaviour\n * matches the real app exactly.\n *\n * Feature flags: pass `features` to hide a control or whole menu group when its\n * feature is disabled. Defaults to all-enabled. A control whose feature is\n * `false` does not render. An entire top-level menu that ends up with no\n * runnable items is dropped.\n *\n * Dialog routing: items marked `dialog: '<kind>'` (Format Cells, Insert Chart,\n * PivotTable, Find & Replace, Insert/Delete cells, Sparkline, Name Manager,\n * Goal Seek, Data Validation, Conditional Formatting, …) call\n * `onDialogRequest(kind, context)` so the host renders its own UI. When\n * `onDialogRequest` is not provided, those items are omitted (the SDK never\n * fakes a dialog).\n *\n * Self-contained: only one menu is open at a time; Escape and an outside\n * pointerdown close it.\n */\n\nimport { useEffect, useRef, useState, type CSSProperties, type ReactNode } from 'react';\nimport { BorderStyleTypes, BorderType } from '@univerjs/core';\nimport { openExternal } from './openExternal';\nimport type { FUniver } from '@univerjs/core/facade';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { ensurePluginByName } from '../univer';\nimport { Icon } from './Icon';\nimport { ensureChromeFonts } from './fonts';\nimport { useDialogs } from './dialog-context';\nimport type { ChromeExtensions } from './extensions';\nimport {\n computeVisibleMenus,\n type MenuDef,\n type MenuId,\n type MenuItemDef,\n type RunFn,\n} from './menu-model';\n\nexport type { MenuDialogKind } from './menu-model';\n\n/**\n * The menu data model + pure gating engine live in `./menu-model` (univer-free,\n * so unit-testable). `RunFn` / `MenuItemDef` / `MenuDef` / `MenuId` /\n * `MenuDialogKind` are re-imported above; the `run` handlers that populate\n * `MENUS` are defined inline below against the `@univerjs/core` facade.\n */\n\n/**\n * Pretty-print a `Ctrl+Shift+X` shortcut for the current platform. The SDK\n * doesn't import the app's `formatShortcut`, so this is a compact inline\n * equivalent: on macOS, swap Ctrl→⌘, Alt→⌥, Shift→⇧ and drop the `+`.\n */\nfunction fmtShortcut(shortcut: string): string {\n const isMac =\n typeof navigator !== 'undefined' && /Mac|iPhone|iPad/i.test(navigator.platform || '');\n if (!isMac) return shortcut;\n return shortcut\n .split('+')\n .map((part) => {\n switch (part) {\n case 'Ctrl':\n return '⌘';\n case 'Alt':\n return '⌥';\n case 'Shift':\n return '⇧';\n default:\n return part;\n }\n })\n .join('');\n}\n\n/* ───────────────────────── inline action helpers ─────────────────────────\n * Every helper below is a faithful port of the corresponding function in\n * apps/web/src/shell/home-tab-actions.ts + tab-actions.ts, reimplemented over\n * the SDK's `api` (CasualSheetsAPI) / `api.univer` (FUniver) so the chrome\n * never imports app context. Command ids are identical to the app's.\n */\n\nfunction fu(api: CasualSheetsAPI): FUniver {\n return api.univer;\n}\n\nfunction activeRange(api: CasualSheetsAPI) {\n return fu(api).getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\nfunction activeSheet(api: CasualSheetsAPI) {\n return fu(api).getActiveWorkbook()?.getActiveSheet() ?? null;\n}\n\n/** Selection as A1 (e.g. `B2:D10`), or null. Used to seed dialog context. */\nfunction selectionA1(api: CasualSheetsAPI): string | null {\n const range = activeRange(api);\n if (!range) return null;\n try {\n return range.getA1Notation();\n } catch {\n return null;\n }\n}\n\n/* ── Edit ─────────────────────────────────────────────────────────────── */\n\nconst undo: RunFn = (api) => void api.executeCommand('univer.command.undo');\nconst redo: RunFn = (api) => void api.executeCommand('univer.command.redo');\nconst cut: RunFn = (api) => void api.executeCommand('univer.command.cut');\nconst copy: RunFn = (api) => void api.executeCommand('univer.command.copy');\nconst paste: RunFn = (api) => void api.executeCommand('univer.command.paste');\nconst pasteFormattingOnly: RunFn = (api) => void api.executeCommand('sheet.command.paste-format');\n\n/* ── Insert (facade-driven; mirror tab-actions.ts) ─────────────────────── */\n\nconst insertRowAbove: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.insertRowBefore(range.getRow());\n};\n\nconst insertRowBelow: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.insertRowAfter(range.getRow() + range.getHeight() - 1);\n};\n\nconst insertColumnLeft: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.insertColumnBefore(range.getColumn());\n};\n\nconst insertColumnRight: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.insertColumnAfter(range.getColumn() + range.getWidth() - 1);\n};\n\nconst deleteSelectedRow: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.deleteRows(range.getRow(), range.getHeight());\n};\n\nconst deleteSelectedColumn: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.deleteColumns(range.getColumn(), range.getWidth());\n};\n\nconst insertNewSheet: RunFn = (api) => {\n fu(api).getActiveWorkbook()?.insertSheet();\n};\n\nconst insertImage: RunFn = (api) => void api.executeCommand('sheet.command.insert-float-image');\n\nconst insertHyperlink: RunFn = (api) =>\n void api.executeCommand('sheet.operation.insert-hyper-link');\n\nconst insertComment: RunFn = (api) => void api.executeCommand('sheet.operation.show-comment-modal');\n\nconst insertTodayDate: RunFn = (api) => {\n const range = activeRange(api);\n if (!range) return;\n const today = new Date();\n const pad = (n: number) => n.toString().padStart(2, '0');\n const v = `${today.getFullYear()}-${pad(today.getMonth() + 1)}-${pad(today.getDate())}`;\n range.setValue({ v });\n};\n\nconst insertCurrentTime: RunFn = (api) => {\n const range = activeRange(api);\n if (!range) return;\n const now = new Date();\n const pad = (n: number) => n.toString().padStart(2, '0');\n const v = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;\n range.setValue({ v });\n};\n\nconst insertTable: RunFn = (api) => {\n void (async () => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n const wb = fu(api).getActiveWorkbook();\n if (!range || !sheet || !wb) return;\n await ensurePluginByName('table');\n await api.executeCommand('sheet.command.add-table', {\n unitId: wb.getId(),\n subUnitId: sheet.getSheetId(),\n range: {\n startRow: range.getRow(),\n startColumn: range.getColumn(),\n endRow: range.getRow() + range.getHeight() - 1,\n endColumn: range.getColumn() + range.getWidth() - 1,\n },\n });\n })();\n};\n\nconst autoFitColumns: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n const withAutoWidth = sheet as unknown as {\n setColumnAutoWidth?: (col: number, n: number) => unknown;\n };\n withAutoWidth.setColumnAutoWidth?.(range.getColumn(), range.getWidth());\n};\n\nconst AUTO_FIT_ROW_CAP = 500;\nconst autoFitRows: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n const start = range.getRow();\n const count = Math.min(range.getHeight(), AUTO_FIT_ROW_CAP);\n for (let r = 0; r < count; r++) sheet.autoFitRow(start + r);\n};\n\n/* ── Format ───────────────────────────────────────────────────────────── */\n\n// Patterns copied from home-tab-actions.ts NUMBER_FORMAT_PATTERNS.\nconst NUMBER_FORMAT_PATTERNS = {\n general: '',\n number: '#,##0.00',\n integer: '#,##0',\n currency: '\"$\"#,##0.00',\n accounting: '_(\"$\"* #,##0.00_);_(\"$\"* (#,##0.00);_(\"$\"* \"-\"??_);_(@_)',\n percent: '0.00%',\n date: 'yyyy-mm-dd',\n time: 'hh:mm:ss',\n scientific: '0.00E+00',\n text: '@',\n} as const;\ntype NumberFormatKey = keyof typeof NUMBER_FORMAT_PATTERNS;\n\nconst NUM_FORMAT_ORDER: NumberFormatKey[] = [\n 'general',\n 'number',\n 'integer',\n 'currency',\n 'accounting',\n 'percent',\n 'date',\n 'time',\n 'scientific',\n 'text',\n];\n\nconst NUM_FORMAT_SHORTCUT: Partial<Record<NumberFormatKey, string>> = {\n number: 'Ctrl+Shift+1',\n time: 'Ctrl+Shift+2',\n date: 'Ctrl+Shift+3',\n currency: 'Ctrl+Shift+4',\n percent: 'Ctrl+Shift+5',\n scientific: 'Ctrl+Shift+6',\n};\n\nfunction setNumberFormatByKey(api: CasualSheetsAPI, key: NumberFormatKey) {\n // setNumberFormat lives on the sheets-numfmt facade extension (runtime cast).\n const range = activeRange(api) as unknown as { setNumberFormat?: (p: string) => unknown } | null;\n range?.setNumberFormat?.(NUMBER_FORMAT_PATTERNS[key]);\n}\n\nconst increaseDecimal: RunFn = (api) =>\n void api.executeCommand('sheet.command.numfmt.add.decimal.command');\nconst decreaseDecimal: RunFn = (api) =>\n void api.executeCommand('sheet.command.numfmt.subtract.decimal.command');\nconst clearFormat: RunFn = (api) => void api.executeCommand('sheet.command.clear-selection-format');\n\nfunction applyBorders(api: CasualSheetsAPI, choice: 'all' | 'outside' | 'none') {\n const range = activeRange(api);\n if (!range) return;\n const type =\n choice === 'all' ? BorderType.ALL : choice === 'outside' ? BorderType.OUTSIDE : BorderType.NONE;\n const style = choice === 'none' ? BorderStyleTypes.NONE : BorderStyleTypes.THIN;\n range.setBorder(type, style, '#000000');\n}\n\n/* ── Format → Visibility (command-driven; mirror tab-actions.ts) ───────── */\n\nfunction rowSpan(api: CasualSheetsAPI) {\n const wb = fu(api).getActiveWorkbook();\n const sheet = activeSheet(api);\n const range = activeRange(api);\n if (!wb || !sheet || !range) return null;\n const startRow = range.getRow();\n const endRow = startRow + range.getHeight() - 1;\n const maxCol = (sheet as unknown as { getMaxColumns?: () => number }).getMaxColumns?.() ?? 1;\n return { wb, sheet, startRow, endRow, maxCol };\n}\n\nfunction colSpan(api: CasualSheetsAPI) {\n const wb = fu(api).getActiveWorkbook();\n const sheet = activeSheet(api);\n const range = activeRange(api);\n if (!wb || !sheet || !range) return null;\n const startColumn = range.getColumn();\n const endColumn = startColumn + range.getWidth() - 1;\n const maxRow = (sheet as unknown as { getMaxRows?: () => number }).getMaxRows?.() ?? 1;\n return { wb, sheet, startColumn, endColumn, maxRow };\n}\n\nconst hideSelectedRows: RunFn = (api) => {\n const s = rowSpan(api);\n if (!s) return;\n void api.executeCommand('sheet.command.set-rows-hidden', {\n unitId: s.wb.getId(),\n subUnitId: s.sheet.getSheetId(),\n ranges: [\n {\n startRow: s.startRow,\n endRow: s.endRow,\n startColumn: 0,\n endColumn: Math.max(0, s.maxCol - 1),\n rangeType: 1,\n },\n ],\n });\n};\n\nconst unhideSelectedRows: RunFn = (api) => {\n const s = rowSpan(api);\n if (!s) return;\n void api.executeCommand('sheet.command.set-specific-rows-visible', {\n unitId: s.wb.getId(),\n subUnitId: s.sheet.getSheetId(),\n ranges: [\n {\n startRow: s.startRow,\n endRow: s.endRow,\n startColumn: 0,\n endColumn: Math.max(0, s.maxCol - 1),\n rangeType: 1,\n },\n ],\n });\n};\n\nconst hideSelectedColumns: RunFn = (api) => {\n const s = colSpan(api);\n if (!s) return;\n void api.executeCommand('sheet.command.set-col-hidden', {\n unitId: s.wb.getId(),\n subUnitId: s.sheet.getSheetId(),\n ranges: [\n {\n startRow: 0,\n endRow: Math.max(0, s.maxRow - 1),\n startColumn: s.startColumn,\n endColumn: s.endColumn,\n rangeType: 2,\n },\n ],\n });\n};\n\nconst unhideSelectedColumns: RunFn = (api) => {\n const s = colSpan(api);\n if (!s) return;\n // Univer's \"show specific cols\" id is asymmetric with the row variant.\n void api.executeCommand('sheet.command.set-col-visible-on-cols', {\n unitId: s.wb.getId(),\n subUnitId: s.sheet.getSheetId(),\n ranges: [\n {\n startRow: 0,\n endRow: Math.max(0, s.maxRow - 1),\n startColumn: s.startColumn,\n endColumn: s.endColumn,\n rangeType: 2,\n },\n ],\n });\n};\n\n/* ── View ─────────────────────────────────────────────────────────────── */\n\ntype FreezeCapableSheet = {\n setFrozenRows: (n: number) => unknown;\n setFrozenColumns: (n: number) => unknown;\n};\n\nconst freezeFirstRow: RunFn = (api) => {\n (activeSheet(api) as unknown as FreezeCapableSheet | null)?.setFrozenRows(1);\n};\nconst freezeFirstColumn: RunFn = (api) => {\n (activeSheet(api) as unknown as FreezeCapableSheet | null)?.setFrozenColumns(1);\n};\nconst freezeAtSelection: RunFn = (api) =>\n void api.executeCommand('sheet.command.set-selection-frozen');\nconst unfreezePanes: RunFn = (api) => void api.executeCommand('sheet.command.cancel-frozen');\n\nconst toggleGridlines: RunFn = (api) => {\n const wb = fu(api).getActiveWorkbook();\n const sheet = activeSheet(api);\n if (!wb || !sheet) return;\n // BooleanNumber: 0 = hide, 1 = show. The app reads current state; without a\n // reactive UI store here we hide (matches the app's default click path).\n void api.executeCommand('sheet.command.toggle-gridlines', {\n unitId: wb.getId(),\n subUnitId: sheet.getSheetId(),\n showGridlines: 0,\n });\n};\n\nconst toggleCommentPanel: RunFn = (api) =>\n void api.executeCommand('sheet.operation.toggle-comment-panel');\n\nconst jumpToFirstCell: RunFn = (api) => {\n activeSheet(api)?.getRange(0, 0).activate();\n};\n\nconst switchToPreviousSheet: RunFn = (api) => switchSheetByDelta(api, -1);\nconst switchToNextSheet: RunFn = (api) => switchSheetByDelta(api, +1);\n\nfunction switchSheetByDelta(api: CasualSheetsAPI, delta: -1 | 1) {\n const wb = fu(api).getActiveWorkbook();\n const active = wb?.getActiveSheet();\n if (!wb || !active) return;\n const sheets = wb.getSheets();\n const activeId = active.getSheetId();\n const idx = sheets.findIndex((s) => s.getSheetId() === activeId);\n if (idx < 0) return;\n const nextIdx = idx + delta;\n if (nextIdx < 0 || nextIdx >= sheets.length) return;\n wb.setActiveSheet(sheets[nextIdx]);\n}\n\nconst showFormulas: RunFn = (api) => void api.executeCommand('sheet.command.set-show-formula', {});\n\n/* ── Data ─────────────────────────────────────────────────────────────── */\n\nconst sortAsc: RunFn = (api) => sortRange(api, true);\nconst sortDesc: RunFn = (api) => sortRange(api, false);\n\nfunction sortRange(api: CasualSheetsAPI, ascending: boolean) {\n const range = activeRange(api);\n if (!range) return;\n // sort() comes from the sheets-sort facade extension (runtime cast).\n const withSort = range as unknown as {\n sort?: (spec: { column: number; ascending: boolean }) => unknown;\n };\n withSort.sort?.({ column: range.getColumn(), ascending });\n}\n\nconst toggleFilter: RunFn = (api) => {\n void (async () => {\n await ensurePluginByName('filter');\n const wb = fu(api).getActiveWorkbook();\n const sheet = activeSheet(api);\n const range = activeRange(api);\n if (!wb || !sheet || !range) return;\n const sheetWithFilter = sheet as unknown as { getFilter?: () => unknown };\n if (sheetWithFilter.getFilter?.()) {\n await api.executeCommand('sheet.command.remove-sheet-filter', {\n unitId: wb.getId(),\n subUnitId: sheet.getSheetId(),\n });\n return;\n }\n await api.executeCommand('sheet.command.set-filter-range', {\n unitId: wb.getId(),\n subUnitId: sheet.getSheetId(),\n range: {\n startRow: range.getRow(),\n startColumn: range.getColumn(),\n endRow: range.getRow() + range.getHeight() - 1,\n endColumn: range.getColumn() + range.getWidth() - 1,\n },\n });\n })();\n};\n\nconst splitTextToColumns: RunFn = (api) =>\n void api.executeCommand('sheet.command.split-text-to-columns');\n\nconst forceRecalculate: RunFn = (api) =>\n void api.executeCommand('formula.mutation.set-formula-calculation-start', {\n forceCalculation: true,\n });\n\n/* ───────────────────────────── menu structure ─────────────────────────── */\n\n// Mirrors the app's menu order. Dialog items resolve `dialog` against\n// `onDialogRequest`; non-dialog items dispatch via the inline helpers above.\nconst MENUS: MenuDef[] = [\n {\n id: 'file',\n label: 'File',\n feature: 'file',\n items: [\n { kind: 'item', id: 'properties', label: 'Properties…', icon: 'info', dialog: 'properties' },\n {\n kind: 'item',\n id: 'about',\n label: 'About casual sheets',\n icon: 'help_outline',\n dialog: 'about',\n feature: 'branding',\n },\n ],\n },\n {\n id: 'edit',\n label: 'Edit',\n items: [\n { kind: 'item', id: 'undo', label: 'Undo', icon: 'undo', shortcut: 'Ctrl+Z', run: undo },\n { kind: 'item', id: 'redo', label: 'Redo', icon: 'redo', shortcut: 'Ctrl+Y', run: redo },\n { kind: 'separator', id: 'sep-clip' },\n { kind: 'item', id: 'cut', label: 'Cut', icon: 'content_cut', shortcut: 'Ctrl+X', run: cut },\n {\n kind: 'item',\n id: 'copy',\n label: 'Copy',\n icon: 'content_copy',\n shortcut: 'Ctrl+C',\n run: copy,\n },\n {\n kind: 'item',\n id: 'paste',\n label: 'Paste',\n icon: 'content_paste',\n shortcut: 'Ctrl+V',\n run: paste,\n },\n {\n kind: 'item',\n id: 'paste-format',\n label: 'Paste formatting only',\n icon: 'content_paste',\n shortcut: 'Ctrl+Shift+V',\n run: pasteFormattingOnly,\n },\n {\n kind: 'item',\n id: 'paste-special',\n label: 'Paste Special…',\n icon: 'content_paste_go',\n shortcut: 'Ctrl+Alt+V',\n dialog: 'paste-special',\n },\n { kind: 'separator', id: 'sep-find' },\n {\n kind: 'item',\n id: 'find-replace',\n label: 'Find & Replace…',\n icon: 'search',\n shortcut: 'Ctrl+F',\n dialog: 'find-replace',\n },\n { kind: 'separator', id: 'sep-cells' },\n {\n kind: 'item',\n id: 'edit-insert-cells',\n label: 'Insert cells…',\n icon: 'add_box',\n shortcut: 'Ctrl++',\n dialog: 'insert-cells',\n },\n {\n kind: 'item',\n id: 'edit-delete-cells',\n label: 'Delete cells…',\n icon: 'indeterminate_check_box',\n shortcut: 'Ctrl+-',\n dialog: 'delete-cells',\n },\n ],\n },\n {\n id: 'view',\n label: 'View',\n items: [\n {\n kind: 'item',\n id: 'show-formulas',\n label: 'Show formulas',\n icon: 'description',\n shortcut: 'Ctrl+`',\n run: showFormulas,\n },\n {\n kind: 'item',\n id: 'toggle-gridlines',\n label: 'Toggle gridlines',\n icon: 'grid_on',\n run: toggleGridlines,\n },\n { kind: 'separator', id: 'sep-freeze' },\n {\n kind: 'item',\n id: 'freeze-row',\n label: 'Freeze top row',\n icon: 'border_horizontal',\n run: freezeFirstRow,\n },\n {\n kind: 'item',\n id: 'freeze-col',\n label: 'Freeze first column',\n icon: 'border_vertical',\n run: freezeFirstColumn,\n },\n {\n kind: 'item',\n id: 'freeze-selection',\n label: 'Freeze panes (at selection)',\n icon: 'grid_4x4',\n run: freezeAtSelection,\n },\n { kind: 'item', id: 'unfreeze', label: 'Unfreeze', icon: 'grid_off', run: unfreezePanes },\n { kind: 'separator', id: 'sep-nav' },\n {\n kind: 'item',\n id: 'jump-home',\n label: 'Jump to A1',\n icon: 'home',\n shortcut: 'Ctrl+Home',\n run: jumpToFirstCell,\n },\n {\n kind: 'item',\n id: 'prev-sheet',\n label: 'Previous sheet',\n icon: 'navigate_before',\n shortcut: 'Ctrl+PageUp',\n run: switchToPreviousSheet,\n },\n {\n kind: 'item',\n id: 'next-sheet',\n label: 'Next sheet',\n icon: 'navigate_next',\n shortcut: 'Ctrl+PageDown',\n run: switchToNextSheet,\n },\n { kind: 'separator', id: 'sep-panels' },\n {\n kind: 'item',\n id: 'comments-panel',\n label: 'Comments panel',\n icon: 'forum',\n run: toggleCommentPanel,\n },\n ],\n },\n {\n id: 'insert',\n label: 'Insert',\n items: [\n {\n kind: 'item',\n id: 'new-sheet',\n label: 'New sheet',\n icon: 'add_box',\n shortcut: 'Shift+F11',\n run: insertNewSheet,\n },\n {\n kind: 'item',\n id: 'insert-table',\n label: 'Table',\n icon: 'table_rows',\n shortcut: 'Ctrl+L',\n run: insertTable,\n feature: 'tables',\n },\n {\n kind: 'item',\n id: 'insert-chart',\n label: 'Chart…',\n icon: 'bar_chart',\n dialog: 'insert-chart',\n feature: 'charts',\n },\n {\n kind: 'item',\n id: 'insert-sparkline',\n label: 'Sparkline…',\n icon: 'show_chart',\n dialog: 'insert-sparkline',\n feature: 'sparklines',\n },\n {\n kind: 'item',\n id: 'insert-pivot',\n label: 'PivotTable…',\n icon: 'pivot_table_chart',\n dialog: 'insert-pivot',\n feature: 'pivots',\n },\n { kind: 'separator', id: 'sep-objects' },\n { kind: 'item', id: 'insert-image', label: 'Image…', icon: 'image', run: insertImage },\n {\n kind: 'item',\n id: 'insert-function',\n label: 'Function…',\n icon: 'functions',\n shortcut: 'Shift+F3',\n dialog: 'insert-function',\n },\n {\n kind: 'item',\n id: 'insert-link',\n label: 'Hyperlink…',\n icon: 'link',\n shortcut: 'Ctrl+K',\n run: insertHyperlink,\n },\n {\n kind: 'item',\n id: 'insert-comment',\n label: 'Comment',\n icon: 'comment',\n shortcut: 'Shift+F2',\n run: insertComment,\n },\n { kind: 'separator', id: 'sep-rowcol' },\n {\n kind: 'submenu',\n id: 'insert-rowcol',\n label: 'Rows & columns',\n icon: 'grid_on',\n items: [\n {\n kind: 'item',\n id: 'insert-row-above',\n label: 'Row above',\n icon: 'vertical_align_top',\n run: insertRowAbove,\n },\n {\n kind: 'item',\n id: 'insert-row-below',\n label: 'Row below',\n icon: 'vertical_align_bottom',\n run: insertRowBelow,\n },\n {\n kind: 'item',\n id: 'insert-col-left',\n label: 'Column left',\n icon: 'keyboard_tab_rtl',\n run: insertColumnLeft,\n },\n {\n kind: 'item',\n id: 'insert-col-right',\n label: 'Column right',\n icon: 'keyboard_tab',\n run: insertColumnRight,\n },\n ],\n },\n { kind: 'separator', id: 'sep-autofit' },\n {\n kind: 'item',\n id: 'autofit-col',\n label: 'Auto-fit column width',\n icon: 'settings_ethernet',\n run: autoFitColumns,\n },\n {\n kind: 'item',\n id: 'autofit-row',\n label: 'Auto-fit row height',\n icon: 'height',\n run: autoFitRows,\n },\n { kind: 'separator', id: 'sep-date' },\n {\n kind: 'item',\n id: 'insert-today',\n label: \"Today's date\",\n icon: 'today',\n shortcut: 'Ctrl+;',\n run: insertTodayDate,\n },\n {\n kind: 'item',\n id: 'insert-time',\n label: 'Current time',\n icon: 'schedule',\n shortcut: 'Ctrl+Shift+:',\n run: insertCurrentTime,\n },\n ],\n },\n {\n id: 'format',\n label: 'Format',\n items: [\n {\n kind: 'item',\n id: 'format-cells',\n label: 'Format cells…',\n icon: 'format_shapes',\n shortcut: 'Ctrl+1',\n dialog: 'format-cells',\n },\n { kind: 'separator', id: 'sep-format-cells' },\n {\n kind: 'item',\n id: 'bold',\n label: 'Bold',\n icon: 'format_bold',\n shortcut: 'Ctrl+B',\n run: (api) => void api.executeCommand('sheet.command.set-range-bold'),\n },\n {\n kind: 'item',\n id: 'italic',\n label: 'Italic',\n icon: 'format_italic',\n shortcut: 'Ctrl+I',\n run: (api) => void api.executeCommand('sheet.command.set-range-italic'),\n },\n {\n kind: 'item',\n id: 'underline',\n label: 'Underline',\n icon: 'format_underlined',\n shortcut: 'Ctrl+U',\n run: (api) => void api.executeCommand('sheet.command.set-range-underline'),\n },\n {\n kind: 'item',\n id: 'wrap-text',\n label: 'Wrap text',\n icon: 'wrap_text',\n run: (api) => void api.executeCommand('sheet.command.set-text-wrap', { value: 3 }),\n },\n { kind: 'separator', id: 'sep-numfmt' },\n {\n kind: 'submenu',\n id: 'num-format',\n label: 'Number format',\n icon: 'looks_one',\n items: NUM_FORMAT_ORDER.map<MenuItemDef>((k) => ({\n kind: 'item',\n id: `num-${k}`,\n label: k[0]!.toUpperCase() + k.slice(1),\n icon: 'looks_one',\n shortcut: NUM_FORMAT_SHORTCUT[k],\n run: (api) => setNumberFormatByKey(api, k),\n })),\n },\n {\n kind: 'item',\n id: 'decimal-up',\n label: 'Increase decimals',\n icon: 'decimal_increase',\n run: increaseDecimal,\n },\n {\n kind: 'item',\n id: 'decimal-down',\n label: 'Decrease decimals',\n icon: 'decimal_decrease',\n run: decreaseDecimal,\n },\n { kind: 'separator', id: 'sep-borders' },\n {\n kind: 'submenu',\n id: 'borders',\n label: 'Borders',\n icon: 'border_all',\n items: [\n {\n kind: 'item',\n id: 'border-all',\n label: 'All borders',\n icon: 'border_all',\n run: (api) => applyBorders(api, 'all'),\n },\n {\n kind: 'item',\n id: 'border-outside',\n label: 'Outside borders',\n icon: 'border_outer',\n run: (api) => applyBorders(api, 'outside'),\n },\n {\n kind: 'item',\n id: 'border-none',\n label: 'No border',\n icon: 'border_clear',\n run: (api) => applyBorders(api, 'none'),\n },\n ],\n },\n { kind: 'separator', id: 'sep-cond' },\n {\n kind: 'item',\n id: 'conditional-formatting',\n label: 'Conditional formatting…',\n icon: 'palette',\n dialog: 'conditional-formatting',\n feature: 'conditionalFormatting',\n },\n { kind: 'separator', id: 'sep-visibility' },\n {\n kind: 'submenu',\n id: 'visibility',\n label: 'Visibility',\n icon: 'visibility',\n items: [\n {\n kind: 'item',\n id: 'hide-row',\n label: 'Hide row',\n icon: 'visibility_off',\n shortcut: 'Ctrl+9',\n run: hideSelectedRows,\n },\n {\n kind: 'item',\n id: 'unhide-row',\n label: 'Unhide row',\n icon: 'visibility',\n shortcut: 'Ctrl+Shift+9',\n run: unhideSelectedRows,\n },\n {\n kind: 'item',\n id: 'hide-col',\n label: 'Hide column',\n icon: 'visibility_off',\n shortcut: 'Ctrl+0',\n run: hideSelectedColumns,\n },\n {\n kind: 'item',\n id: 'unhide-col',\n label: 'Unhide column',\n icon: 'visibility',\n shortcut: 'Ctrl+Shift+0',\n run: unhideSelectedColumns,\n },\n ],\n },\n { kind: 'separator', id: 'sep-clear' },\n {\n kind: 'item',\n id: 'clear-format',\n label: 'Clear formatting',\n icon: 'format_clear',\n run: clearFormat,\n },\n { kind: 'separator', id: 'sep-delete' },\n {\n kind: 'item',\n id: 'delete-row',\n label: 'Delete row',\n icon: 'delete_sweep',\n run: deleteSelectedRow,\n },\n {\n kind: 'item',\n id: 'delete-col',\n label: 'Delete column',\n icon: 'folder_delete',\n run: deleteSelectedColumn,\n },\n ],\n },\n {\n id: 'data',\n label: 'Data',\n items: [\n {\n kind: 'item',\n id: 'sort-asc',\n label: 'Sort ascending',\n icon: 'arrow_upward',\n run: sortAsc,\n },\n {\n kind: 'item',\n id: 'sort-desc',\n label: 'Sort descending',\n icon: 'arrow_downward',\n run: sortDesc,\n },\n {\n kind: 'item',\n id: 'sort-custom',\n label: 'Sort range…',\n icon: 'sort',\n dialog: 'custom-sort',\n },\n {\n kind: 'item',\n id: 'toggle-filter',\n label: 'Toggle filter',\n icon: 'filter_alt',\n shortcut: 'Ctrl+Shift+L',\n run: toggleFilter,\n feature: 'filter',\n },\n { kind: 'separator', id: 'sep-tools' },\n {\n kind: 'item',\n id: 'data-validation',\n label: 'Data validation…',\n icon: 'rule',\n dialog: 'data-validation',\n feature: 'dataValidation',\n },\n {\n kind: 'item',\n id: 'name-manager',\n label: 'Name Manager…',\n icon: 'bookmark_add',\n shortcut: 'Ctrl+F3',\n dialog: 'name-manager',\n },\n {\n kind: 'item',\n id: 'goal-seek',\n label: 'Goal Seek…',\n icon: 'analytics',\n dialog: 'goal-seek',\n },\n { kind: 'separator', id: 'sep-clean' },\n {\n kind: 'item',\n id: 'text-to-columns',\n label: 'Text to Columns',\n icon: 'splitscreen',\n run: splitTextToColumns,\n },\n {\n kind: 'item',\n id: 'recalculate',\n label: 'Recalculate',\n icon: 'autorenew',\n shortcut: 'F9',\n run: forceRecalculate,\n },\n ],\n },\n {\n id: 'help',\n label: 'Help',\n // Whole-menu gate: an embedded host passes `features={{ help: false }}` to\n // drop the Help menu entirely (no editor-branded surface). Individual\n // branding links below also carry `feature: 'branding'` so a host that\n // keeps Help (for keyboard shortcuts) can still hide the About / GitHub\n // links with `features={{ branding: false }}`.\n feature: 'help',\n items: [\n {\n kind: 'item',\n id: 'keyboard-shortcuts',\n label: 'Keyboard shortcuts',\n icon: 'info',\n shortcut: 'Ctrl+/',\n dialog: 'keyboard-shortcuts',\n },\n { kind: 'separator', id: 'sep-help', feature: 'branding' },\n {\n kind: 'item',\n id: 'about',\n label: 'About casual sheets',\n icon: 'info',\n dialog: 'about',\n feature: 'branding',\n },\n {\n kind: 'item',\n id: 'github',\n label: 'View on GitHub',\n icon: 'open_in_new',\n run: () => openExternal('https://github.com/CasualOffice/sheets'),\n feature: 'branding',\n },\n ],\n },\n];\n\n/* ───────────────────────────── styling ────────────────────────────────── */\n\nconst BAR_STYLE: CSSProperties = {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n padding: '2px 6px',\n borderBottom: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-bg, #eef1f5)',\n flex: '0 0 auto',\n userSelect: 'none',\n font: 'inherit',\n fontSize: 13,\n};\n\nconst MENU_BTN_STYLE: CSSProperties = {\n height: 26,\n display: 'inline-flex',\n alignItems: 'center',\n padding: '0 10px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n};\n\nconst DROPDOWN_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n minWidth: 220,\n marginTop: 2,\n padding: 4,\n display: 'flex',\n flexDirection: 'column',\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n borderRadius: 8,\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.16)',\n zIndex: 1000,\n};\n\nconst ITEM_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 10,\n width: '100%',\n height: 30,\n padding: '0 10px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n textAlign: 'left',\n};\n\nconst SEPARATOR_STYLE: CSSProperties = {\n height: 1,\n margin: '4px 6px',\n background: 'var(--cs-chrome-border, #e6e9ee)',\n};\n\nconst SHORTCUT_STYLE: CSSProperties = {\n marginLeft: 'auto',\n paddingLeft: 16,\n fontSize: 11,\n color: 'var(--cs-chrome-muted, #6b7280)',\n};\n\nconst SUBMENU_PANEL_STYLE: CSSProperties = {\n position: 'absolute',\n top: -4,\n left: '100%',\n minWidth: 200,\n marginLeft: 2,\n padding: 4,\n display: 'flex',\n flexDirection: 'column',\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n borderRadius: 8,\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.16)',\n zIndex: 1001,\n};\n\n/* ───────────────────────────── component ──────────────────────────────── */\n\nexport interface MenuBarProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n /**\n * Per-feature toggles. A control / menu whose `feature` key is `false` is not\n * rendered. Unknown / omitted keys default to enabled.\n */\n features?: Record<string, boolean>;\n /**\n * Host chrome extensions — custom menu items appended to their target menu.\n * Dialogs/toolbar/panels are handled elsewhere; only `extensions.menu` is read\n * here.\n */\n extensions?: ChromeExtensions;\n}\n\nexport function MenuBar({ api, features = {}, extensions }: MenuBarProps) {\n const dialogs = useDialogs();\n const [open, setOpen] = useState<MenuId | null>(null);\n const [openSubmenu, setOpenSubmenu] = useState<string | null>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n ensureChromeFonts();\n }, []);\n\n // Close on Escape + on a pointerdown outside the menu bar.\n useEffect(() => {\n if (open === null) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setOpen(null);\n setOpenSubmenu(null);\n }\n };\n const onDown = (e: PointerEvent) => {\n if (!rootRef.current?.contains(e.target as Node)) {\n setOpen(null);\n setOpenSubmenu(null);\n }\n };\n document.addEventListener('keydown', onKey);\n document.addEventListener('pointerdown', onDown, true);\n return () => {\n document.removeEventListener('keydown', onKey);\n document.removeEventListener('pointerdown', onDown, true);\n };\n }, [open]);\n\n const close = () => {\n setOpen(null);\n setOpenSubmenu(null);\n };\n\n const runItem = (item: Extract<MenuItemDef, { kind: 'item' }>) => {\n close();\n if (!api) return;\n if (item.dialog) {\n // Range-seeded dialogs get the current selection in A1 as context.\n const seeded =\n item.dialog === 'insert-chart' ||\n item.dialog === 'insert-pivot' ||\n item.dialog === 'insert-sparkline' ||\n item.dialog === 'insert-cells' ||\n item.dialog === 'delete-cells';\n // openDialog opens the SDK built-in by default; a host override / host-owned\n // kind / onDialogRequest wins per the resolution rules in DialogProvider.\n dialogs.openDialog(item.dialog, seeded ? selectionA1(api) : undefined);\n return;\n }\n item.run?.(api);\n };\n\n // Compute the visible menus once per render (feature + dialog-open gating +\n // host menu extensions). Extracted to `computeVisibleMenus` so the gating\n // contract is unit-testable without a DOM.\n const visibleMenus = computeVisibleMenus(MENUS, features, dialogs.canOpen, extensions?.menu);\n\n const renderItems = (items: MenuItemDef[]): ReactNode =>\n items.map((item) => {\n if (item.kind === 'separator') {\n return <div key={item.id} style={SEPARATOR_STYLE} role=\"separator\" aria-hidden />;\n }\n if (item.kind === 'submenu') {\n const isSubOpen = openSubmenu === item.id;\n return (\n <div\n key={item.id}\n style={{ position: 'relative' }}\n onMouseEnter={() => setOpenSubmenu(item.id)}\n onMouseLeave={() => setOpenSubmenu((cur) => (cur === item.id ? null : cur))}\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n data-testid={`cs-menuitem-${item.id}`}\n aria-haspopup=\"menu\"\n aria-expanded={isSubOpen}\n disabled={!api}\n style={{ ...ITEM_STYLE, opacity: api ? 1 : 0.5 }}\n onMouseDown={(e) => e.preventDefault()}\n >\n {item.icon ? (\n <Icon name={item.icon} size={18} />\n ) : (\n <span style={{ width: 18 }} aria-hidden />\n )}\n <span>{item.label}</span>\n <Icon name=\"chevron_right\" size={18} style={{ marginLeft: 'auto' }} />\n </button>\n {isSubOpen && (\n <div style={SUBMENU_PANEL_STYLE} role=\"menu\" aria-label={item.label}>\n {renderItems(item.items)}\n </div>\n )}\n </div>\n );\n }\n return (\n <button\n key={item.id}\n type=\"button\"\n role=\"menuitem\"\n data-testid={`cs-menuitem-${item.id}`}\n disabled={!api}\n style={{ ...ITEM_STYLE, opacity: api ? 1 : 0.5 }}\n onMouseDown={(e) => {\n e.preventDefault();\n runItem(item);\n }}\n onMouseEnter={(e) => {\n setOpenSubmenu(null);\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n >\n {item.icon ? (\n <Icon name={item.icon} size={18} />\n ) : (\n <span style={{ width: 18 }} aria-hidden />\n )}\n <span>{item.label}</span>\n {item.shortcut && <span style={SHORTCUT_STYLE}>{fmtShortcut(item.shortcut)}</span>}\n </button>\n );\n });\n\n return (\n <div\n ref={rootRef}\n style={BAR_STYLE}\n data-testid=\"cs-menubar\"\n role=\"menubar\"\n aria-label=\"Menu bar\"\n >\n {visibleMenus.map((menu) => {\n const isOpen = open === menu.id;\n return (\n <div key={menu.id} style={{ position: 'relative' }}>\n <button\n type=\"button\"\n data-menu={menu.id}\n data-testid={`cs-menu-${menu.id}`}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n style={{\n ...MENU_BTN_STYLE,\n background: isOpen ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent',\n color: isOpen ? 'var(--cs-chrome-active-fg, #0e7490)' : MENU_BTN_STYLE.color,\n }}\n // mousedown (not click) so the grid selection isn't lost first;\n // toggle the menu open/closed.\n onMouseDown={(e) => {\n e.preventDefault();\n setOpenSubmenu(null);\n setOpen((cur) => (cur === menu.id ? null : menu.id));\n }}\n onMouseEnter={(e) => {\n // Hover-to-switch once a menu is already open (Office behaviour).\n if (open !== null && open !== menu.id) {\n setOpen(menu.id);\n setOpenSubmenu(null);\n } else if (!isOpen)\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = isOpen\n ? 'var(--cs-chrome-active, #e6f3f7)'\n : 'transparent';\n }}\n >\n {menu.label}\n </button>\n {isOpen && (\n <div style={DROPDOWN_STYLE} role=\"menu\" aria-label={menu.label}>\n {renderItems(menu.items)}\n </div>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Open an external link in the user's default browser.\n *\n * Inside the Casual Office desktop shell, `window.open()` silently no-ops in the\n * Tauri webview. Route through the shell's scheme-guarded `open_external`\n * command when the Tauri bridge is present; fall back to `window.open` on web.\n */\nexport function openExternal(url: string): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const invoke = (window as any)?.__TAURI__?.core?.invoke as\n | ((cmd: string, args?: unknown) => Promise<unknown>)\n | undefined;\n if (invoke) {\n void invoke('open_external', { url }).catch(() => {\n window.open(url, '_blank', 'noopener,noreferrer');\n });\n return;\n }\n window.open(url, '_blank', 'noopener,noreferrer');\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Univer, IWorkbookData } from '@univerjs/core';\n\n/**\n * Lazy plugin loading — pipeline Stage 4. The cheap plugins (render,\n * formula, sheets, sheets-ui, numfmt, docs) stay eager because every\n * workbook needs them. The heavy / feature-specific plugins (CF, DV,\n * hyperlink, table, note, thread-comment, drawing, sort, filter,\n * find-replace) load on demand:\n *\n * 1. Eagerly when a snapshot is about to mount and we detect the\n * plugin's resource key on it (e.g. `SHEET_CONDITIONAL_FORMATTING_PLUGIN`\n * in `data.resources`). This is the safety net: missing this would\n * silently drop plugin data on file open.\n * 2. Lazily when the user reaches for the feature — opens the Data\n * tab (sort/filter), hits Ctrl+F (find-replace), uses the Insert\n * tab (drawing), etc. The shell hooks `ensurePlugin(...)` into\n * these triggers and awaits before the action runs.\n *\n * Each loader returns the plugins-to-register in the correct order\n * (base before UI, same as `plugins.ts`). Registration order matters\n * in Univer; the loaders bundle a small group together to keep that\n * locality explicit.\n */\n\nexport type LazyPluginGroup =\n | 'cf'\n | 'dv'\n | 'hyperlink'\n | 'note'\n | 'table'\n | 'threadComment'\n | 'drawing'\n | 'sort'\n | 'filter'\n | 'findReplace';\n\ntype Loader = () => Promise<Array<[unknown, unknown?]>>;\n\nconst LOADERS: Record<LazyPluginGroup, Loader> = {\n cf: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-conditional-formatting'),\n import('@univerjs/sheets-conditional-formatting-ui'),\n ]);\n return [\n [base.UniverSheetsConditionalFormattingPlugin],\n [ui.UniverSheetsConditionalFormattingUIPlugin],\n ];\n },\n dv: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-data-validation'),\n import('@univerjs/sheets-data-validation-ui'),\n ]);\n return [[base.UniverSheetsDataValidationPlugin], [ui.UniverSheetsDataValidationUIPlugin]];\n },\n hyperlink: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-hyper-link'),\n import('@univerjs/sheets-hyper-link-ui'),\n ]);\n return [[base.UniverSheetsHyperLinkPlugin], [ui.UniverSheetsHyperLinkUIPlugin]];\n },\n note: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-note'),\n import('@univerjs/sheets-note-ui'),\n ]);\n return [[base.UniverSheetsNotePlugin], [ui.UniverSheetsNoteUIPlugin]];\n },\n table: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-table'),\n import('@univerjs/sheets-table-ui'),\n ]);\n return [[base.UniverSheetsTablePlugin], [ui.UniverSheetsTableUIPlugin]];\n },\n threadComment: async () => {\n const [tc, tcUi, sheetsTc, sheetsTcUi, mentionUi] = await Promise.all([\n import('@univerjs/thread-comment'),\n import('@univerjs/thread-comment-ui'),\n import('@univerjs/sheets-thread-comment'),\n import('@univerjs/sheets-thread-comment-ui'),\n // @-mention autocomplete for the comment editor. Lists candidates via the\n // core IMentionIOService, which CasualSheets overrides with the\n // host-pluggable CasualMentionIOService (see mention-source.ts). Riding\n // the comment group means it loads exactly when comments do.\n import('@univerjs/docs-mention-ui'),\n // Side-effect imports: install FWorksheet.getComments / FRange.\n // getComments / addCommentAsync on the facade prototype. Without\n // these the CommentsPanel's `getActiveSheet().getComments()` and\n // any facade-driven comment flow (e2e, future shell glue) see an\n // undefined method even though the plugin is registered — mirrors\n // the `drawing` group's facade imports above.\n import('@univerjs/sheets-thread-comment/facade'),\n ]);\n return [\n [tc.UniverThreadCommentPlugin],\n [tcUi.UniverThreadCommentUIPlugin],\n [sheetsTc.UniverSheetsThreadCommentPlugin],\n [sheetsTcUi.UniverSheetsThreadCommentUIPlugin],\n [mentionUi.UniverDocsMentionUIPlugin],\n ];\n },\n drawing: async () => {\n const [d, dUi, sd, sdUi] = await Promise.all([\n import('@univerjs/drawing'),\n import('@univerjs/drawing-ui'),\n import('@univerjs/sheets-drawing'),\n import('@univerjs/sheets-drawing-ui'),\n // Side-effect imports: install FWorksheet.insertImage / getImages /\n // updateImages on the facade prototype. Without these, code that\n // reaches in via the FUniver facade (e2e specs, future shell glue)\n // sees an undefined method even though the plugin is registered.\n import('@univerjs/sheets-drawing/facade'),\n import('@univerjs/sheets-drawing-ui/facade'),\n ]);\n return [\n [d.UniverDrawingPlugin],\n [dUi.UniverDrawingUIPlugin],\n [sd.UniverSheetsDrawingPlugin],\n [sdUi.UniverSheetsDrawingUIPlugin],\n ];\n },\n sort: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-sort'),\n import('@univerjs/sheets-sort-ui'),\n ]);\n return [[base.UniverSheetsSortPlugin], [ui.UniverSheetsSortUIPlugin]];\n },\n filter: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-filter'),\n import('@univerjs/sheets-filter-ui'),\n ]);\n return [[base.UniverSheetsFilterPlugin], [ui.UniverSheetsFilterUIPlugin]];\n },\n findReplace: async () => {\n const [base, sheets] = await Promise.all([\n import('@univerjs/find-replace'),\n import('@univerjs/sheets-find-replace'),\n ]);\n return [[base.UniverFindReplacePlugin], [sheets.UniverSheetsFindReplacePlugin]];\n },\n};\n\n/**\n * Map from a Univer `data.resources[].name` to the lazy group that owns\n * it. Used by `eagerLoadForSnapshot` to pre-register plugins whose\n * state already lives on the workbook so file-open never silently\n * drops a CF rule / table / drawing / etc.\n */\nconst RESOURCE_NAME_TO_GROUP: Record<string, LazyPluginGroup> = {\n SHEET_CONDITIONAL_FORMATTING_PLUGIN: 'cf',\n SHEET_DATA_VALIDATION_PLUGIN: 'dv',\n SHEET_HYPER_LINK_PLUGIN: 'hyperlink',\n SHEET_NOTE_PLUGIN: 'note',\n SHEET_TABLE_PLUGIN: 'table',\n SHEET_THREAD_COMMENT_BASE_PLUGIN: 'threadComment',\n SHEET_DRAWING_PLUGIN: 'drawing',\n SHEET_SORT_PLUGIN: 'sort',\n SHEET_FILTER_PLUGIN: 'filter',\n};\n\nconst loaded = new Set<LazyPluginGroup>();\nconst inflight = new Map<LazyPluginGroup, Promise<void>>();\n\n/**\n * Module-level reference to the live Univer instance, set by\n * `UniverSheet.tsx` immediately after `new Univer()`. Lets shell code\n * call `ensurePluginByName(group)` without plumbing the Univer\n * instance through React context (the FUniver facade doesn't expose\n * its host). Cleared on dispose so callers fail loudly if they hit\n * the lazy path after teardown.\n */\nlet currentUniver: Univer | null = null;\n\nexport function setUniverForLazyLoad(univer: Univer | null): void {\n currentUniver = univer;\n}\n\n/**\n * Idempotent: subsequent calls for the same group resolve immediately\n * if the plugin is already loaded; concurrent calls share the same\n * in-flight promise so we never double-register.\n */\nexport function ensurePlugin(univer: Univer, group: LazyPluginGroup): Promise<void> {\n if (loaded.has(group)) return Promise.resolve();\n const existing = inflight.get(group);\n if (existing) return existing;\n const loader = LOADERS[group];\n if (!loader) return Promise.resolve();\n const p = loader().then((plugins) => {\n for (const [PluginCtor, config] of plugins) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n univer.registerPlugin(PluginCtor as any, config);\n }\n loaded.add(group);\n inflight.delete(group);\n });\n inflight.set(group, p);\n return p;\n}\n\n/**\n * Shell-friendly variant of `ensurePlugin` that pulls the Univer\n * instance from the module-level holder set by `UniverSheet.tsx`. Use\n * this anywhere we only have the FUniver facade (toolbar callbacks,\n * panel handlers). Returns a resolved promise if the holder is empty —\n * the worst case is a no-op, never a throw.\n */\nexport function ensurePluginByName(group: LazyPluginGroup): Promise<void> {\n if (loaded.has(group)) return Promise.resolve();\n if (!currentUniver) return Promise.resolve();\n return ensurePlugin(currentUniver, group);\n}\n\n/**\n * Walk a snapshot for plugin-owned resources + side-channel hyperlinks\n * and eagerly load every group that's referenced. Returns a promise\n * the caller MUST await before `createUnit` — Univer's resource manager\n * silently discards keys for plugins that aren't yet registered.\n */\nexport async function eagerLoadForSnapshot(univer: Univer, snapshot: IWorkbookData): Promise<void> {\n const groups = new Set<LazyPluginGroup>();\n const resources = snapshot.resources ?? [];\n for (const r of resources) {\n const g = RESOURCE_NAME_TO_GROUP[r.name];\n if (g) groups.add(g);\n }\n // Hyperlinks live inline in cell.p (Stage 5) — the hyperlink plugin\n // still owns click handling / context-menu actions, so eager-load\n // when any cell has a HYPERLINK customRange.\n if (snapshotHasHyperlinks(snapshot)) groups.add('hyperlink');\n await Promise.all(Array.from(groups).map((g) => ensurePlugin(univer, g)));\n}\n\n/**\n * Idle-load every remaining lazy group AFTER Univer is mounted. The\n * bundle split (each group ships as its own chunk) is the persistent\n * boot-time win — the initial paint doesn't pay for them. This\n * idle-load just ensures they're all eventually registered so a user\n * clicking \"Insert > Table\" doesn't hit a no-op.\n *\n * Loads in parallel via `requestIdleCallback` so they don't compete\n * with the first paint, falling back to `setTimeout(0)` in browsers\n * without rIC (Safari).\n */\nexport function idleLoadAll(univer: Univer): void {\n const groups = Object.keys(LOADERS) as LazyPluginGroup[];\n schedule(() => {\n for (const g of groups) {\n void ensurePlugin(univer, g);\n }\n });\n}\n\nfunction schedule(fn: () => void): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ric = (globalThis as any).requestIdleCallback as\n | ((cb: () => void, opts?: { timeout: number }) => number)\n | undefined;\n if (ric) ric(fn, { timeout: 500 });\n else setTimeout(fn, 0);\n}\n\nfunction snapshotHasHyperlinks(snapshot: IWorkbookData): boolean {\n const sheetOrder = snapshot.sheetOrder ?? [];\n for (const sid of sheetOrder) {\n const sheet = snapshot.sheets?.[sid];\n if (!sheet?.cellData) continue;\n const cellData = sheet.cellData as Record<\n string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, { p?: any }>\n >;\n for (const r of Object.keys(cellData)) {\n const row = cellData[r];\n for (const c of Object.keys(row)) {\n const ranges = row[c]?.p?.body?.customRanges ?? [];\n if (ranges.some((cr: { rangeType?: number }) => cr.rangeType === 0)) return true;\n }\n }\n }\n return false;\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * MenuBar data model + pure gating engine.\n *\n * Split out of `MenuBar.tsx` so the feature-gating contract is unit-testable\n * under `node --test`: `MenuBar.tsx` statically imports `@univerjs/core` values\n * (which the vendored typeless-package ESM can't expose as named exports to\n * node), so it can't be imported in a DOM-less test. This module has only\n * type-only imports (all erased at build), so `computeVisibleMenus` — the code\n * that decides which menus/items a host actually sees — can be exercised\n * directly.\n *\n * Feature gates: pass `features` to hide a control or whole menu group when its\n * feature is disabled. Defaults to all-enabled. A control whose feature is\n * `false` does not render. An entire top-level menu whose own `feature` is\n * `false`, or that ends up with no runnable items, is dropped.\n */\n\nimport type { DialogKind } from './dialog-context';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport type { MenuExtension } from './extensions';\n\nexport type MenuId = 'file' | 'edit' | 'view' | 'insert' | 'format' | 'data' | 'help';\n\n/**\n * Dialog kinds the host can choose to render via `onDialogRequest`. These are\n * the actions the SDK chrome can't fulfil on its own (no built-in modal). The\n * string is passed straight to the host hook; the `context` (when present)\n * carries the pre-resolved A1 selection so the host doesn't have to re-read it.\n */\nexport type MenuDialogKind = DialogKind;\n\nexport type RunFn = (api: CasualSheetsAPI) => void;\n\nexport type MenuItemDef =\n | {\n kind: 'item';\n id: string;\n label: string;\n icon?: string;\n shortcut?: string;\n /** Dispatch a command / facade call directly. */\n run?: RunFn;\n /** Route through the host's `onDialogRequest`. Omitted if no host hook. */\n dialog?: MenuDialogKind;\n /** Feature gate — item hidden when `features[feature] === false`. */\n feature?: string;\n }\n | { kind: 'separator'; id: string; feature?: string }\n | {\n kind: 'submenu';\n id: string;\n label: string;\n icon?: string;\n items: MenuItemDef[];\n feature?: string;\n };\n\nexport interface MenuDef {\n id: MenuId;\n label: string;\n /** Feature gate for the whole menu. */\n feature?: string;\n items: MenuItemDef[];\n}\n\n/* ───────────────────────────── filtering ──────────────────────────────── */\n\n/** True when the feature gate (if any) is enabled (default: enabled). */\nexport function featureOn(feature: string | undefined, features: Record<string, boolean>): boolean {\n if (!feature) return true;\n return features[feature] !== false;\n}\n\n/**\n * Keep an item if its feature is on AND — for a dialog item — the chrome can\n * open it (built-in dialog, host override, or `onDialogRequest`). Dialog items\n * with no way to open are dropped (the SDK never fakes a dialog). Submenus are\n * filtered recursively and dropped when empty.\n */\nexport function keepItem(\n item: MenuItemDef,\n features: Record<string, boolean>,\n canOpen: (kind: DialogKind) => boolean,\n): MenuItemDef | null {\n if (!featureOn(item.feature, features)) return null;\n if (item.kind === 'separator') return item;\n if (item.kind === 'submenu') {\n const items = filterItems(item.items, features, canOpen);\n if (items.length === 0) return null;\n return { ...item, items };\n }\n if (item.dialog && !canOpen(item.dialog)) return null;\n return item;\n}\n\n/** Filter a list and collapse leading/trailing/double separators. */\nexport function filterItems(\n items: MenuItemDef[],\n features: Record<string, boolean>,\n canOpen: (kind: DialogKind) => boolean,\n): MenuItemDef[] {\n const kept = items\n .map((i) => keepItem(i, features, canOpen))\n .filter((i): i is MenuItemDef => i !== null);\n // Collapse separators: drop leading, trailing, and runs.\n const out: MenuItemDef[] = [];\n for (const item of kept) {\n if (item.kind === 'separator') {\n if (out.length === 0) continue;\n if (out[out.length - 1].kind === 'separator') continue;\n }\n out.push(item);\n }\n while (out.length > 0 && out[out.length - 1].kind === 'separator') out.pop();\n return out;\n}\n\n/* ─────────────────────────── host extensions ──────────────────────────── */\n\n/**\n * Append host menu extensions to their target top-level menu. Each extension\n * becomes a normal `item` (with a leading separator before the first host item\n * in that menu so it's visually grouped). Host items dispatch via `onClick` or\n * route a `dialog` kind through the dialog host, exactly like built-ins.\n */\nexport function withMenuExtensions(menus: MenuDef[], ext?: MenuExtension[]): MenuDef[] {\n if (!ext || ext.length === 0) return menus;\n const byMenu = new Map<MenuId, MenuExtension[]>();\n for (const e of ext) {\n const list = byMenu.get(e.menu) ?? [];\n list.push(e);\n byMenu.set(e.menu, list);\n }\n return menus.map((menu) => {\n const extras = byMenu.get(menu.id);\n if (!extras || extras.length === 0) return menu;\n const items: MenuItemDef[] = [...menu.items, { kind: 'separator', id: `ext-sep-${menu.id}` }];\n for (const e of extras) {\n items.push({\n kind: 'item',\n id: `ext-${e.id}`,\n label: e.label,\n icon: e.icon,\n shortcut: e.shortcut,\n dialog: e.dialog,\n run: e.onClick ? (api) => e.onClick?.(api) : undefined,\n });\n }\n return { ...menu, items };\n });\n}\n\n/**\n * Resolve the menus a host actually sees: append menu extensions, filter every\n * item by its `feature` gate + dialog-openability, then drop any top-level menu\n * whose own `feature` is off or that ends up empty.\n *\n * Exported (not inlined in the component) so the feature-gating contract — e.g.\n * `features={{ help: false }}` drops the Help menu and\n * `features={{ branding: false }}` drops the \"View on GitHub\" / \"About\" links —\n * is unit-testable without a DOM.\n */\nexport function computeVisibleMenus(\n menus: MenuDef[],\n features: Record<string, boolean>,\n canOpen: (kind: DialogKind) => boolean,\n ext?: MenuExtension[],\n): MenuDef[] {\n return withMenuExtensions(menus, ext)\n .map((menu) => ({\n ...menu,\n items: filterItems(menu.items, features, canOpen),\n }))\n .filter((menu) => featureOn(menu.feature, features) && menu.items.length > 0);\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * SheetTabs — worksheet tab strip for `<CasualSheets chrome>`.\n *\n * The fundamental multi-sheet control the built-in chrome was missing: switch\n * sheets (click), add a sheet (+), rename (double-click), and delete (context\n * menu). Drives the editor through the FUniver facade only — `insertSheet` /\n * `setActiveSheet` / `deleteSheet` / `FWorksheet.setName` — and stays live by\n * subscribing to the sheet-lifecycle facade events (plus the mutation-level\n * fallback so collab/replay-driven changes refresh too).\n *\n * Scope of this batch: switch / add / rename / delete. Drag-reorder, tab\n * colour, hide/unhide, and duplicate are richer host features deferred to\n * later parity batches (the reference app's SheetTabs has them).\n */\n\nimport { useEffect, useState, type CSSProperties, type KeyboardEvent } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { CasualSheetsAPI } from '../sheets/api';\n\ninterface SheetTab {\n id: string;\n name: string;\n hidden: boolean;\n}\n\ninterface SheetsSnapshot {\n tabs: SheetTab[];\n activeId: string | null;\n}\n\nconst EMPTY: SheetsSnapshot = { tabs: [], activeId: null };\n\n/** Sheet-list mutations that must refresh the strip even when they arrive via\n * the collab bridge's mutation-only replay (which bypasses facade events). */\nconst SHEET_LIST_MUTATIONS = new Set([\n 'sheet.mutation.insert-sheet',\n 'sheet.mutation.remove-sheet',\n 'sheet.mutation.set-worksheet-name',\n 'sheet.mutation.set-worksheet-order',\n 'sheet.mutation.set-worksheet-hidden',\n]);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFacade = any;\n\nfunction readSheets(api: CasualSheetsAPI): SheetsSnapshot {\n const wb = api.univer.getActiveWorkbook();\n if (!wb) return EMPTY;\n const tabs = wb.getSheets().map((s) => ({\n id: s.getSheetId(),\n name: s.getSheetName(),\n hidden: (s as AnyFacade).isSheetHidden?.() === true,\n }));\n return { tabs, activeId: wb.getActiveSheet()?.getSheetId() ?? null };\n}\n\nconst BAR_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'stretch',\n gap: 2,\n height: 30,\n flex: '0 0 auto',\n padding: '0 6px',\n borderTop: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.12))',\n background: 'var(--cs-chrome-bg, #f8f9fa)',\n font: 'inherit',\n fontSize: 13,\n overflowX: 'auto',\n overflowY: 'hidden',\n};\n\nconst ADD_BTN_STYLE: CSSProperties = {\n flex: '0 0 auto',\n width: 28,\n border: 'none',\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n cursor: 'pointer',\n fontSize: 18,\n lineHeight: 1,\n borderRadius: 4,\n};\n\nconst RENAME_INPUT_STYLE: CSSProperties = {\n height: 22,\n alignSelf: 'center',\n padding: '0 6px',\n border: '1px solid var(--cs-chrome-active-fg, #0e7490)',\n borderRadius: 4,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n width: 120,\n};\n\nconst MENU_STYLE: CSSProperties = {\n position: 'fixed',\n zIndex: 1000,\n minWidth: 140,\n padding: 4,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n borderRadius: 8,\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.16)',\n};\n\nconst MENU_ITEM_STYLE: CSSProperties = {\n display: 'block',\n width: '100%',\n textAlign: 'left',\n height: 28,\n padding: '0 10px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n};\n\nexport interface SheetTabsProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function SheetTabs({ api }: SheetTabsProps) {\n const [{ tabs, activeId }, setSnapshot] = useState<SheetsSnapshot>(EMPTY);\n // Inline-rename target sheet id (null = not renaming) + its draft text.\n const [renaming, setRenaming] = useState<string | null>(null);\n const [draft, setDraft] = useState('');\n // Right-click context menu: anchor + target sheet id.\n const [menu, setMenu] = useState<{ x: number; y: number; sheetId: string } | null>(null);\n\n useEffect(() => {\n if (!api) return;\n const refresh = () => setSnapshot(readSheets(api));\n refresh();\n const f = api.univer as AnyFacade;\n const subs: Array<{ dispose(): void }> = [];\n try {\n subs.push(\n f.addEvent(f.Event.SheetCreated, refresh),\n f.addEvent(f.Event.SheetDeleted, refresh),\n f.addEvent(f.Event.SheetNameChanged, refresh),\n f.addEvent(f.Event.ActiveSheetChanged, refresh),\n f.addEvent(f.Event.SheetMoved, refresh),\n // Mutation-level fallback — catches collab/replay-driven changes that\n // don't emit the higher-level facade events.\n f.addEvent(f.Event.CommandExecuted, (e: { id?: string }) => {\n if (e?.id && SHEET_LIST_MUTATIONS.has(e.id)) refresh();\n }),\n );\n // Whole-unit swaps (loadSnapshot / File→Open) don't fire SheetCreated;\n // refresh a tick after the new unit is wired in.\n if (typeof f.onUniverSheetCreated === 'function') {\n subs.push(f.onUniverSheetCreated(() => queueMicrotask(refresh)));\n }\n } catch {\n /* facade event surface differs — the initial read still populated tabs */\n }\n return () => {\n for (const s of subs) s?.dispose?.();\n };\n }, [api]);\n\n // Close the context menu on any outside interaction.\n useEffect(() => {\n if (!menu) return;\n const close = () => setMenu(null);\n window.addEventListener('pointerdown', close);\n window.addEventListener('keydown', close);\n return () => {\n window.removeEventListener('pointerdown', close);\n window.removeEventListener('keydown', close);\n };\n }, [menu]);\n\n if (!api) {\n return <div style={BAR_STYLE} data-testid=\"casual-sheets-tabs\" />;\n }\n\n const visible = tabs.filter((t) => !t.hidden);\n const wb = () => api.univer.getActiveWorkbook();\n\n const switchTo = (id: string) => {\n if (id === activeId) return;\n wb()?.setActiveSheet(id);\n };\n\n const addSheet = () => {\n const created = (wb() as AnyFacade)?.insertSheet?.();\n created?.activate?.();\n };\n\n const startRename = (tab: SheetTab) => {\n setMenu(null);\n setRenaming(tab.id);\n setDraft(tab.name);\n };\n\n const commitRename = () => {\n const id = renaming;\n setRenaming(null);\n if (!id) return;\n const name = draft.trim();\n if (!name) return;\n const sheet = (wb() as AnyFacade)?.getSheetBySheetId?.(id);\n if (sheet && sheet.getSheetName?.() !== name) sheet.setName?.(name);\n };\n\n const deleteSheet = (id: string) => {\n setMenu(null);\n // Excel keeps at least one visible sheet — never delete the last one.\n if (visible.length <= 1) return;\n (wb() as AnyFacade)?.deleteSheet?.(id);\n };\n\n const onRenameKey = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n commitRename();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setRenaming(null);\n }\n };\n\n return (\n <div style={BAR_STYLE} data-testid=\"casual-sheets-tabs\" role=\"tablist\">\n {visible.map((tab) => {\n const active = tab.id === activeId;\n if (renaming === tab.id) {\n return (\n <input\n key={tab.id}\n autoFocus\n style={RENAME_INPUT_STYLE}\n value={draft}\n data-testid=\"cs-tab-rename-input\"\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onRenameKey}\n onBlur={commitRename}\n />\n );\n }\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n data-testid={`cs-tab-${tab.id}`}\n data-active={active || undefined}\n title={tab.name}\n style={{\n flex: '0 0 auto',\n maxWidth: 160,\n padding: '0 12px',\n border: 'none',\n borderTop: active\n ? '2px solid var(--cs-chrome-active-fg, #0e7490)'\n : '2px solid transparent',\n background: active ? 'var(--cs-chrome-input-bg, #fff)' : 'transparent',\n color: active\n ? 'var(--cs-chrome-active-fg, #0e7490)'\n : 'var(--cs-chrome-fg, #201f1e)',\n fontWeight: active ? 600 : 400,\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n // mousedown keeps the grid from stealing focus mid-switch.\n onMouseDown={(e) => {\n e.preventDefault();\n switchTo(tab.id);\n }}\n onDoubleClick={() => startRename(tab)}\n onContextMenu={(e) => {\n e.preventDefault();\n setMenu({ x: e.clientX, y: e.clientY, sheetId: tab.id });\n }}\n >\n {tab.name}\n </button>\n );\n })}\n <button\n type=\"button\"\n style={ADD_BTN_STYLE}\n aria-label=\"Add sheet\"\n title=\"Add sheet\"\n data-testid=\"cs-tab-add\"\n onMouseDown={(e) => {\n e.preventDefault();\n addSheet();\n }}\n >\n +\n </button>\n\n {menu &&\n createPortal(\n <div\n // Portaled to <body> so it escapes the tab strip's stacking context\n // (otherwise the fixed menu renders BEHIND the status bar below the\n // tabs). `translateY(-100%)` opens it UPWARD from the click since the\n // tab strip sits at the bottom of the editor.\n style={{ ...MENU_STYLE, left: menu.x, top: menu.y, transform: 'translateY(-100%)' }}\n data-testid=\"cs-tab-menu\"\n role=\"menu\"\n // Keep clicks inside the menu from closing it via the window handler.\n onPointerDown={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n style={MENU_ITEM_STYLE}\n data-testid=\"cs-tab-menu-rename\"\n onMouseDown={(e) => {\n e.preventDefault();\n const tab = tabs.find((t) => t.id === menu.sheetId);\n if (tab) startRename(tab);\n }}\n >\n Rename\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n style={{\n ...MENU_ITEM_STYLE,\n opacity: visible.length <= 1 ? 0.5 : 1,\n cursor: visible.length <= 1 ? 'not-allowed' : 'pointer',\n }}\n data-testid=\"cs-tab-menu-delete\"\n onMouseDown={(e) => {\n e.preventDefault();\n deleteSheet(menu.sheetId);\n }}\n >\n Delete\n </button>\n </div>,\n document.body,\n )}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * FindReplace — a custom find/replace dialog for `<CasualSheets chrome>`.\n *\n * Univer's own find-replace dialog doesn't render in the SDK's headless mount\n * (it needs Univer's UI/overlay layer, which is dormant when header/toolbar/\n * footer are off), so the chrome ships its own — driven purely through the\n * facade: search reads the active sheet's `cellData` from `getSnapshot()`,\n * navigation `activate()`s the matching cell, and replace `setValue()`s it.\n *\n * Opens on Ctrl/Cmd+F (find) or Ctrl/Cmd+H (replace) while the editor has focus;\n * Escape closes. Self-managing — just mount it in the chrome with the live api.\n */\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n} from 'react';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\n\ninterface Match {\n row: number;\n col: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnySnapshot = any;\n\n/** Collect matches on the active sheet, in row-major order. Searches each\n * cell's value (`v`) and formula (`f`) text. */\nfunction findMatches(api: CasualSheetsAPI, query: string, matchCase: boolean): Match[] {\n if (!query) return [];\n const snap = api.getSnapshot() as AnySnapshot;\n const sheetId =\n api.getSelection()?.sheetId ?? api.univer.getActiveWorkbook()?.getActiveSheet()?.getSheetId();\n const sheet = sheetId ? snap?.sheets?.[sheetId] : undefined;\n const cellData = sheet?.cellData as Record<string, Record<string, AnySnapshot>> | undefined;\n if (!cellData) return [];\n const needle = matchCase ? query : query.toLowerCase();\n const out: Match[] = [];\n for (const rk of Object.keys(cellData).sort((a, b) => Number(a) - Number(b))) {\n const rowObj = cellData[rk];\n if (!rowObj) continue;\n for (const ck of Object.keys(rowObj).sort((a, b) => Number(a) - Number(b))) {\n const cell = rowObj[ck];\n if (!cell) continue;\n const hay = `${cell.v ?? ''}${cell.f ? ` ${cell.f}` : ''}`;\n const cmp = matchCase ? hay : hay.toLowerCase();\n if (cmp.includes(needle)) out.push({ row: Number(rk), col: Number(ck) });\n }\n }\n return out;\n}\n\nconst WRAP_STYLE: CSSProperties = {\n position: 'absolute',\n top: 8,\n right: 12,\n zIndex: 1100,\n width: 320,\n padding: 10,\n borderRadius: 8,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 8px 28px rgba(0,0,0,0.18)',\n font: 'inherit',\n fontSize: 13,\n color: 'var(--cs-chrome-fg, #201f1e)',\n};\n\nconst ROW_STYLE: CSSProperties = { display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 };\n\nconst INPUT_STYLE: CSSProperties = {\n flex: '1 1 auto',\n height: 26,\n padding: '0 8px',\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 4,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n boxSizing: 'border-box',\n};\n\nconst BTN_STYLE: CSSProperties = {\n height: 26,\n padding: '0 10px',\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 4,\n background: 'var(--cs-chrome-bg, #f3f5f8)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 12,\n cursor: 'pointer',\n};\n\nconst ICON_BTN_STYLE: CSSProperties = {\n width: 26,\n height: 26,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 4,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n cursor: 'pointer',\n padding: 0,\n};\n\nexport interface FindReplaceProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n /**\n * Imperative open trigger from the dialog host. Bump this counter to open the\n * panel (e.g. when `openDialog('find-replace')` is called from a menu item).\n * The panel still self-opens on Ctrl/Cmd+F·H independently.\n */\n openSignal?: number;\n /** When the host opens it via `openSignal`, start in replace mode. */\n openInReplaceMode?: boolean;\n}\n\nexport function FindReplace({ api, openSignal, openInReplaceMode }: FindReplaceProps) {\n const [open, setOpen] = useState(false);\n const [showReplace, setShowReplace] = useState(false);\n const [query, setQuery] = useState('');\n const [replaceText, setReplaceText] = useState('');\n const [matchCase, setMatchCase] = useState(false);\n const [idx, setIdx] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Open on Ctrl/Cmd+F (find) / Ctrl/Cmd+H (replace), close on Escape.\n useEffect(() => {\n const onKey = (e: globalThis.KeyboardEvent) => {\n const mod = e.metaKey || e.ctrlKey;\n if (mod && (e.key === 'f' || e.key === 'F')) {\n e.preventDefault();\n setShowReplace(false);\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n } else if (mod && (e.key === 'h' || e.key === 'H')) {\n e.preventDefault();\n setShowReplace(true);\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n }\n };\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, []);\n\n // Host-driven open (openDialog('find-replace')). `openSignal === undefined`\n // means \"never opened by the host\"; any defined value opens (and re-opening\n // bumps the counter). Skip the initial undefined→defined? No — only react when\n // a defined signal arrives.\n const lastSignal = useRef<number | undefined>(undefined);\n useEffect(() => {\n if (openSignal === undefined) return;\n if (lastSignal.current === openSignal) return;\n lastSignal.current = openSignal;\n setShowReplace(!!openInReplaceMode);\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n }, [openSignal, openInReplaceMode]);\n\n const matches = useMemo(\n () => (api && open && query ? findMatches(api, query, matchCase) : []),\n [api, open, query, matchCase],\n );\n\n // Keep idx in range as matches change.\n useEffect(() => {\n setIdx((i) => (matches.length === 0 ? 0 : Math.min(i, matches.length - 1)));\n }, [matches.length]);\n\n if (!open || !api) return null;\n\n const go = (delta: number) => {\n if (matches.length === 0) return;\n const next = (idx + delta + matches.length) % matches.length;\n setIdx(next);\n activate(matches[next]);\n };\n\n const activate = (m: Match) => {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (sheet?.getRange(m.row, m.col) as any)?.activate?.();\n };\n\n const replaceOne = () => {\n if (matches.length === 0) return;\n const m = matches[Math.min(idx, matches.length - 1)];\n replaceAt(m);\n // Matches recompute via the query memo on next render; advance stays put.\n };\n\n const replaceAt = (m: Match) => {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sheet) return;\n const cur = String(sheet.getRange(m.row, m.col).getValue?.() ?? '');\n const next = replaceInString(cur, query, replaceText, matchCase);\n if (next !== cur) sheet.getRange(m.row, m.col).setValue(next);\n };\n\n const replaceAll = () => {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sheet) return;\n for (const m of matches) {\n const cur = String(sheet.getRange(m.row, m.col).getValue?.() ?? '');\n const next = replaceInString(cur, query, replaceText, matchCase);\n if (next !== cur) sheet.getRange(m.row, m.col).setValue(next);\n }\n };\n\n const onInputKey = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n go(e.shiftKey ? -1 : 1);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setOpen(false);\n }\n };\n\n const count = matches.length;\n const position = count === 0 ? 0 : Math.min(idx, count - 1) + 1;\n\n return (\n <div\n style={WRAP_STYLE}\n data-testid=\"cs-find-replace\"\n role=\"dialog\"\n aria-label=\"Find and replace\"\n >\n <div style={ROW_STYLE}>\n <input\n ref={inputRef}\n type=\"text\"\n aria-label=\"Find\"\n placeholder=\"Find\"\n data-testid=\"cs-find-input\"\n style={INPUT_STYLE}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={onInputKey}\n />\n <span\n style={{ minWidth: 54, textAlign: 'center', color: 'var(--cs-chrome-muted, #6b7280)' }}\n data-testid=\"cs-find-count\"\n >\n {position}/{count}\n </span>\n <button\n type=\"button\"\n style={ICON_BTN_STYLE}\n aria-label=\"Previous match\"\n data-testid=\"cs-find-prev\"\n onMouseDown={(e) => {\n e.preventDefault();\n go(-1);\n }}\n >\n <Icon name=\"keyboard_arrow_up\" size={18} />\n </button>\n <button\n type=\"button\"\n style={ICON_BTN_STYLE}\n aria-label=\"Next match\"\n data-testid=\"cs-find-next\"\n onMouseDown={(e) => {\n e.preventDefault();\n go(1);\n }}\n >\n <Icon name=\"keyboard_arrow_down\" size={18} />\n </button>\n <button\n type=\"button\"\n style={ICON_BTN_STYLE}\n aria-label=\"Close\"\n data-testid=\"cs-find-close\"\n onMouseDown={(e) => {\n e.preventDefault();\n setOpen(false);\n }}\n >\n <Icon name=\"close\" size={18} />\n </button>\n </div>\n\n {showReplace && (\n <div style={ROW_STYLE}>\n <input\n type=\"text\"\n aria-label=\"Replace with\"\n placeholder=\"Replace with\"\n data-testid=\"cs-replace-input\"\n style={INPUT_STYLE}\n value={replaceText}\n onChange={(e) => setReplaceText(e.target.value)}\n />\n <button\n type=\"button\"\n style={BTN_STYLE}\n data-testid=\"cs-replace-one\"\n onMouseDown={(e) => {\n e.preventDefault();\n replaceOne();\n }}\n >\n Replace\n </button>\n <button\n type=\"button\"\n style={BTN_STYLE}\n data-testid=\"cs-replace-all\"\n onMouseDown={(e) => {\n e.preventDefault();\n replaceAll();\n }}\n >\n All\n </button>\n </div>\n )}\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>\n <label style={{ display: 'inline-flex', alignItems: 'center', gap: 4, cursor: 'pointer' }}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-find-match-case\"\n checked={matchCase}\n onChange={(e) => setMatchCase(e.target.checked)}\n />\n Match case\n </label>\n {!showReplace && (\n <button\n type=\"button\"\n style={{\n ...BTN_STYLE,\n marginLeft: 'auto',\n border: 'none',\n background: 'transparent',\n color: 'var(--cs-chrome-active-fg, #0e7490)',\n }}\n data-testid=\"cs-find-toggle-replace\"\n onMouseDown={(e) => {\n e.preventDefault();\n setShowReplace(true);\n }}\n >\n Replace…\n </button>\n )}\n </div>\n </div>\n );\n}\n\n/** Replace all occurrences of `query` in `text` (case-(in)sensitive). */\nfunction replaceInString(\n text: string,\n query: string,\n replacement: string,\n matchCase: boolean,\n): string {\n if (!query) return text;\n if (matchCase) return text.split(query).join(replacement);\n // Case-insensitive: walk and rebuild preserving non-matched casing.\n const lower = text.toLowerCase();\n const needle = query.toLowerCase();\n let out = '';\n let i = 0;\n while (i < text.length) {\n if (lower.startsWith(needle, i)) {\n out += replacement;\n i += needle.length;\n } else {\n out += text[i];\n i += 1;\n }\n }\n return out;\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * ChromeTop — the chrome ABOVE the grid (menu bar + toolbar + formula bar).\n * Lives in the `@casualoffice/sheets/chrome` entry, lazy-imported by\n * `<CasualSheets>` only when `chrome !== 'none'` so bare-grid consumers (the\n * default; the apps/web host renders chrome=\"none\" + its own shell) never bundle\n * the chrome JS.\n *\n * Owns the dialog host: wraps MenuBar/Toolbar in `<DialogProvider>` so their\n * controls call `openDialog(kind)` and the SDK's built-in dialogs (Format Cells,\n * …) open by default — a host overrides them via `extensions.dialogs`. The\n * self-managing FindReplace panel is mounted here and bridged to\n * `openDialog('find-replace')` via an open signal.\n */\nimport { useCallback, useState } from 'react';\nimport { MenuBar } from './MenuBar';\nimport { Toolbar } from './Toolbar';\nimport { FormulaBar } from './FormulaBar';\nimport { FindReplace } from './FindReplace';\nimport { DialogProvider, type DialogKind } from './dialog-context';\nimport type { ChromeExtensions } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\n\nexport interface ChromeTopProps {\n api: CasualSheetsAPI | null;\n /** Hide a control/group + block its command when its key is false. */\n features?: Record<string, boolean>;\n /**\n * Legacy host hook — route dialog-backed controls to the host instead of the\n * SDK built-in. Kept for back-compat; prefer `extensions.dialogs`.\n */\n onDialogRequest?: (kind: DialogKind, context?: unknown) => void;\n /** Kinds the host owns via `onDialogRequest` despite an SDK built-in. */\n hostOwnedDialogs?: DialogKind[];\n /** Host chrome extensions: custom toolbar/menu items, dialogs, panels. */\n extensions?: ChromeExtensions;\n}\n\nexport function ChromeTop({\n api,\n features,\n onDialogRequest,\n hostOwnedDialogs,\n extensions,\n}: ChromeTopProps) {\n // FindReplace is a self-managing panel; the dialog host opens it by bumping\n // this signal. (Ctrl/Cmd+F·H still open it directly.)\n const [findSignal, setFindSignal] = useState(0);\n const [findReplaceMode, setFindReplaceMode] = useState(false);\n const openFindReplace = useCallback((replaceMode: boolean) => {\n setFindReplaceMode(replaceMode);\n setFindSignal((n) => n + 1);\n }, []);\n\n return (\n <DialogProvider\n api={api}\n extensions={extensions}\n onDialogRequest={onDialogRequest}\n hostOwnedDialogs={hostOwnedDialogs}\n onOpenFindReplace={openFindReplace}\n >\n <MenuBar api={api} features={features} extensions={extensions} />\n <Toolbar api={api} features={features} extensions={extensions} />\n <FormulaBar api={api} />\n <FindReplace\n api={api}\n openSignal={findSignal || undefined}\n openInReplaceMode={findReplaceMode}\n />\n </DialogProvider>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * ChromeBottom — the chrome BELOW the grid (sheet tabs + status bar).\n * Lazy-imported with ChromeTop (see ChromeTop).\n *\n * NOTE: Find & Replace is mounted in ChromeTop (inside the DialogProvider, so\n * the dialog host can open it via `openDialog('find-replace')`). It is NOT\n * mounted here — two `<FindReplace>` instances both bound Ctrl+F and rendered\n * two `cs-find-replace` dialogs (strict-mode violation in the chrome e2e).\n */\nimport { SheetTabs } from './SheetTabs';\nimport { StatusBar } from './StatusBar';\nimport type { CasualSheetsAPI } from '../sheets/api';\n\nexport function ChromeBottom({ api }: { api: CasualSheetsAPI | null }) {\n return (\n <>\n <SheetTabs api={api} />\n <StatusBar api={api} />\n </>\n );\n}\n"],"mappings":"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","names":["import_react","import_core","import_jsx_runtime","import_react","import_jsx_runtime","ROW_STYLE","BTN_STYLE","POPOVER_STYLE","import_react","import_jsx_runtime","ROW_STYLE","BTN_STYLE","POPOVER_STYLE","ITEM_STYLE","import_react","import_react","import_react","import_jsx_runtime","first","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","readActiveStyle","FONT_FAMILIES","NUMBER_FORMAT_PATTERNS","NUMBER_FORMAT_OPTIONS","detectFormatKey","BTN_STYLE","import_react","import_core","import_react","import_core","import_jsx_runtime","onKeyDown","import_jsx_runtime","colToLetters","BAR_STYLE","import_react","import_core","import_jsx_runtime","BAR_STYLE","import_react","import_core","import_jsx_runtime","activeRange","NUMBER_FORMAT_PATTERNS","BAR_STYLE","ITEM_STYLE","import_react","import_react_dom","import_jsx_runtime","BAR_STYLE","MENU_STYLE","MENU_ITEM_STYLE","import_react","import_jsx_runtime","ROW_STYLE","INPUT_STYLE","BTN_STYLE","import_react","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../src/chrome/index.ts","../src/chrome/Toolbar.tsx","../src/chrome/Icon.tsx","../src/chrome/fonts.ts","../src/chrome/ColorPicker.tsx","../src/chrome/BordersPicker.tsx","../src/chrome/AutoSumPicker.tsx","../src/chrome/dialog-context.tsx","../src/chrome/FormatCellsDialog.tsx","../src/chrome/Dialog.tsx","../src/chrome/dialog-styles.ts","../src/chrome/DataValidationDialog.tsx","../src/chrome/ConditionalFormattingDialog.tsx","../src/chrome/CustomSortDialog.tsx","../src/chrome/PasteSpecialDialog.tsx","../src/chrome/InsertFunctionDialog.tsx","../src/chrome/NameManagerDialog.tsx","../src/chrome/InsertCellsDialog.tsx","../src/chrome/DeleteCellsDialog.tsx","../src/chrome/GoalSeekDialog.tsx","../src/chrome/InsertChartDialog.tsx","../src/chrome/InsertSparklineDialog.tsx","../src/chrome/InsertPivotDialog.tsx","../src/chrome/FormulaBar.tsx","../src/chrome/NameBox.tsx","../src/chrome/StatusBar.tsx","../src/chrome/MenuBar.tsx","../src/chrome/openExternal.ts","../src/univer/lazy-plugins.ts","../src/chrome/menu-model.ts","../src/chrome/SheetTabs.tsx","../src/chrome/FindReplace.tsx","../src/chrome/ChromeTop.tsx","../src/chrome/ChromeBottom.tsx"],"sourcesContent":["/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Chrome — the Office shell as slot components for `<CasualSheets chrome>`.\n *\n * First slice (SDK_MIGRATION_PIPELINE Phase 1 step 2): a minimal built-in\n * `Toolbar`. The rich shell (FormulaBar, MenuBar, TitleBar, StatusBar) lifts\n * from `apps/web/src/shell/` here in later slices, behind `chrome=\"full\"`.\n */\nexport { Toolbar, type ToolbarProps } from './Toolbar';\nexport { FormulaBar, type FormulaBarProps } from './FormulaBar';\nexport { StatusBar, type StatusBarProps } from './StatusBar';\nexport { Icon, type IconProps } from './Icon';\nexport { ensureChromeFonts } from './fonts';\nexport { ColorPicker, type ColorPickerProps } from './ColorPicker';\nexport { BordersPicker, type BordersPickerProps } from './BordersPicker';\nexport { AutoSumPicker, type AutoSumPickerProps } from './AutoSumPicker';\nexport { MenuBar, type MenuBarProps, type MenuDialogKind } from './MenuBar';\nexport { NameBox, type NameBoxProps } from './NameBox';\nexport { SheetTabs, type SheetTabsProps } from './SheetTabs';\nexport { FindReplace, type FindReplaceProps } from './FindReplace';\n// Dialog foundation: the modal primitive, the dialog host/registry, the\n// extension API, and the built-in reference dialogs.\nexport { Dialog, type DialogProps } from './Dialog';\nexport { FormatCellsDialog } from './FormatCellsDialog';\nexport {\n DialogProvider,\n useDialogs,\n hasBuiltInDialog,\n type DialogKind,\n type DialogController,\n type DialogProviderProps,\n} from './dialog-context';\nexport type {\n ChromeExtensions,\n ToolbarExtension,\n MenuExtension,\n PanelExtension,\n DialogExtension,\n DialogComponentProps,\n PanelComponentProps,\n MenuTarget,\n} from './extensions';\n// Lazy-loaded shells: chrome above (ChromeTop) and below (ChromeBottom) the grid,\n// imported on demand by `<CasualSheets>` via the `@casualoffice/sheets/chrome`\n// subpath so `chrome=\"none\"` consumers don't bundle the chrome JS.\nexport { ChromeTop } from './ChromeTop';\nexport { ChromeBottom } from './ChromeBottom';\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Toolbar — the rich built-in formatting toolbar for `<CasualSheets chrome>`.\n *\n * Drives the editor purely through `CasualSheetsAPI.executeCommand` + the FUniver\n * facade (`api.univer`), with Material Symbols icons + design-system tokens. No\n * app context, no title/logo row (the host frames the editor with its own bar).\n * Commands grouped with dividers, Office-style — mirrors the app shell's\n * `apps/web/src/shell/Toolbar.tsx` + `RibbonControls.tsx` group/order/icons,\n * replicating `home-tab-actions.ts` logic inline against `api` / `api.univer`.\n *\n * Covered (parity with the app's Home tab):\n * history (undo/redo) · clipboard (paste/cut/copy/paste-values) · format\n * painter · font family/size + grow/shrink · bold/italic/underline/strike ·\n * text + fill colour (ColorPicker) · borders (BordersPicker) · horizontal +\n * vertical align · wrap · merge/unmerge · number-format dropdown +\n * currency/percent/decimals · AutoSum (AutoSumPicker) · clear formatting.\n *\n * Reflects the active cell — toggles light up, dropdowns show the current font /\n * number format — via a command-execution subscription.\n *\n * Dialog-only controls (Format Cells, Insert Chart, PivotTable) have no SDK\n * dialog: when the host passes `onDialogRequest` they render and call it so the\n * host can render its own; without it, they are omitted entirely (no fake\n * dialog). Each group/control can also be hidden via the `features` flag map.\n */\n\nimport { useEffect, useState, type CSSProperties } from 'react';\nimport { ICommandService } from '@univerjs/core';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\nimport { ensureChromeFonts } from './fonts';\nimport { ColorPicker } from './ColorPicker';\nimport { BordersPicker } from './BordersPicker';\nimport { AutoSumPicker } from './AutoSumPicker';\nimport { useDialogs } from './dialog-context';\nimport type { ChromeExtensions, ToolbarExtension } from './extensions';\n\ninterface ActiveStyle {\n bold: boolean;\n italic: boolean;\n underline: boolean;\n strike: boolean;\n ht: number; // HorizontalAlign of the active cell (0 = unset)\n vt: number; // VerticalAlign of the active cell (0 = unset)\n tb: number; // WrapStrategy of the active cell (0 = unset, 3 = wrap)\n ff: string;\n fs: number;\n nf: string; // number-format pattern ('' = General)\n}\n\nconst NO_STYLE: ActiveStyle = {\n bold: false,\n italic: false,\n underline: false,\n strike: false,\n ht: 0,\n vt: 0,\n tb: 0,\n ff: '',\n fs: 0,\n nf: '',\n};\n\nfunction readActiveStyle(api: CasualSheetsAPI): ActiveStyle {\n const sel = api.getSelection();\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sel || !sheet) return NO_STYLE;\n const range = sheet.getRange(sel.range.startRow, sel.range.startColumn);\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const s = (range.getCellStyleData?.() ?? null) as any;\n return {\n bold: s?.bl === 1,\n italic: s?.it === 1,\n underline: s?.ul?.s === 1,\n strike: s?.st?.s === 1,\n ht: typeof s?.ht === 'number' ? s.ht : 0,\n vt: typeof s?.vt === 'number' ? s.vt : 0,\n tb: typeof s?.tb === 'number' ? s.tb : 0,\n ff: typeof s?.ff === 'string' ? s.ff : '',\n fs: typeof s?.fs === 'number' ? s.fs : 0,\n nf: typeof s?.n?.pattern === 'string' ? s.n.pattern : '',\n };\n}\n\nconst FONT_FAMILIES = [\n 'Calibri',\n 'Arial',\n 'Helvetica',\n 'Inter',\n 'Times New Roman',\n 'Georgia',\n 'Verdana',\n 'Courier New',\n 'JetBrains Mono',\n];\nconst FONT_SIZES = [8, 9, 10, 11, 12, 14, 16, 18, 20, 24, 28, 32, 36, 48, 72];\n\n/**\n * Number-format presets, mirroring the app's `home-tab-actions`\n * `NUMBER_FORMAT_PATTERNS`. The dropdown applies a pattern via the facade\n * (`FRange.setNumberFormat`, a runtime numfmt-facade extension) so it lands as a\n * normal numfmt mutation — same path the app uses.\n */\nconst NUMBER_FORMAT_PATTERNS = {\n general: '',\n integer: '#,##0',\n number: '#,##0.00',\n currency: '\"$\"#,##0.00',\n accounting: '_(\"$\"* #,##0.00_);_(\"$\"* (#,##0.00);_(\"$\"* \"-\"??_);_(@_)',\n percent: '0.00%',\n date: 'yyyy-mm-dd',\n time: 'hh:mm:ss',\n scientific: '0.00E+00',\n text: '@',\n} as const;\n\ntype NumberFormatKey = keyof typeof NUMBER_FORMAT_PATTERNS;\n\nconst NUMBER_FORMAT_OPTIONS: { value: NumberFormatKey; label: string }[] = [\n { value: 'general', label: 'General' },\n { value: 'integer', label: 'Number (no decimals)' },\n { value: 'number', label: 'Number (2 decimals)' },\n { value: 'currency', label: 'Currency' },\n { value: 'accounting', label: 'Accounting' },\n { value: 'percent', label: 'Percent' },\n { value: 'date', label: 'Date (yyyy-mm-dd)' },\n { value: 'time', label: 'Time (hh:mm:ss)' },\n { value: 'scientific', label: 'Scientific' },\n { value: 'text', label: 'Text' },\n];\n\nfunction detectFormatKey(pattern: string): NumberFormatKey {\n for (const k of Object.keys(NUMBER_FORMAT_PATTERNS) as NumberFormatKey[]) {\n if (NUMBER_FORMAT_PATTERNS[k] === pattern) return k;\n }\n return 'general';\n}\n\ninterface ToolbarAction {\n id: string;\n label: string;\n command: string;\n icon: string;\n params?: object;\n /** Feature key gating this action; defaults to the owning group's key. */\n feature?: string;\n}\n\n/**\n * Each entry is a feature-gated group. The `feature` key lets a host hide the\n * whole group (and per-action `feature` keys gate individual buttons). Order +\n * icons mirror the app shell's Home tab.\n *\n * HorizontalAlign enum (@univerjs/core): LEFT=1, CENTER=2, RIGHT=3.\n * VerticalAlign enum (@univerjs/core): TOP=1, MIDDLE=2, BOTTOM=3.\n * WrapStrategy enum (@univerjs/core): OVERFLOW=1, CLIP=2, WRAP=3.\n *\n * Clipboard command ids: `univer.command.{paste,cut,copy}` (matches\n * `home-tab-actions.ts`). Paste values-only uses the base paste command with a\n * predefined hook `value` (`special-paste-value`), same as the app's\n * `pasteSpecial`.\n */\nconst GROUPS: { feature: string; actions: ToolbarAction[] }[] = [\n {\n feature: 'history',\n actions: [\n { id: 'undo', label: 'Undo (Ctrl+Z)', command: 'univer.command.undo', icon: 'undo' },\n { id: 'redo', label: 'Redo (Ctrl+Y)', command: 'univer.command.redo', icon: 'redo' },\n ],\n },\n {\n feature: 'clipboard',\n actions: [\n {\n id: 'paste',\n label: 'Paste (Ctrl+V)',\n command: 'univer.command.paste',\n icon: 'content_paste',\n },\n { id: 'cut', label: 'Cut (Ctrl+X)', command: 'univer.command.cut', icon: 'content_cut' },\n { id: 'copy', label: 'Copy (Ctrl+C)', command: 'univer.command.copy', icon: 'content_copy' },\n {\n id: 'paste-values',\n label: 'Paste values only',\n command: 'univer.command.paste',\n icon: 'content_paste_go',\n params: { value: 'special-paste-value' },\n },\n ],\n },\n {\n feature: 'format-painter',\n actions: [\n {\n id: 'format-painter',\n label: 'Format Painter',\n command: 'sheet.command.set-once-format-painter',\n icon: 'format_paint',\n },\n ],\n },\n {\n feature: 'font-style',\n actions: [\n {\n id: 'bold',\n label: 'Bold (Ctrl+B)',\n command: 'sheet.command.set-range-bold',\n icon: 'format_bold',\n },\n {\n id: 'italic',\n label: 'Italic (Ctrl+I)',\n command: 'sheet.command.set-range-italic',\n icon: 'format_italic',\n },\n {\n id: 'underline',\n label: 'Underline (Ctrl+U)',\n command: 'sheet.command.set-range-underline',\n icon: 'format_underlined',\n },\n {\n id: 'strikethrough',\n label: 'Strikethrough',\n command: 'sheet.command.set-range-stroke',\n icon: 'format_strikethrough',\n },\n ],\n },\n {\n feature: 'alignment',\n actions: [\n {\n id: 'align-left',\n label: 'Align left',\n command: 'sheet.command.set-horizontal-text-align',\n icon: 'format_align_left',\n params: { value: 1 },\n },\n {\n id: 'align-center',\n label: 'Align center',\n command: 'sheet.command.set-horizontal-text-align',\n icon: 'format_align_center',\n params: { value: 2 },\n },\n {\n id: 'align-right',\n label: 'Align right',\n command: 'sheet.command.set-horizontal-text-align',\n icon: 'format_align_right',\n params: { value: 3 },\n },\n {\n id: 'wrap-text',\n label: 'Wrap text',\n command: 'sheet.command.set-text-wrap',\n icon: 'wrap_text',\n params: { value: 3 },\n },\n ],\n },\n {\n feature: 'alignment',\n actions: [\n {\n id: 'align-top',\n label: 'Align top',\n command: 'sheet.command.set-vertical-text-align',\n icon: 'vertical_align_top',\n params: { value: 1 },\n },\n {\n id: 'align-middle',\n label: 'Align middle',\n command: 'sheet.command.set-vertical-text-align',\n icon: 'vertical_align_center',\n params: { value: 2 },\n },\n {\n id: 'align-bottom',\n label: 'Align bottom',\n command: 'sheet.command.set-vertical-text-align',\n icon: 'vertical_align_bottom',\n params: { value: 3 },\n },\n ],\n },\n {\n feature: 'merge',\n actions: [\n {\n id: 'merge',\n label: 'Merge cells',\n command: 'sheet.command.add-worksheet-merge-all',\n icon: 'cell_merge',\n },\n {\n id: 'unmerge',\n label: 'Unmerge cells',\n command: 'sheet.command.remove-worksheet-merge',\n icon: 'splitscreen_vertical_add',\n },\n ],\n },\n {\n feature: 'number',\n actions: [\n {\n id: 'currency',\n label: 'Currency format',\n command: 'sheet.command.numfmt.set.currency',\n icon: 'attach_money',\n },\n {\n id: 'percent',\n label: 'Percent format',\n command: 'sheet.command.numfmt.set.percent',\n icon: 'percent',\n },\n {\n id: 'decimal-increase',\n label: 'Increase decimals',\n command: 'sheet.command.numfmt.add.decimal.command',\n icon: 'decimal_increase',\n },\n {\n id: 'decimal-decrease',\n label: 'Decrease decimals',\n command: 'sheet.command.numfmt.subtract.decimal.command',\n icon: 'decimal_decrease',\n },\n ],\n },\n {\n feature: 'clear-format',\n actions: [\n {\n id: 'clear-format',\n label: 'Clear formatting',\n command: 'sheet.command.clear-selection-format',\n icon: 'format_clear',\n },\n ],\n },\n];\n\nconst BAR_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n padding: '4px 8px',\n borderBottom: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-bg, #eef1f5)',\n flex: '0 0 auto',\n userSelect: 'none',\n flexWrap: 'wrap',\n};\n\nconst BTN_STYLE: CSSProperties = {\n width: 30,\n height: 30,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n padding: 0,\n};\n\nconst DIVIDER_STYLE: CSSProperties = {\n width: 1,\n height: 18,\n margin: '0 4px',\n background: 'var(--cs-chrome-border, #cdd3db)',\n flex: '0 0 auto',\n};\n\nconst SELECT_STYLE: CSSProperties = {\n height: 26,\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n padding: '0 4px',\n cursor: 'pointer',\n};\n\nexport interface ToolbarProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n /**\n * Per-control / per-group feature flags. A key set to `false` hides that\n * control or group; omitted keys default to enabled. Keys:\n * history · clipboard · format-painter · font · font-style · color ·\n * borders · alignment · merge · number · autosum · clear-format ·\n * format-cells · insert-chart · pivot-table\n */\n features?: Record<string, boolean>;\n /** Host chrome extensions — only `extensions.toolbar` is read here. */\n extensions?: ChromeExtensions;\n}\n\n/** A feature is on unless explicitly set to `false`. */\nfunction enabled(features: Record<string, boolean> | undefined, key: string): boolean {\n return features?.[key] !== false;\n}\n\n// Which actions reflect an active state, keyed off the active cell's style.\nfunction isActive(id: string, s: ActiveStyle): boolean {\n switch (id) {\n case 'bold':\n return s.bold;\n case 'italic':\n return s.italic;\n case 'underline':\n return s.underline;\n case 'strikethrough':\n return s.strike;\n case 'align-left':\n return s.ht === 1;\n case 'align-center':\n return s.ht === 2;\n case 'align-right':\n return s.ht === 3;\n case 'align-top':\n return s.vt === 1;\n case 'align-middle':\n return s.vt === 2;\n case 'align-bottom':\n return s.vt === 3;\n case 'wrap-text':\n return s.tb === 3;\n default:\n return false;\n }\n}\n\nexport function Toolbar({ api, features, extensions }: ToolbarProps) {\n const dialogs = useDialogs();\n const [active, setActive] = useState<ActiveStyle>(NO_STYLE);\n\n useEffect(() => {\n ensureChromeFonts();\n }, []);\n\n // Reflect the active cell: subscribe to command activity (covers selection\n // moves + style mutations) and re-read the style.\n useEffect(() => {\n if (!api) return;\n const refresh = () => setActive(readActiveStyle(api));\n refresh();\n const injector = (api.univer as unknown as { _injector?: { get(t: unknown): unknown } })\n ._injector;\n const cmd = injector?.get(ICommandService) as\n | { onCommandExecuted: (cb: () => void) => { dispose: () => void } }\n | undefined;\n const sub = cmd?.onCommandExecuted(() => refresh());\n return () => sub?.dispose();\n }, [api]);\n\n const dispatch = (command: string, params?: object) => void api?.executeCommand(command, params);\n\n /**\n * Apply a font size via the dedicated command (matches the app's\n * `set-range-fontsize`). Used by the size dropdown + grow/shrink.\n */\n const applyFontSize = (size: number) => {\n if (!Number.isFinite(size) || size <= 0) return;\n dispatch('sheet.command.set-range-fontsize', { value: size });\n };\n\n /**\n * Grow / shrink the active cell's font size by `delta`, mirroring the app's\n * `adjustFontSize` (read current off the active cell, fall back to 11, clamp\n * to [6, 72]). Reads the size we already track in `active`.\n */\n const adjustFontSize = (delta: number) => {\n const current = active.fs && active.fs > 0 ? active.fs : 11;\n const next = Math.max(6, Math.min(72, current + delta));\n if (next === current) return;\n applyFontSize(next);\n };\n\n /**\n * Apply a number-format pattern via the FUniver facade — `FRange.setNumberFormat`\n * is a runtime numfmt-facade extension (added via `FUniver.extend()`), so a\n * runtime cast is the cleanest way to reach it. Same approach as the app's\n * `home-tab-actions.setNumberFormat`.\n */\n const applyNumberFormat = (pattern: string) => {\n const sheet = api?.univer.getActiveWorkbook()?.getActiveSheet();\n const range = (sheet as unknown as { getActiveRange?: () => unknown })?.getActiveRange?.() as\n | { setNumberFormat?: (p: string) => unknown }\n | undefined;\n range?.setNumberFormat?.(pattern);\n };\n\n // Reflect current font in the dropdowns; surface a non-listed value too.\n const familyValue = active.ff || 'Calibri';\n const familyOptions =\n active.ff && !FONT_FAMILIES.includes(active.ff) ? [active.ff, ...FONT_FAMILIES] : FONT_FAMILIES;\n const sizeValue = active.fs || 11;\n const sizeOptions =\n active.fs && !FONT_SIZES.includes(active.fs) ? [active.fs, ...FONT_SIZES] : FONT_SIZES;\n const numberFormatValue = detectFormatKey(active.nf);\n\n const renderActionButton = (a: ToolbarAction) => {\n const on = isActive(a.id, active);\n const baseBg = on ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent';\n return (\n <button\n key={a.id}\n type=\"button\"\n title={a.label}\n aria-label={a.label}\n aria-pressed={on}\n data-action={a.id}\n data-testid={`cs-${a.id}`}\n data-active={on ? 'true' : undefined}\n disabled={!api}\n style={{\n ...BTN_STYLE,\n background: baseBg,\n color: on ? 'var(--cs-chrome-active-fg, #0e7490)' : BTN_STYLE.color,\n }}\n // mousedown (not click) so the grid's selection isn't lost first.\n onMouseDown={(e) => {\n e.preventDefault();\n dispatch(a.command, a.params);\n }}\n onMouseEnter={(e) => {\n if (!on) e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = baseBg;\n }}\n >\n <Icon name={a.icon} size={20} />\n </button>\n );\n };\n\n // A plain (non-command) icon button — used for grow/shrink + dialog requests.\n const renderIconButton = (\n id: string,\n label: string,\n icon: string,\n onPress: () => void,\n testid: string,\n ) => (\n <button\n key={id}\n type=\"button\"\n title={label}\n aria-label={label}\n data-action={id}\n data-testid={testid}\n disabled={!api}\n style={BTN_STYLE}\n onMouseDown={(e) => {\n e.preventDefault();\n onPress();\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n >\n <Icon name={icon} size={20} />\n </button>\n );\n\n // Render the static command groups, skipping any whose feature is off and any\n // group left empty after per-action filtering. A leading divider separates a\n // group from whatever rendered before it.\n let firstGroupRendered = false;\n const groupNodes = GROUPS.map((group, gi) => {\n if (!enabled(features, group.feature)) return null;\n const visible = group.actions.filter((a) => enabled(features, a.feature ?? group.feature));\n if (visible.length === 0) return null;\n const showDivider = firstGroupRendered;\n firstGroupRendered = true;\n return (\n <span key={gi} style={{ display: 'inline-flex', alignItems: 'center' }}>\n {showDivider && <span style={DIVIDER_STYLE} aria-hidden />}\n {visible.map(renderActionButton)}\n </span>\n );\n });\n\n const showFont = enabled(features, 'font');\n const showColor = enabled(features, 'color');\n const showBorders = enabled(features, 'borders');\n const showAutoSum = enabled(features, 'autosum');\n const showNumberDropdown = enabled(features, 'number');\n\n // Dialog-backed controls: render when the chrome can open them — Format Cells\n // is a built-in (always available); Insert Chart / PivotTable open only when a\n // host registered/handles them.\n const showFormatCells = enabled(features, 'format-cells') && dialogs.canOpen('format-cells');\n const showInsertChart = enabled(features, 'insert-chart') && dialogs.canOpen('insert-chart');\n const showPivotTable = enabled(features, 'pivot-table') && dialogs.canOpen('insert-pivot');\n const showDialogGroup = showFormatCells || showInsertChart || showPivotTable;\n\n // Host toolbar extensions — appended after the built-in groups.\n const toolbarExt = (extensions?.toolbar ?? []).filter(\n (e) => !e.isVisible || (api ? e.isVisible(api) : false),\n );\n const runExt = (e: ToolbarExtension) => {\n if (!api) return;\n if (e.command) void api.executeCommand(e.command, e.commandParams);\n else e.onClick?.(api);\n };\n\n return (\n <div style={BAR_STYLE} data-testid=\"casual-sheets-toolbar\" role=\"toolbar\" aria-label=\"Editor\">\n {showFont && (\n <>\n <select\n aria-label=\"Font family\"\n data-testid=\"cs-font-family\"\n style={{ ...SELECT_STYLE, width: 130 }}\n value={familyValue}\n disabled={!api}\n onChange={(e) =>\n dispatch('sheet.command.set-range-font-family', { value: e.target.value })\n }\n >\n {familyOptions.map((f) => (\n <option key={f} value={f}>\n {f}\n </option>\n ))}\n </select>\n <select\n aria-label=\"Font size\"\n data-testid=\"cs-font-size\"\n style={{ ...SELECT_STYLE, width: 56, marginLeft: 4 }}\n value={sizeValue}\n disabled={!api}\n onChange={(e) => applyFontSize(Number(e.target.value))}\n >\n {sizeOptions.map((s) => (\n <option key={s} value={s}>\n {s}\n </option>\n ))}\n </select>\n {renderIconButton(\n 'font-size-up',\n 'Increase font size',\n 'text_increase',\n () => adjustFontSize(+1),\n 'cs-font-size-up',\n )}\n {renderIconButton(\n 'font-size-down',\n 'Decrease font size',\n 'text_decrease',\n () => adjustFontSize(-1),\n 'cs-font-size-down',\n )}\n <span style={DIVIDER_STYLE} aria-hidden />\n </>\n )}\n\n {groupNodes}\n\n {(showColor || showBorders) && <span style={DIVIDER_STYLE} aria-hidden />}\n {showColor && <ColorPicker api={api} />}\n {showBorders && <BordersPicker api={api} />}\n\n {showNumberDropdown && (\n <>\n <span style={DIVIDER_STYLE} aria-hidden />\n <select\n aria-label=\"Number format\"\n data-testid=\"cs-number-format\"\n style={{ ...SELECT_STYLE, width: 124 }}\n value={numberFormatValue}\n disabled={!api}\n onChange={(e) =>\n applyNumberFormat(NUMBER_FORMAT_PATTERNS[e.target.value as NumberFormatKey])\n }\n >\n {NUMBER_FORMAT_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </>\n )}\n\n {showAutoSum && (\n <>\n <span style={DIVIDER_STYLE} aria-hidden />\n <AutoSumPicker api={api} />\n </>\n )}\n\n {showDialogGroup && (\n <>\n <span style={DIVIDER_STYLE} aria-hidden />\n {showFormatCells &&\n renderIconButton(\n 'format-cells',\n 'Format Cells…',\n 'format_shapes',\n () => dialogs.openDialog('format-cells'),\n 'cs-format-cells',\n )}\n {showInsertChart &&\n renderIconButton(\n 'insert-chart',\n 'Insert chart',\n 'bar_chart',\n () => dialogs.openDialog('insert-chart'),\n 'cs-insert-chart',\n )}\n {showPivotTable &&\n renderIconButton(\n 'pivot-table',\n 'Insert PivotTable',\n 'pivot_table_chart',\n () => dialogs.openDialog('insert-pivot'),\n 'cs-pivot-table',\n )}\n </>\n )}\n\n {toolbarExt.length > 0 && (\n <>\n <span style={DIVIDER_STYLE} aria-hidden />\n {toolbarExt.map((e) =>\n renderIconButton(e.id, e.label, e.icon, () => runExt(e), `cs-ext-${e.id}`),\n )}\n </>\n )}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Icon — a Material Symbols Outlined glyph for the chrome.\n *\n * Names are Material Symbols ids (https://fonts.google.com/icons), e.g.\n * `format_bold`. Requires the Material Symbols font (loaded via\n * `ensureChromeFonts`); if it isn't present the ligature text shows instead,\n * which is harmless. Icon-only buttons must carry their own `aria-label`.\n */\n\nimport type { CSSProperties } from 'react';\n\nexport interface IconProps {\n name: string;\n size?: number;\n style?: CSSProperties;\n}\n\nexport function Icon({ name, size = 20, style }: IconProps) {\n return (\n <span\n className=\"material-symbols-outlined\"\n aria-hidden\n style={{\n fontFamily: \"'Material Symbols Outlined'\",\n fontWeight: 'normal',\n fontStyle: 'normal',\n fontSize: size,\n lineHeight: 1,\n letterSpacing: 'normal',\n textTransform: 'none',\n display: 'inline-block',\n whiteSpace: 'nowrap',\n wordWrap: 'normal',\n direction: 'ltr',\n // Hint the variable-font axes so weight/optical-size are consistent.\n fontVariationSettings: \"'opsz' 20, 'wght' 400, 'FILL' 0, 'GRAD' 0\",\n ...style,\n }}\n >\n {name}\n </span>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Ensures the chrome's webfonts (Inter for UI, Material Symbols Outlined for\n * icons) are loaded. The design system standardises on these; the rich\n * `chrome=\"full\"` toolbar/menus render Material Symbols ligatures.\n *\n * Idempotent + safe to call repeatedly: it no-ops if the links already exist\n * (e.g. a host that already loads them, like our own app). Injected lazily only\n * when chrome is actually shown, so bare-grid SDK consumers pull nothing.\n *\n * Hosts with a strict CSP (no fonts.googleapis.com) can pre-load the fonts\n * themselves or self-host them; this is best-effort, not required for the editor\n * to function (icons fall back to the ligature text).\n */\n\nconst LINKS: Array<{ id: string; href: string }> = [\n {\n id: 'cs-font-inter',\n href: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap',\n },\n {\n id: 'cs-font-material-symbols',\n href: 'https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@20..48,300..700,0..1,-50..200&display=block',\n },\n];\n\nlet done = false;\n\nexport function ensureChromeFonts(): void {\n if (done || typeof document === 'undefined') return;\n done = true;\n const head = document.head;\n for (const { id, href } of LINKS) {\n if (document.getElementById(id)) continue;\n // Skip if the host already loaded the same family by any <link>.\n // Match on the `family=<name>` segment, NOT the bare `/css2` path — both\n // Google Fonts URLs share `/css2`, so splitting on `?` made the second\n // family (Material Symbols) collide with the first (Inter) and never get\n // injected, leaving `chrome=\"full\"` icons as raw ligature text.\n const familyKey = href.match(/family=[^:&]+/)?.[0] ?? href.split('?')[0];\n if (document.querySelector(`link[href*=\"${familyKey}\"]`)) continue;\n const link = document.createElement('link');\n link.id = id;\n link.rel = 'stylesheet';\n link.href = href;\n head.appendChild(link);\n }\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * ColorPicker — text-colour + fill-colour swatch pickers for `<CasualSheets chrome>`.\n *\n * Two icon buttons (text colour, fill colour). Clicking one toggles a swatch\n * popover; picking a swatch dispatches the matching Univer command on the active\n * selection and closes the popover. A \"None\" entry resets the colour.\n *\n * Drives the editor purely through `CasualSheetsAPI.executeCommand`. Commands:\n * text colour : `sheet.command.set-range-text-color` { value: '#rrggbb' | null }\n * fill colour : `sheet.command.set-background-color` { value: '#rrggbb' }\n * fill reset : `sheet.command.reset-background-color` (no params)\n * (`set-background-color` rejects a null value, so reset uses its own command.)\n */\n\nimport { useEffect, useRef, useState, type CSSProperties } from 'react';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\n\ntype Kind = 'text' | 'fill';\n\n// A tasteful 14-swatch palette: neutrals + a spread of hues, teal = brand.\nconst SWATCHES: { hex: string; label: string }[] = [\n { hex: '#000000', label: 'Black' },\n { hex: '#5f6368', label: 'Dark gray' },\n { hex: '#9aa0a6', label: 'Gray' },\n { hex: '#d9dce0', label: 'Light gray' },\n { hex: '#ffffff', label: 'White' },\n { hex: '#d13438', label: 'Red' },\n { hex: '#e8710a', label: 'Orange' },\n { hex: '#f2c811', label: 'Yellow' },\n { hex: '#107c10', label: 'Green' },\n { hex: '#0e7490', label: 'Teal' },\n { hex: '#1a73e8', label: 'Blue' },\n { hex: '#5b2a86', label: 'Purple' },\n { hex: '#c2185b', label: 'Magenta' },\n { hex: '#795548', label: 'Brown' },\n];\n\nconst ROW_STYLE: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n position: 'relative',\n};\n\nconst BTN_STYLE: CSSProperties = {\n width: 30,\n height: 30,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n padding: 0,\n};\n\nconst POPOVER_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: 4,\n zIndex: 1000,\n padding: 8,\n borderRadius: 8,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.18)',\n};\n\nconst GRID_STYLE: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: 'repeat(7, 22px)',\n gap: 6,\n};\n\nconst SWATCH_STYLE: CSSProperties = {\n width: 22,\n height: 22,\n borderRadius: 4,\n border: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.18))',\n cursor: 'pointer',\n padding: 0,\n};\n\nconst NONE_STYLE: CSSProperties = {\n marginTop: 8,\n width: '100%',\n height: 26,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n gap: 4,\n border: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.18))',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 12,\n cursor: 'pointer',\n};\n\nexport interface ColorPickerProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function ColorPicker({ api }: ColorPickerProps) {\n const [open, setOpen] = useState<Kind | null>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Close on Escape and on any pointerdown outside the picker root.\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: PointerEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(null);\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(null);\n };\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n const pick = (kind: Kind, hex: string | null) => {\n if (api) {\n if (kind === 'text') {\n void api.executeCommand('sheet.command.set-range-text-color', { value: hex });\n } else if (hex === null) {\n void api.executeCommand('sheet.command.reset-background-color');\n } else {\n void api.executeCommand('sheet.command.set-background-color', { value: hex });\n }\n }\n setOpen(null);\n };\n\n const toggle = (kind: Kind) => setOpen((cur) => (cur === kind ? null : kind));\n\n const renderButton = (kind: Kind, icon: string, label: string, testid: string) => {\n const on = open === kind;\n const baseBg = on ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent';\n return (\n <button\n type=\"button\"\n title={label}\n aria-label={label}\n aria-haspopup=\"true\"\n aria-expanded={on}\n data-testid={testid}\n style={{\n ...BTN_STYLE,\n background: baseBg,\n color: on ? 'var(--cs-chrome-active-fg, #0e7490)' : BTN_STYLE.color,\n }}\n // mousedown (not click) so the grid's selection isn't lost first.\n onMouseDown={(e) => {\n e.preventDefault();\n toggle(kind);\n }}\n onMouseEnter={(e) => {\n if (!on) e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = baseBg;\n }}\n >\n <Icon name={icon} size={20} />\n </button>\n );\n };\n\n const renderPopover = (kind: Kind) => (\n <div style={POPOVER_STYLE} data-testid=\"cs-color-popover\" role=\"menu\">\n <div style={GRID_STYLE}>\n {SWATCHES.map((s) => (\n <button\n key={s.hex}\n type=\"button\"\n role=\"menuitem\"\n title={s.label}\n aria-label={s.label}\n data-color={s.hex}\n style={{ ...SWATCH_STYLE, background: s.hex }}\n onMouseDown={(e) => {\n e.preventDefault();\n pick(kind, s.hex);\n }}\n />\n ))}\n </div>\n <button\n type=\"button\"\n role=\"menuitem\"\n data-color=\"none\"\n style={NONE_STYLE}\n onMouseDown={(e) => {\n e.preventDefault();\n pick(kind, null);\n }}\n >\n <Icon name=\"format_color_reset\" size={16} />\n None\n </button>\n </div>\n );\n\n return (\n <div ref={rootRef} style={ROW_STYLE} data-testid=\"cs-color-picker\">\n {renderButton('text', 'format_color_text', 'Text color', 'cs-color-text')}\n {renderButton('fill', 'format_color_fill', 'Fill color', 'cs-color-fill')}\n {open && renderPopover(open)}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * BordersPicker — border-position dropdown for `<CasualSheets chrome>`.\n *\n * One toolbar button that opens a popover of Excel-style border options (All,\n * Outside, Inside, Top, Bottom, Left, Right, None). Picking one dispatches\n * `sheet.command.set-border-position` with the matching `BorderType` against the\n * active selection, using Univer's current border style/colour (thin black by\n * default). Drives the editor purely through `CasualSheetsAPI.executeCommand`.\n */\n\nimport { useEffect, useRef, useState, type CSSProperties } from 'react';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\n\n// BorderType is a string enum in @univerjs/core ('all' | 'outside' | …); use the\n// literal values directly so this component needs no Univer value import.\nconst OPTIONS: { value: string; icon: string; label: string }[] = [\n { value: 'all', icon: 'border_all', label: 'All borders' },\n { value: 'outside', icon: 'border_outer', label: 'Outside borders' },\n { value: 'inside', icon: 'border_inner', label: 'Inside borders' },\n { value: 'top', icon: 'border_top', label: 'Top border' },\n { value: 'bottom', icon: 'border_bottom', label: 'Bottom border' },\n { value: 'left', icon: 'border_left', label: 'Left border' },\n { value: 'right', icon: 'border_right', label: 'Right border' },\n { value: 'none', icon: 'border_clear', label: 'No border' },\n];\n\nconst ROW_STYLE: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n position: 'relative',\n};\n\nconst BTN_STYLE: CSSProperties = {\n width: 30,\n height: 30,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n padding: 0,\n};\n\nconst POPOVER_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: 4,\n zIndex: 1000,\n padding: 4,\n minWidth: 168,\n borderRadius: 8,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.18)',\n};\n\nconst ITEM_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n width: '100%',\n height: 28,\n padding: '0 8px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n textAlign: 'left',\n};\n\nexport interface BordersPickerProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function BordersPicker({ api }: BordersPickerProps) {\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Close on Escape and on any pointerdown outside the picker root.\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: PointerEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n const pick = (value: string) => {\n void api?.executeCommand('sheet.command.set-border-position', { value });\n setOpen(false);\n };\n\n const on = open;\n const baseBg = on ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent';\n\n return (\n <div ref={rootRef} style={ROW_STYLE} data-testid=\"cs-borders\">\n <button\n type=\"button\"\n title=\"Borders\"\n aria-label=\"Borders\"\n aria-haspopup=\"true\"\n aria-expanded={on}\n data-testid=\"cs-borders-button\"\n disabled={!api}\n style={{\n ...BTN_STYLE,\n background: baseBg,\n color: on ? 'var(--cs-chrome-active-fg, #0e7490)' : BTN_STYLE.color,\n }}\n // mousedown (not click) so the grid's selection isn't lost first.\n onMouseDown={(e) => {\n e.preventDefault();\n setOpen((v) => !v);\n }}\n onMouseEnter={(e) => {\n if (!on) e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = baseBg;\n }}\n >\n <Icon name=\"border_all\" size={20} />\n </button>\n {open && (\n <div style={POPOVER_STYLE} data-testid=\"cs-borders-popover\" role=\"menu\">\n {OPTIONS.map((o) => (\n <button\n key={o.value}\n type=\"button\"\n role=\"menuitem\"\n data-border={o.value}\n data-testid={`cs-border-${o.value}`}\n style={ITEM_STYLE}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n pick(o.value);\n }}\n >\n <Icon name={o.icon} size={18} />\n {o.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * AutoSumPicker — Excel-style AutoSum dropdown for `<CasualSheets chrome>`.\n *\n * One toolbar button (Σ) opening Sum / Average / Count / Max / Min. Picking one\n * inserts `=FN(<selection>)` one row below a multi-cell selection (and activates\n * that cell), or `=FN()` into a single active cell so the user can type the\n * range. Pure facade — no command, no Univer UI dependency — so it works in the\n * SDK's embedded mount.\n */\n\nimport { useEffect, useRef, useState, type CSSProperties } from 'react';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\n\nconst FUNCS: { fn: string; label: string }[] = [\n { fn: 'SUM', label: 'Sum' },\n { fn: 'AVERAGE', label: 'Average' },\n { fn: 'COUNT', label: 'Count numbers' },\n { fn: 'MAX', label: 'Max' },\n { fn: 'MIN', label: 'Min' },\n];\n\nconst ROW_STYLE: CSSProperties = {\n display: 'inline-flex',\n alignItems: 'center',\n position: 'relative',\n};\n\nconst BTN_STYLE: CSSProperties = {\n width: 30,\n height: 30,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n padding: 0,\n};\n\nconst POPOVER_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: 4,\n zIndex: 1000,\n padding: 4,\n minWidth: 160,\n borderRadius: 8,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.18)',\n};\n\nconst ITEM_STYLE: CSSProperties = {\n display: 'block',\n width: '100%',\n textAlign: 'left',\n height: 28,\n padding: '0 10px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n};\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyRange = any;\n\nexport interface AutoSumPickerProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function AutoSumPicker({ api }: AutoSumPickerProps) {\n const [open, setOpen] = useState(false);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: PointerEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n };\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n const apply = (fn: string) => {\n setOpen(false);\n const sheet = api?.univer.getActiveWorkbook()?.getActiveSheet();\n const range = (sheet as unknown as { getActiveRange?: () => AnyRange })?.getActiveRange?.();\n if (!sheet || !range) return;\n const multi = range.getWidth() * range.getHeight() > 1;\n if (multi) {\n // Drop the formula one row below the selection, same column as its start.\n const target = sheet.getRange(range.getRow() + range.getHeight(), range.getColumn());\n target.setValue({ f: `=${fn}(${range.getA1Notation()})` });\n (target as AnyRange).activate?.();\n } else {\n // Single cell — leave the cursor inside the parens for the user to fill.\n sheet.getRange(range.getRow(), range.getColumn()).setValue({ f: `=${fn}()` });\n }\n };\n\n const on = open;\n const baseBg = on ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent';\n\n return (\n <div ref={rootRef} style={ROW_STYLE} data-testid=\"cs-autosum\">\n <button\n type=\"button\"\n title=\"AutoSum\"\n aria-label=\"AutoSum\"\n aria-haspopup=\"true\"\n aria-expanded={on}\n data-testid=\"cs-autosum-button\"\n disabled={!api}\n style={{\n ...BTN_STYLE,\n background: baseBg,\n color: on ? 'var(--cs-chrome-active-fg, #0e7490)' : BTN_STYLE.color,\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n setOpen((v) => !v);\n }}\n onMouseEnter={(e) => {\n if (!on) e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = baseBg;\n }}\n >\n <Icon name=\"functions\" size={20} />\n </button>\n {open && (\n <div style={POPOVER_STYLE} data-testid=\"cs-autosum-popover\" role=\"menu\">\n {FUNCS.map((f) => (\n <button\n key={f.fn}\n type=\"button\"\n role=\"menuitem\"\n data-fn={f.fn}\n data-testid={`cs-autosum-${f.fn}`}\n style={ITEM_STYLE}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n onMouseDown={(e) => {\n e.preventDefault();\n apply(f.fn);\n }}\n >\n {f.label}\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Dialog host + registry for `<CasualSheets chrome>`.\n *\n * The model: a chrome control (menu item, toolbar button) calls\n * `openDialog(kind, context)`. By default that opens the SDK's BUILT-IN dialog\n * for that kind (rendered by `<DialogHost>`). A host can OVERRIDE any kind — or\n * add novel kinds — via `extensions.dialogs`, and can additionally route\n * specific kinds to its legacy `onDialogRequest` callback (back-compat).\n *\n * Resolution order in `openDialog(kind)`:\n * 1. host registered `extensions.dialogs[kind]` → render host dialog\n * 2. host opted `kind` to `onDialogRequest` (no built-in, or host wants it)\n * → emit onDialogRequest\n * 3. SDK has a built-in dialog for `kind` → render built-in\n * 4. else, if `onDialogRequest` provided → emit onDialogRequest\n * 5. else → no-op\n *\n * `onDialogRequest` stays fully supported: if a host passes it and DOESN'T\n * register a built-in override, kinds the SDK has no built-in for fall through\n * to it (3→4), matching the previous behaviour.\n */\n\nimport { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from 'react';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport type { ChromeExtensions, DialogComponentProps } from './extensions';\nimport { FormatCellsDialog } from './FormatCellsDialog';\nimport { DataValidationDialog } from './DataValidationDialog';\nimport { ConditionalFormattingDialog } from './ConditionalFormattingDialog';\nimport { CustomSortDialog } from './CustomSortDialog';\nimport { PasteSpecialDialog } from './PasteSpecialDialog';\nimport { InsertFunctionDialog } from './InsertFunctionDialog';\nimport { NameManagerDialog } from './NameManagerDialog';\nimport { InsertCellsDialog } from './InsertCellsDialog';\nimport { DeleteCellsDialog } from './DeleteCellsDialog';\nimport { GoalSeekDialog } from './GoalSeekDialog';\nimport { InsertChartDialog } from './InsertChartDialog';\nimport { InsertSparklineDialog } from './InsertSparklineDialog';\nimport { InsertPivotDialog } from './InsertPivotDialog';\n\n/**\n * All dialog kinds the chrome knows about. Mirrors `MenuDialogKind` in MenuBar\n * (kept in sync) and is the key space for `extensions.dialogs`. Kinds with a\n * built-in renderer are listed in `BUILT_IN_DIALOGS`; the rest need a host\n * override or `onDialogRequest` to do anything.\n */\nexport type DialogKind =\n | 'format-cells'\n | 'find-replace'\n | 'insert-cells'\n | 'delete-cells'\n | 'paste-special'\n | 'insert-chart'\n | 'insert-pivot'\n | 'insert-sparkline'\n | 'insert-function'\n | 'name-manager'\n | 'goal-seek'\n | 'data-validation'\n | 'conditional-formatting'\n | 'custom-sort'\n | 'properties'\n | 'about'\n | 'keyboard-shortcuts';\n\n/**\n * SDK built-in dialog components, keyed by kind. Anything NOT here has no\n * built-in UI and falls through to a host override / onDialogRequest.\n *\n * `find-replace` is intentionally NOT here — it's the self-managing\n * `<FindReplace>` panel (Ctrl+F/H), wired separately in ChromeTop and opened\n * imperatively; `DialogHost` only owns the modal-style built-ins.\n */\nconst BUILT_IN_DIALOGS: Partial<Record<DialogKind, React.ComponentType<DialogComponentProps>>> = {\n 'format-cells': FormatCellsDialog,\n 'data-validation': DataValidationDialog,\n 'conditional-formatting': ConditionalFormattingDialog,\n 'custom-sort': CustomSortDialog,\n 'paste-special': PasteSpecialDialog,\n 'insert-function': InsertFunctionDialog,\n 'name-manager': NameManagerDialog,\n 'insert-cells': InsertCellsDialog,\n 'delete-cells': DeleteCellsDialog,\n 'goal-seek': GoalSeekDialog,\n 'insert-chart': InsertChartDialog,\n 'insert-sparkline': InsertSparklineDialog,\n 'insert-pivot': InsertPivotDialog,\n};\n\n/** Kinds the chrome can open without a host (built-in modal or self-managing). */\nexport function hasBuiltInDialog(kind: DialogKind): boolean {\n return kind in BUILT_IN_DIALOGS || kind === 'find-replace';\n}\n\ninterface ActiveDialog {\n kind: DialogKind;\n context?: unknown;\n}\n\nexport interface DialogController {\n /** Open a dialog (built-in by default; host override / onDialogRequest wins per rules). */\n openDialog: (kind: DialogKind, context?: unknown) => void;\n /** Close the currently-open built-in/override dialog. */\n closeDialog: () => void;\n /** True when the chrome can open `kind` itself OR a host registered/handles it. */\n canOpen: (kind: DialogKind) => boolean;\n}\n\nconst DialogContext = createContext<DialogController | null>(null);\n\n/** Access the dialog controller from any chrome component under the provider. */\nexport function useDialogs(): DialogController {\n const ctx = useContext(DialogContext);\n if (!ctx) {\n // Defensive — should never happen inside the chrome tree. A no-op keeps a\n // mis-mounted control from throwing.\n return {\n openDialog: () => {},\n closeDialog: () => {},\n canOpen: () => false,\n };\n }\n return ctx;\n}\n\nexport interface DialogProviderProps {\n api: CasualSheetsAPI | null;\n extensions?: ChromeExtensions;\n /**\n * Legacy host hook. When set, kinds the host opts to handle (no built-in, or\n * explicitly listed in `hostOwnedDialogs`) emit through it instead of\n * rendering a built-in. Back-compat: still fires for non-built-in kinds.\n */\n onDialogRequest?: (kind: DialogKind, context?: unknown) => void;\n /**\n * Kinds the host wants to own via `onDialogRequest` even though the SDK has a\n * built-in. Lets a host keep the SDK chrome but its own Format Cells, say,\n * without registering a React component.\n */\n hostOwnedDialogs?: DialogKind[];\n /**\n * Bridge for the self-managing find-replace panel. `find-replace` isn't a\n * modal `<DialogHost>` renders — it's the `<FindReplace>` panel — so the\n * provider delegates opening it to the chrome (which owns the panel's open\n * signal) instead of setting `active`.\n */\n onOpenFindReplace?: (replaceMode: boolean) => void;\n children: ReactNode;\n}\n\n/**\n * Provides `openDialog`/`closeDialog` to the chrome tree and renders the active\n * built-in/override dialog via `<DialogHost>` (mounted internally).\n */\nexport function DialogProvider({\n api,\n extensions,\n onDialogRequest,\n hostOwnedDialogs,\n onOpenFindReplace,\n children,\n}: DialogProviderProps) {\n const [active, setActive] = useState<ActiveDialog | null>(null);\n\n const overrides = extensions?.dialogs;\n const hostOwned = useMemo(() => new Set(hostOwnedDialogs ?? []), [hostOwnedDialogs]);\n\n const openDialog = useCallback(\n (kind: DialogKind, context?: unknown) => {\n // 1. Host-registered React override → render it.\n if (overrides?.[kind]) {\n setActive({ kind, context });\n return;\n }\n // 2. Host explicitly owns this kind via onDialogRequest.\n if (onDialogRequest && hostOwned.has(kind)) {\n onDialogRequest(kind, context);\n return;\n }\n // find-replace is the self-managing panel, not a DialogHost modal — bridge\n // to the chrome's open signal.\n if (kind === 'find-replace') {\n onOpenFindReplace?.(false);\n return;\n }\n // 3. SDK built-in.\n if (hasBuiltInDialog(kind)) {\n setActive({ kind, context });\n return;\n }\n // 4. Fall through to onDialogRequest for kinds with no built-in.\n if (onDialogRequest) {\n onDialogRequest(kind, context);\n return;\n }\n // 5. No way to fulfil — no-op (the control shouldn't have rendered).\n },\n [overrides, onDialogRequest, hostOwned, onOpenFindReplace],\n );\n\n const closeDialog = useCallback(() => setActive(null), []);\n\n const canOpen = useCallback(\n (kind: DialogKind) =>\n !!overrides?.[kind] || hasBuiltInDialog(kind) || !!onDialogRequest || hostOwned.has(kind),\n [overrides, onDialogRequest, hostOwned],\n );\n\n const controllerCanOpen = useCallback(\n (kind: DialogKind) =>\n kind === 'find-replace' ? !!onOpenFindReplace || canOpen(kind) : canOpen(kind),\n [canOpen, onOpenFindReplace],\n );\n\n const controller = useMemo<DialogController>(\n () => ({ openDialog, closeDialog, canOpen: controllerCanOpen }),\n [openDialog, closeDialog, controllerCanOpen],\n );\n\n return (\n <DialogContext.Provider value={controller}>\n {children}\n <DialogHost api={api} active={active} overrides={overrides} onClose={closeDialog} />\n </DialogContext.Provider>\n );\n}\n\ninterface DialogHostProps {\n api: CasualSheetsAPI | null;\n active: ActiveDialog | null;\n overrides?: ChromeExtensions['dialogs'];\n onClose: () => void;\n}\n\n/**\n * Renders the currently-active modal dialog — a host override if registered for\n * the kind, otherwise the SDK built-in. `find-replace` is excluded (the\n * self-managing FindReplace panel owns it). Renders nothing when no dialog is\n * open or the API isn't ready.\n */\nfunction DialogHost({ api, active, overrides, onClose }: DialogHostProps) {\n if (!active || !api) return null;\n if (active.kind === 'find-replace') return null;\n const Component = overrides?.[active.kind] ?? BUILT_IN_DIALOGS[active.kind];\n if (!Component) return null;\n return <Component api={api} onClose={onClose} context={active.context} />;\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * FormatCellsDialog — the SDK chrome's built-in Format Cells modal.\n *\n * Ported from `apps/web/src/shell/FormatCellsDialog.tsx`, reimplemented against\n * the `CasualSheetsAPI` + FUniver facade ONLY (no app context: no use-univer, no\n * useActiveCellState, no home-tab-actions). Tabs: Number · Alignment · Font ·\n * Border · Fill. Reads the active cell's current style off the snapshot to seed\n * the form, and applies via the same facade calls the app uses\n * (`setFontWeight` / `setHorizontalAlignment` / `setNumberFormat` / `setBorder`\n * / `setBackground` / …), so behaviour matches the real app exactly.\n *\n * Mounted by `<DialogHost>` when `openDialog('format-cells')` is called and no\n * host override is registered.\n */\n\nimport { useEffect, useMemo, useState, type CSSProperties } from 'react';\nimport { BorderStyleTypes, BorderType } from '@univerjs/core';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_INPUT_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\ntype TabId = 'number' | 'alignment' | 'font' | 'border' | 'fill';\n\ntype HAlign = 'left' | 'center' | 'right';\ntype VAlign = 'top' | 'middle' | 'bottom';\ntype BorderChoice = 'all' | 'outside' | 'top' | 'bottom' | 'left' | 'right' | 'none';\n\nconst DEFAULT_BORDER_COLOR = '#000000';\n\n/** Number-format presets — patterns copied verbatim from the app's\n * `home-tab-actions.NUMBER_FORMAT_PATTERNS`. */\nconst NUMBER_FORMAT_PATTERNS = {\n general: '',\n number: '#,##0.00',\n integer: '#,##0',\n currency: '\"$\"#,##0.00',\n accounting: '_(\"$\"* #,##0.00_);_(\"$\"* (#,##0.00);_(\"$\"* \"-\"??_);_(@_)',\n percent: '0.00%',\n date: 'yyyy-mm-dd',\n time: 'hh:mm:ss',\n scientific: '0.00E+00',\n text: '@',\n} as const;\ntype NumberFormatKey = keyof typeof NUMBER_FORMAT_PATTERNS;\n\nconst WEIGHT_TO_STYLE: BorderStyleTypes = BorderStyleTypes.THIN;\n\ninterface DialogState {\n numberFormatKey: NumberFormatKey;\n numberPattern: string;\n align: HAlign;\n vAlign: VAlign;\n wrap: boolean;\n fontFamily: string;\n fontSize: string;\n bold: boolean;\n italic: boolean;\n underline: boolean;\n borderChoice: BorderChoice;\n borderColor: string;\n fillColor: string;\n}\n\nconst TABS: Array<{ id: TabId; label: string }> = [\n { id: 'number', label: 'Number' },\n { id: 'alignment', label: 'Alignment' },\n { id: 'font', label: 'Font' },\n { id: 'border', label: 'Border' },\n { id: 'fill', label: 'Fill' },\n];\n\nconst FONT_FAMILIES = [\n 'Calibri',\n 'Arial',\n 'Helvetica',\n 'Inter',\n 'Times New Roman',\n 'Georgia',\n 'Verdana',\n 'Courier New',\n 'JetBrains Mono',\n];\n\nconst NUMBER_FORMAT_OPTIONS: Array<{ value: NumberFormatKey; label: string }> = [\n { value: 'general', label: 'General' },\n { value: 'integer', label: 'Number (no decimals)' },\n { value: 'number', label: 'Number (2 decimals)' },\n { value: 'currency', label: 'Currency' },\n { value: 'accounting', label: 'Accounting' },\n { value: 'percent', label: 'Percent' },\n { value: 'date', label: 'Date' },\n { value: 'time', label: 'Time' },\n { value: 'scientific', label: 'Scientific' },\n { value: 'text', label: 'Text' },\n];\n\nfunction detectFormatKey(pattern: string): NumberFormatKey {\n for (const key of Object.keys(NUMBER_FORMAT_PATTERNS) as NumberFormatKey[]) {\n if (NUMBER_FORMAT_PATTERNS[key] === pattern) return key;\n }\n return 'general';\n}\n\n/** Univer style shape we read off the active cell (subset). */\ninterface CellStyle {\n ff?: string;\n fs?: number;\n bl?: number; // bold (1)\n it?: number; // italic (1)\n ul?: { s?: number } | number; // underline\n ht?: number; // horizontal: 1 left, 2 center, 3 right\n vt?: number; // vertical: 1 top, 2 middle, 3 bottom\n tb?: number; // text wrap: 3 wrap\n bg?: { rgb?: string };\n n?: { pattern?: string };\n bd?: Record<string, unknown>;\n}\n\n/**\n * Resolve the active cell's style from the snapshot. Styles can be an inline\n * object or a string key into the workbook's style table — mirror the app's\n * `getCellData()` + styles-table lookup, but off the SDK snapshot.\n */\nfunction readActiveStyle(api: CasualSheetsAPI): CellStyle | null {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const snap = api.getSnapshot() as any;\n if (!snap) return null;\n const sel = api.getSelection();\n const sheetId = sel?.sheetId ?? api.univer.getActiveWorkbook()?.getActiveSheet()?.getSheetId();\n if (!sheetId) return null;\n const sheet = snap.sheets?.[sheetId];\n if (!sheet) return null;\n const row = sel?.range.startRow ?? 0;\n const col = sel?.range.startColumn ?? 0;\n const cell = sheet.cellData?.[row]?.[col];\n if (!cell) return null;\n const s = cell.s;\n if (typeof s === 'string') return (snap.styles?.[s] as CellStyle) ?? null;\n return (s as CellStyle) ?? null;\n}\n\nfunction buildInitialState(style: CellStyle | null): DialogState {\n const pattern = style?.n?.pattern ?? '';\n const underline =\n typeof style?.ul === 'number' ? style.ul === 1 : !!(style?.ul && style.ul.s === 1);\n return {\n numberFormatKey: detectFormatKey(pattern),\n numberPattern: pattern,\n align: style?.ht === 2 ? 'center' : style?.ht === 3 ? 'right' : 'left',\n vAlign: style?.vt === 1 ? 'top' : style?.vt === 2 ? 'middle' : 'bottom',\n wrap: style?.tb === 3,\n fontFamily: style?.ff || 'Calibri',\n fontSize: String(style?.fs || 11),\n bold: style?.bl === 1,\n italic: style?.it === 1,\n underline,\n borderChoice: style?.bd && Object.keys(style.bd).length > 0 ? 'outside' : 'none',\n borderColor: DEFAULT_BORDER_COLOR,\n fillColor: style?.bg?.rgb || '#ffffff',\n };\n}\n\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/** Apply every section of the form via the facade — same calls as the app. */\nfunction applyFormat(api: CasualSheetsAPI, s: DialogState): void {\n const range = activeRange(api);\n if (!range) return;\n\n // Number format — sheets-numfmt facade extension (runtime-added to FRange).\n (range as unknown as { setNumberFormat?: (p: string) => unknown }).setNumberFormat?.(\n s.numberPattern,\n );\n\n // Univer's facade uses 'normal' for right-aligned (FHorizontalAlignment).\n range.setHorizontalAlignment(s.align === 'right' ? 'normal' : s.align);\n range.setVerticalAlignment(s.vAlign);\n range.setWrap(s.wrap);\n\n range.setFontFamily(s.fontFamily || null);\n const size = Number(s.fontSize);\n if (Number.isFinite(size) && size > 0) range.setFontSize(size);\n range.setFontWeight(s.bold ? 'bold' : 'normal');\n range.setFontStyle(s.italic ? 'italic' : 'normal');\n range.setFontLine(s.underline ? 'underline' : 'none');\n\n // Borders — map the preset to a Univer BorderType + thin style (matches the\n // app's setBorders default weight).\n const type =\n s.borderChoice === 'all'\n ? BorderType.ALL\n : s.borderChoice === 'outside'\n ? BorderType.OUTSIDE\n : s.borderChoice === 'top'\n ? BorderType.TOP\n : s.borderChoice === 'bottom'\n ? BorderType.BOTTOM\n : s.borderChoice === 'left'\n ? BorderType.LEFT\n : s.borderChoice === 'right'\n ? BorderType.RIGHT\n : BorderType.NONE;\n const borderStyle = s.borderChoice === 'none' ? BorderStyleTypes.NONE : WEIGHT_TO_STYLE;\n range.setBorder(type, borderStyle, s.borderColor);\n\n range.setBackground(s.fillColor);\n}\n\nconst TABS_ROW_STYLE: CSSProperties = {\n display: 'flex',\n gap: 2,\n borderBottom: '1px solid var(--cs-chrome-border, #edeff3)',\n marginBottom: 14,\n};\n\nfunction tabStyle(activeTab: boolean): CSSProperties {\n return {\n padding: '6px 12px',\n border: 'none',\n borderBottom: `2px solid ${activeTab ? 'var(--cs-chrome-active-fg, #0e7490)' : 'transparent'}`,\n background: 'transparent',\n color: activeTab ? 'var(--cs-chrome-active-fg, #0e7490)' : 'var(--cs-chrome-muted, #605e5c)',\n font: 'inherit',\n fontSize: 13,\n fontWeight: activeTab ? 600 : 400,\n cursor: 'pointer',\n };\n}\n\nconst CHECK_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n marginBottom: 8,\n cursor: 'pointer',\n};\n\nconst COLOR_INPUT_STYLE: CSSProperties = {\n width: 48,\n height: 30,\n padding: 2,\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n cursor: 'pointer',\n};\n\nexport function FormatCellsDialog({ api, onClose }: DialogComponentProps) {\n const [tab, setTab] = useState<TabId>('number');\n // Seed once from the active cell when the dialog mounts.\n const initial = useMemo(() => buildInitialState(readActiveStyle(api)), [api]);\n const [state, setState] = useState<DialogState>(initial);\n\n // Re-seed if the active cell changes while open (rare, but keeps it honest).\n useEffect(() => {\n setState(buildInitialState(readActiveStyle(api)));\n }, [api]);\n\n const update = <K extends keyof DialogState>(key: K, value: DialogState[K]) =>\n setState((prev) => ({ ...prev, [key]: value }));\n\n const apply = () => {\n applyFormat(api, state);\n onClose();\n };\n\n return (\n <Dialog\n title=\"Format Cells\"\n onClose={onClose}\n width={480}\n data-testid=\"cs-format-cells-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-format-cells-apply\"\n onClick={apply}\n >\n Apply\n </button>\n </>\n }\n >\n <div style={TABS_ROW_STYLE} role=\"tablist\" aria-label=\"Format sections\">\n {TABS.map((t) => (\n <button\n key={t.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={tab === t.id}\n data-testid={`cs-format-cells-tab-${t.id}`}\n style={tabStyle(tab === t.id)}\n onClick={() => setTab(t.id)}\n >\n {t.label}\n </button>\n ))}\n </div>\n\n <div role=\"tabpanel\">\n {tab === 'number' && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Preset</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-number-preset\"\n value={state.numberFormatKey}\n onChange={(e) => {\n const key = e.target.value as NumberFormatKey;\n update('numberFormatKey', key);\n update('numberPattern', NUMBER_FORMAT_PATTERNS[key]);\n }}\n >\n {NUMBER_FORMAT_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Pattern</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-number-pattern\"\n value={state.numberPattern}\n onChange={(e) => update('numberPattern', e.target.value)}\n />\n </label>\n </>\n )}\n\n {tab === 'alignment' && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Horizontal</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-align\"\n value={state.align}\n onChange={(e) => update('align', e.target.value as HAlign)}\n >\n <option value=\"left\">Left</option>\n <option value=\"center\">Center</option>\n <option value=\"right\">Right</option>\n </select>\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Vertical</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-valign\"\n value={state.vAlign}\n onChange={(e) => update('vAlign', e.target.value as VAlign)}\n >\n <option value=\"top\">Top</option>\n <option value=\"middle\">Middle</option>\n <option value=\"bottom\">Bottom</option>\n </select>\n </label>\n <label style={CHECK_STYLE} data-testid=\"cs-format-cells-wrap-label\">\n <input\n type=\"checkbox\"\n data-testid=\"cs-format-cells-wrap\"\n checked={state.wrap}\n onChange={(e) => update('wrap', e.target.checked)}\n />\n <span>Wrap text</span>\n </label>\n </>\n )}\n\n {tab === 'font' && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Font</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-font-family\"\n value={state.fontFamily}\n onChange={(e) => update('fontFamily', e.target.value)}\n >\n {FONT_FAMILIES.map((family) => (\n <option key={family} value={family}>\n {family}\n </option>\n ))}\n </select>\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Size</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-font-size\"\n type=\"number\"\n min={6}\n max={72}\n value={state.fontSize}\n onChange={(e) => update('fontSize', e.target.value)}\n />\n </label>\n <label style={CHECK_STYLE}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-format-cells-bold\"\n checked={state.bold}\n onChange={(e) => update('bold', e.target.checked)}\n />\n <span>Bold</span>\n </label>\n <label style={CHECK_STYLE}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-format-cells-italic\"\n checked={state.italic}\n onChange={(e) => update('italic', e.target.checked)}\n />\n <span>Italic</span>\n </label>\n <label style={CHECK_STYLE}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-format-cells-underline\"\n checked={state.underline}\n onChange={(e) => update('underline', e.target.checked)}\n />\n <span>Underline</span>\n </label>\n </>\n )}\n\n {tab === 'border' && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Preset</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-format-cells-border-choice\"\n value={state.borderChoice}\n onChange={(e) => update('borderChoice', e.target.value as BorderChoice)}\n >\n <option value=\"none\">No border</option>\n <option value=\"all\">All borders</option>\n <option value=\"outside\">Outside border</option>\n <option value=\"top\">Top border</option>\n <option value=\"bottom\">Bottom border</option>\n <option value=\"left\">Left border</option>\n <option value=\"right\">Right border</option>\n </select>\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Color</span>\n <input\n style={COLOR_INPUT_STYLE}\n data-testid=\"cs-format-cells-border-color\"\n type=\"color\"\n value={state.borderColor}\n onChange={(e) => update('borderColor', e.target.value)}\n />\n </label>\n </>\n )}\n\n {tab === 'fill' && (\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Fill color</span>\n <input\n style={COLOR_INPUT_STYLE}\n data-testid=\"cs-format-cells-fill-color\"\n type=\"color\"\n value={state.fillColor}\n onChange={(e) => update('fillColor', e.target.value)}\n />\n </label>\n )}\n </div>\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Dialog — the SDK chrome's modal primitive for `<CasualSheets chrome>`.\n *\n * Ported from `apps/web/src/shell/Dialog.tsx`, but decoupled from the app: it\n * uses ONLY React + the chrome's `--cs-chrome-*` token approach (inline styles\n * with DS-token-backed CSS-var fallbacks, the same pattern as FindReplace), so\n * it renders standalone and themes light/dark via the `data-theme` wrapper\n * `<CasualSheets>` already sets. No app CSS classes, no app context.\n *\n * - Click-backdrop and Escape close it.\n * - Body scroll is locked while open.\n * - Focus is trapped (Tab/Shift+Tab cycle within the dialog) and restored to\n * the opener on close — the WAI-ARIA dialog pattern.\n * - Portaled to `document.body` so it escapes the chrome's stacking contexts\n * and the Univer canvas can't intercept clicks meant for the dialog.\n */\n\nimport { useEffect, useRef, type CSSProperties, type ReactNode } from 'react';\nimport { createPortal } from 'react-dom';\nimport { Icon } from './Icon';\n\nexport interface DialogProps {\n /** Heading shown in the dialog header. */\n title: string;\n /** Close request (backdrop click, Escape, the × button, or a footer action). */\n onClose: () => void;\n /** Optional footer node — typically Cancel / primary-action buttons. */\n footer?: ReactNode;\n children: ReactNode;\n /** Max width of the dialog card. Default 460. */\n width?: number;\n ['data-testid']?: string;\n}\n\nconst FOCUSABLE_SELECTOR =\n 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex]:not([tabindex=\"-1\"]), [contenteditable=\"true\"]';\n\nconst BACKDROP_STYLE: CSSProperties = {\n position: 'fixed',\n inset: 0,\n zIndex: 1200,\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'center',\n padding: '8vh 16px 16px',\n background: 'rgba(15, 23, 42, 0.35)',\n overflow: 'auto',\n};\n\nconst CARD_STYLE: CSSProperties = {\n width: '100%',\n background: 'var(--cs-chrome-input-bg, #ffffff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n borderRadius: 10,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n boxShadow: '0 18px 48px rgba(0, 0, 0, 0.28)',\n font: 'inherit',\n fontSize: 13,\n display: 'flex',\n flexDirection: 'column',\n maxHeight: '84vh',\n};\n\nconst HEADER_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 8,\n padding: '12px 16px',\n borderBottom: '1px solid var(--cs-chrome-border, #edeff3)',\n};\n\nconst TITLE_STYLE: CSSProperties = {\n margin: 0,\n fontSize: 15,\n fontWeight: 600,\n color: 'var(--cs-chrome-fg, #201f1e)',\n};\n\nconst CLOSE_STYLE: CSSProperties = {\n width: 28,\n height: 28,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-muted, #605e5c)',\n cursor: 'pointer',\n padding: 0,\n};\n\nconst BODY_STYLE: CSSProperties = {\n padding: 16,\n overflow: 'auto',\n};\n\nconst FOOTER_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: 8,\n padding: '12px 16px',\n borderTop: '1px solid var(--cs-chrome-border, #edeff3)',\n};\n\nexport function Dialog({ title, onClose, footer, children, width = 460, ...rest }: DialogProps) {\n const dialogRef = useRef<HTMLDivElement>(null);\n const openerRef = useRef<HTMLElement | null>(null);\n\n useEffect(() => {\n // Remember who had focus before us so we can restore it on close.\n openerRef.current = (document.activeElement as HTMLElement) ?? null;\n\n // Lock body scroll; pad for the disappearing scrollbar so the grid doesn't\n // shift when the dialog opens.\n const prevOverflow = document.body.style.overflow;\n const prevPaddingRight = document.body.style.paddingRight;\n const scrollbarW = window.innerWidth - document.documentElement.clientWidth;\n document.body.style.overflow = 'hidden';\n if (scrollbarW > 0) document.body.style.paddingRight = `${scrollbarW}px`;\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n e.stopPropagation();\n onClose();\n return;\n }\n if (e.key !== 'Tab') return;\n const root = dialogRef.current;\n if (!root) return;\n const focusables = Array.from(root.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR)).filter(\n (el) => !el.hasAttribute('disabled') && el.offsetParent !== null,\n );\n if (focusables.length === 0) return;\n const first = focusables[0];\n const last = focusables[focusables.length - 1];\n const active = document.activeElement as HTMLElement | null;\n if (e.shiftKey && (active === first || !root.contains(active))) {\n e.preventDefault();\n last.focus();\n } else if (!e.shiftKey && (active === last || !root.contains(active))) {\n e.preventDefault();\n first.focus();\n }\n };\n document.addEventListener('keydown', onKey);\n\n const first = dialogRef.current?.querySelector<HTMLElement>(FOCUSABLE_SELECTOR);\n first?.focus();\n\n return () => {\n document.removeEventListener('keydown', onKey);\n document.body.style.overflow = prevOverflow;\n document.body.style.paddingRight = prevPaddingRight;\n const opener = openerRef.current;\n if (opener && document.contains(opener)) opener.focus();\n };\n }, [onClose]);\n\n return createPortal(\n <div\n style={BACKDROP_STYLE}\n data-testid=\"cs-dialog-backdrop\"\n onMouseDown={(e) => {\n if (e.target === e.currentTarget) onClose();\n }}\n >\n <div\n style={{ ...CARD_STYLE, maxWidth: width }}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n ref={dialogRef}\n data-testid={rest['data-testid']}\n >\n <div style={HEADER_STYLE}>\n <h2 style={TITLE_STYLE}>{title}</h2>\n <button\n type=\"button\"\n style={CLOSE_STYLE}\n data-testid=\"cs-dialog-close\"\n aria-label=\"Close\"\n onClick={onClose}\n >\n <Icon name=\"close\" size={18} />\n </button>\n </div>\n <div style={BODY_STYLE}>{children}</div>\n {footer && <div style={FOOTER_STYLE}>{footer}</div>}\n </div>\n </div>,\n document.body,\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Shared inline styles for built-in SDK dialogs. Kept in their own module (not\n * in Dialog.tsx) so the component files stay component-only for React Fast\n * Refresh. Every value reads a `--cs-chrome-*` token with a hardcoded fallback,\n * matching the chrome's theming approach (light/dark via the `data-theme`\n * wrapper `<CasualSheets>` sets).\n */\n\nimport type { CSSProperties } from 'react';\n\nexport const DIALOG_FIELD_STYLE: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: 4,\n marginBottom: 12,\n};\n\nexport const DIALOG_LABEL_STYLE: CSSProperties = {\n fontSize: 12,\n fontWeight: 500,\n color: 'var(--cs-chrome-muted, #605e5c)',\n};\n\nexport const DIALOG_INPUT_STYLE: CSSProperties = {\n height: 30,\n padding: '0 8px',\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n boxSizing: 'border-box',\n};\n\nexport const DIALOG_BTN_PRIMARY_STYLE: CSSProperties = {\n height: 30,\n padding: '0 14px',\n border: 'none',\n borderRadius: 6,\n background: 'var(--cs-chrome-active-fg, #0e7490)',\n color: '#fff',\n font: 'inherit',\n fontSize: 13,\n fontWeight: 500,\n cursor: 'pointer',\n};\n\nexport const DIALOG_BTN_SECONDARY_STYLE: CSSProperties = {\n height: 30,\n padding: '0 14px',\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n};\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * DataValidationDialog — the SDK chrome's built-in Data Validation modal.\n *\n * The exemplar the other 11 built-in dialogs copy: it reads the active A1\n * selection off the FUniver facade, gathers a validation rule via a small form,\n * and applies it through the `@univerjs/sheets-data-validation` facade — the\n * `univerAPI.newDataValidation()` builder → `.build()` → `FRange.setDataValidation(rule)`\n * pattern (grounded in `sheets-data-validation/lib/types/facade/*.d.ts`). Passing\n * `null` to `setDataValidation` clears the rule, which is how \"Remove rule\" works.\n *\n * Rule types: list of items · whole number · decimal · date · text length ·\n * checkbox. Each maps to a real builder method:\n * - list → `.requireValueInList(values, false, true)`\n * - whole number → `.requireNumber*(…, isInteger=true)`\n * - decimal → `.requireNumber*(…, isInteger=false)`\n * - date → `.requireDate*(Date, …)`\n * - text length → `.requireFormulaSatisfied('=LEN(<anchor>) <op> n')`\n * (the builder has no first-class text-length method — see\n * the facade note below; formula-satisfied is the real,\n * installed fallback)\n * - checkbox → `.requireCheckbox()`\n *\n * Mounted by `<DialogHost>` when `openDialog('data-validation')` is called and no\n * host override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties } from 'react';\n// Side-effect import: installs `FUniver.newDataValidation()` and\n// `FRange.setDataValidation / getDataValidation` on the facade prototype (both\n// the runtime methods AND the TS augmentation of `@univerjs/core/facade` +\n// `@univerjs/sheets/facade`). The `dv` plugin group in univer/lazy-plugins.ts\n// registers the plugin but does NOT import this facade module, so without it the\n// builder/setDataValidation calls below are undefined at runtime. Mirrors the\n// `drawing` / `threadComment` groups' `/facade` side-effect imports.\nimport '@univerjs/sheets-data-validation/facade';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_INPUT_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\n/** Rule families the dialog can build. */\ntype RuleType = 'list' | 'number' | 'decimal' | 'date' | 'textLength' | 'checkbox';\n\n/** Operators for the numeric / text-length / date families. */\ntype Operator =\n | 'between'\n | 'notBetween'\n | 'equal'\n | 'notEqual'\n | 'greater'\n | 'greaterEqual'\n | 'less'\n | 'lessEqual';\n\nconst RULE_TYPE_OPTIONS: Array<{ value: RuleType; label: string }> = [\n { value: 'list', label: 'List of items' },\n { value: 'number', label: 'Whole number' },\n { value: 'decimal', label: 'Decimal' },\n { value: 'date', label: 'Date' },\n { value: 'textLength', label: 'Text length' },\n { value: 'checkbox', label: 'Checkbox' },\n];\n\nconst OPERATOR_OPTIONS: Array<{ value: Operator; label: string }> = [\n { value: 'between', label: 'Between' },\n { value: 'notBetween', label: 'Not between' },\n { value: 'equal', label: 'Equal to' },\n { value: 'notEqual', label: 'Not equal to' },\n { value: 'greater', label: 'Greater than' },\n { value: 'greaterEqual', label: 'Greater than or equal to' },\n { value: 'less', label: 'Less than' },\n { value: 'lessEqual', label: 'Less than or equal to' },\n];\n\n/** True when the operator needs a second operand. */\nfunction isRangeOperator(op: Operator): boolean {\n return op === 'between' || op === 'notBetween';\n}\n\n/** Rule types that carry an operator + operand(s). */\nfunction usesOperator(type: RuleType): boolean {\n return type === 'number' || type === 'decimal' || type === 'date' || type === 'textLength';\n}\n\ninterface DialogState {\n ruleType: RuleType;\n operator: Operator;\n /** Numeric / date / text-length first operand (raw string; parsed on apply). */\n operand1: string;\n /** Second operand, used only for between / notBetween. */\n operand2: string;\n /** Newline-separated list items for the 'list' type. */\n listItems: string;\n ignoreBlank: boolean;\n showErrorMessage: boolean;\n errorMessage: string;\n showInputMessage: boolean;\n inputMessage: string;\n}\n\nconst INITIAL_STATE: DialogState = {\n ruleType: 'list',\n operator: 'between',\n operand1: '',\n operand2: '',\n listItems: '',\n ignoreBlank: true,\n showErrorMessage: false,\n errorMessage: '',\n showInputMessage: false,\n inputMessage: '',\n};\n\n/** The active FRange, or null when there is no selection. */\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/**\n * Build an FDataValidation rule from the form via the sheets-data-validation\n * builder, then apply it (or clear, when `remove` is true). Returns false when\n * there's no active range or the inputs are unusable.\n */\nfunction applyValidation(api: CasualSheetsAPI, s: DialogState, remove: boolean): boolean {\n const range = activeRange(api);\n if (!range) return false;\n\n // The FRange setDataValidation extension is contributed by the\n // sheets-data-validation facade module; typed loosely here so the SDK doesn't\n // hard-depend on the facade's ambient FRange augmentation at this call site.\n const dvRange = range as unknown as {\n setDataValidation: (rule: unknown | null) => unknown;\n getA1Notation?: () => string;\n };\n\n if (remove) {\n dvRange.setDataValidation(null);\n return true;\n }\n\n const builder = api.univer.newDataValidation();\n const n1 = Number(s.operand1);\n const n2 = Number(s.operand2);\n const wholeNumber = s.ruleType === 'number';\n\n switch (s.ruleType) {\n case 'list': {\n const values = s.listItems\n .split(/[\\n,]/)\n .map((v) => v.trim())\n .filter((v) => v.length > 0);\n if (values.length === 0) return false;\n // (values, multiple=false, showDropdown=true)\n builder.requireValueInList(values, false, true);\n break;\n }\n case 'number':\n case 'decimal': {\n if (!Number.isFinite(n1)) return false;\n switch (s.operator) {\n case 'between':\n if (!Number.isFinite(n2)) return false;\n builder.requireNumberBetween(n1, n2, wholeNumber);\n break;\n case 'notBetween':\n if (!Number.isFinite(n2)) return false;\n builder.requireNumberNotBetween(n1, n2, wholeNumber);\n break;\n case 'equal':\n builder.requireNumberEqualTo(n1, wholeNumber);\n break;\n case 'notEqual':\n builder.requireNumberNotEqualTo(n1, wholeNumber);\n break;\n case 'greater':\n builder.requireNumberGreaterThan(n1, wholeNumber);\n break;\n case 'greaterEqual':\n builder.requireNumberGreaterThanOrEqualTo(n1, wholeNumber);\n break;\n case 'less':\n builder.requireNumberLessThan(n1, wholeNumber);\n break;\n case 'lessEqual':\n builder.requireNumberLessThanOrEqualTo(n1, wholeNumber);\n break;\n }\n break;\n }\n case 'date': {\n const d1 = new Date(s.operand1);\n const d2 = new Date(s.operand2);\n if (Number.isNaN(d1.getTime())) return false;\n switch (s.operator) {\n case 'between':\n if (Number.isNaN(d2.getTime())) return false;\n builder.requireDateBetween(d1, d2);\n break;\n case 'notBetween':\n if (Number.isNaN(d2.getTime())) return false;\n builder.requireDateNotBetween(d1, d2);\n break;\n case 'equal':\n builder.requireDateEqualTo(d1);\n break;\n // The builder has no requireDateNotEqualTo; map the remaining operators\n // to the closest available on/after / on/before methods.\n case 'notEqual':\n case 'greater':\n builder.requireDateAfter(d1);\n break;\n case 'greaterEqual':\n builder.requireDateOnOrAfter(d1);\n break;\n case 'less':\n builder.requireDateBefore(d1);\n break;\n case 'lessEqual':\n builder.requireDateOnOrBefore(d1);\n break;\n }\n break;\n }\n case 'textLength': {\n if (!Number.isFinite(n1)) return false;\n // No first-class text-length rule in the installed builder — express it as\n // a per-cell LEN() formula on the range's top-left anchor. Univer offsets\n // the reference relative to each cell in the range (see requireFormulaSatisfied).\n const anchor = dvRange.getA1Notation?.() ?? 'A1';\n const cell = anchor.split(':')[0];\n const len = `LEN(${cell})`;\n let formula: string;\n switch (s.operator) {\n case 'between':\n if (!Number.isFinite(n2)) return false;\n formula = `=AND(${len}>=${n1}, ${len}<=${n2})`;\n break;\n case 'notBetween':\n if (!Number.isFinite(n2)) return false;\n formula = `=OR(${len}<${n1}, ${len}>${n2})`;\n break;\n case 'equal':\n formula = `=${len}=${n1}`;\n break;\n case 'notEqual':\n formula = `=${len}<>${n1}`;\n break;\n case 'greater':\n formula = `=${len}>${n1}`;\n break;\n case 'greaterEqual':\n formula = `=${len}>=${n1}`;\n break;\n case 'less':\n formula = `=${len}<${n1}`;\n break;\n case 'lessEqual':\n formula = `=${len}<=${n1}`;\n break;\n }\n builder.requireFormulaSatisfied(formula);\n break;\n }\n case 'checkbox':\n builder.requireCheckbox();\n break;\n }\n\n builder.setAllowBlank(s.ignoreBlank);\n builder.setOptions({\n showErrorMessage: s.showErrorMessage,\n error: s.showErrorMessage ? s.errorMessage : undefined,\n showInputMessage: s.showInputMessage,\n prompt: s.showInputMessage ? s.inputMessage : undefined,\n });\n\n dvRange.setDataValidation(builder.build());\n return true;\n}\n\nconst CHECK_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n marginBottom: 8,\n cursor: 'pointer',\n};\n\nconst TEXTAREA_STYLE: CSSProperties = {\n ...DIALOG_INPUT_STYLE,\n height: 'auto',\n minHeight: 64,\n padding: '6px 8px',\n resize: 'vertical',\n lineHeight: 1.4,\n};\n\nconst RANGE_NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 12,\n};\n\nconst TWO_COL_STYLE: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: '1fr 1fr',\n gap: 8,\n};\n\nexport function DataValidationDialog({ api, onClose }: DialogComponentProps) {\n const [state, setState] = useState<DialogState>(INITIAL_STATE);\n\n // Read the selection once for the header hint. `getA1Notation` off the live\n // FRange (verified in @univerjs/sheets/facade f-range.d.ts) gives the\n // user-facing A1 label, e.g. \"A1:B2\".\n const rangeLabel = useMemo(() => {\n const fRange = activeRange(api) as unknown as { getA1Notation?: () => string } | null;\n return fRange?.getA1Notation?.() ?? null;\n }, [api]);\n\n const hasSelection = activeRange(api) !== null;\n\n const update = <K extends keyof DialogState>(key: K, value: DialogState[K]) =>\n setState((prev) => ({ ...prev, [key]: value }));\n\n const apply = () => {\n if (applyValidation(api, state, false)) onClose();\n };\n\n const removeRule = () => {\n applyValidation(api, state, true);\n onClose();\n };\n\n const showOperator = usesOperator(state.ruleType);\n const showSecondOperand = showOperator && isRangeOperator(state.operator);\n const operandType = state.ruleType === 'date' ? 'date' : 'number';\n\n return (\n <Dialog\n title=\"Data validation\"\n onClose={onClose}\n width={440}\n data-testid=\"cs-data-validation-dialog\"\n footer={\n <>\n <button\n type=\"button\"\n style={DIALOG_BTN_SECONDARY_STYLE}\n data-testid=\"cs-data-validation-remove\"\n onClick={removeRule}\n >\n Remove rule\n </button>\n <span style={{ flex: 1 }} />\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-data-validation-apply\"\n disabled={!hasSelection}\n onClick={apply}\n >\n Apply\n </button>\n </>\n }\n >\n {hasSelection ? (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-data-validation-range\">\n Applies to <strong>{rangeLabel ?? 'the current selection'}</strong>\n </div>\n ) : (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-data-validation-no-selection\">\n Select one or more cells first, then reopen this dialog.\n </div>\n )}\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Criteria</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-data-validation-type\"\n value={state.ruleType}\n onChange={(e) => update('ruleType', e.target.value as RuleType)}\n >\n {RULE_TYPE_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n\n {state.ruleType === 'list' && (\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Items (one per line, or comma-separated)</span>\n <textarea\n style={TEXTAREA_STYLE}\n data-testid=\"cs-data-validation-list-items\"\n value={state.listItems}\n placeholder={'Yes\\nNo\\nMaybe'}\n onChange={(e) => update('listItems', e.target.value)}\n />\n </label>\n )}\n\n {showOperator && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Condition</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-data-validation-operator\"\n value={state.operator}\n onChange={(e) => update('operator', e.target.value as Operator)}\n >\n {OPERATOR_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n\n <div style={showSecondOperand ? TWO_COL_STYLE : undefined}>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>{showSecondOperand ? 'Minimum' : 'Value'}</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-data-validation-operand1\"\n type={operandType}\n value={state.operand1}\n onChange={(e) => update('operand1', e.target.value)}\n />\n </label>\n {showSecondOperand && (\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Maximum</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-data-validation-operand2\"\n type={operandType}\n value={state.operand2}\n onChange={(e) => update('operand2', e.target.value)}\n />\n </label>\n )}\n </div>\n </>\n )}\n\n {state.ruleType === 'checkbox' && (\n <div style={RANGE_NOTE_STYLE}>\n Each cell in the selection becomes a checkbox (checked = TRUE).\n </div>\n )}\n\n <label style={CHECK_STYLE} data-testid=\"cs-data-validation-ignore-blank-label\">\n <input\n type=\"checkbox\"\n data-testid=\"cs-data-validation-ignore-blank\"\n checked={state.ignoreBlank}\n onChange={(e) => update('ignoreBlank', e.target.checked)}\n />\n <span>Ignore blank cells</span>\n </label>\n\n <label style={CHECK_STYLE}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-data-validation-show-input\"\n checked={state.showInputMessage}\n onChange={(e) => update('showInputMessage', e.target.checked)}\n />\n <span>Show input message</span>\n </label>\n {state.showInputMessage && (\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Input message</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-data-validation-input-message\"\n value={state.inputMessage}\n onChange={(e) => update('inputMessage', e.target.value)}\n />\n </label>\n )}\n\n <label style={CHECK_STYLE}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-data-validation-show-error\"\n checked={state.showErrorMessage}\n onChange={(e) => update('showErrorMessage', e.target.checked)}\n />\n <span>Show error message on invalid input</span>\n </label>\n {state.showErrorMessage && (\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Error message</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-data-validation-error-message\"\n value={state.errorMessage}\n onChange={(e) => update('errorMessage', e.target.value)}\n />\n </label>\n )}\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * ConditionalFormattingDialog — the SDK chrome's built-in Conditional Formatting\n * modal. Sibling of DataValidationDialog / FormatCellsDialog: it reads the active\n * A1 selection off the FUniver facade, gathers a rule via a small form, and\n * applies it through the `@univerjs/sheets-conditional-formatting` facade.\n *\n * Pattern (grounded in\n * `sheets-conditional-formatting/lib/types/facade/*.d.ts`):\n * worksheet.newConditionalFormattingRule() // FConditionalFormattingBuilder\n * .<condition>() // → ConditionalFormatHighlightRuleBuilder\n * .setBackground(fill) / .setFontColor(text)\n * .setRanges([range.getRange()])\n * .build() // → IConditionFormattingRule\n * worksheet.addConditionalFormattingRule(rule)\n *\n * Condition families (each → a real builder method, verified in\n * f-conditional-formatting-builder.d.ts):\n * - Cell value: greater / greaterEqual / less / lessEqual / equal / notEqual /\n * between / notBetween → `.whenNumber*` (L461-609)\n * - Text contains → `.whenTextContains(text)` (L630)\n * - Top N / Bottom N → `.setRank({ isBottom, isPercent, value })` (L227)\n * - Color scale → `.setColorScale(config)` (L853) — its own visual,\n * no fill/text format\n *\n * The \"Clear rules\" action calls `worksheet.clearConditionalFormatRules()`\n * (f-worksheet.d.ts L172) — the whole-sheet clear the facade exposes (there's no\n * range-scoped clear on FWorksheet; FRange.clearConditionalFormatRules exists but\n * is deprecated — see limitations).\n *\n * Mounted by `<DialogHost>` when `openDialog('conditional-formatting')` is called\n * and no host override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties } from 'react';\n// Side-effect import: installs `FWorksheet.newConditionalFormattingRule /\n// addConditionalFormattingRule / clearConditionalFormatRules` (and the FRange\n// mixin) on the facade prototypes AND augments the `@univerjs/sheets/facade`\n// FWorksheet/FRange types. The `cf` plugin group registers the plugin but does\n// NOT import this facade module, so without it the builder calls below are\n// undefined at runtime. Mirrors DataValidationDialog's `/facade` side-effect.\nimport '@univerjs/sheets-conditional-formatting/facade';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_INPUT_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\n/** Rule families the dialog can build. */\ntype RuleType = 'cellValue' | 'textContains' | 'topN' | 'bottomN' | 'colorScale';\n\n/** Operators for the cell-value family. */\ntype Operator =\n | 'greater'\n | 'greaterEqual'\n | 'less'\n | 'lessEqual'\n | 'equal'\n | 'notEqual'\n | 'between'\n | 'notBetween';\n\nconst RULE_TYPE_OPTIONS: Array<{ value: RuleType; label: string }> = [\n { value: 'cellValue', label: 'Cell value' },\n { value: 'textContains', label: 'Text contains' },\n { value: 'topN', label: 'Top N' },\n { value: 'bottomN', label: 'Bottom N' },\n { value: 'colorScale', label: 'Color scale' },\n];\n\nconst OPERATOR_OPTIONS: Array<{ value: Operator; label: string }> = [\n { value: 'greater', label: 'Greater than' },\n { value: 'greaterEqual', label: 'Greater than or equal to' },\n { value: 'less', label: 'Less than' },\n { value: 'lessEqual', label: 'Less than or equal to' },\n { value: 'equal', label: 'Equal to' },\n { value: 'notEqual', label: 'Not equal to' },\n { value: 'between', label: 'Between' },\n { value: 'notBetween', label: 'Not between' },\n];\n\n/** True when the operator needs a second operand. */\nfunction isRangeOperator(op: Operator): boolean {\n return op === 'between' || op === 'notBetween';\n}\n\ninterface DialogState {\n ruleType: RuleType;\n operator: Operator;\n /** Cell-value first operand (raw string; parsed on apply). */\n operand1: string;\n /** Second operand, used only for between / notBetween. */\n operand2: string;\n /** Substring for the text-contains family. */\n text: string;\n /** N for top/bottom N. */\n rankN: string;\n /** Interpret rankN as a percent instead of a count. */\n rankPercent: boolean;\n /** Highlight fill color. */\n fillColor: string;\n /** Highlight text color. */\n textColor: string;\n /** Color-scale endpoints (2-color: min → max). */\n scaleMinColor: string;\n scaleMaxColor: string;\n}\n\nconst INITIAL_STATE: DialogState = {\n ruleType: 'cellValue',\n operator: 'greater',\n operand1: '',\n operand2: '',\n text: '',\n rankN: '10',\n rankPercent: false,\n fillColor: '#fce8b2',\n textColor: '#7f6000',\n scaleMinColor: '#ffffff',\n scaleMaxColor: '#57bb8a',\n};\n\n/** The active FRange, or null when there is no selection. */\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/** The active FWorksheet, or null. */\nfunction activeSheet(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet() ?? null;\n}\n\n/** True when the rule family carries a fill/text highlight format. */\nfunction usesHighlight(type: RuleType): boolean {\n return type !== 'colorScale';\n}\n\n/**\n * Build a conditional-formatting rule from the form via the facade builder and\n * add it to the active sheet, scoped to the active range. Returns false when\n * there's no selection or the inputs are unusable.\n */\nfunction applyRule(api: CasualSheetsAPI, s: DialogState): boolean {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return false;\n\n // The conditional-formatting facade contributes these to FWorksheet at\n // runtime; typed loosely here so the SDK doesn't hard-depend on the ambient\n // FWorksheet augmentation at this call site.\n const cfSheet = sheet as unknown as {\n newConditionalFormattingRule: () => CfBuilder;\n addConditionalFormattingRule: (rule: unknown) => unknown;\n };\n const iRange = (range as unknown as { getRange: () => unknown }).getRange();\n\n const n1 = Number(s.operand1);\n const n2 = Number(s.operand2);\n const rankN = Number(s.rankN);\n\n let builder = cfSheet.newConditionalFormattingRule();\n\n switch (s.ruleType) {\n case 'cellValue': {\n if (!Number.isFinite(n1)) return false;\n switch (s.operator) {\n case 'greater':\n builder = builder.whenNumberGreaterThan(n1);\n break;\n case 'greaterEqual':\n builder = builder.whenNumberGreaterThanOrEqualTo(n1);\n break;\n case 'less':\n builder = builder.whenNumberLessThan(n1);\n break;\n case 'lessEqual':\n builder = builder.whenNumberLessThanOrEqualTo(n1);\n break;\n case 'equal':\n builder = builder.whenNumberEqualTo(n1);\n break;\n case 'notEqual':\n builder = builder.whenNumberNotEqualTo(n1);\n break;\n case 'between':\n if (!Number.isFinite(n2)) return false;\n builder = builder.whenNumberBetween(n1, n2);\n break;\n case 'notBetween':\n if (!Number.isFinite(n2)) return false;\n builder = builder.whenNumberNotBetween(n1, n2);\n break;\n }\n break;\n }\n case 'textContains': {\n const text = s.text.trim();\n if (text.length === 0) return false;\n builder = builder.whenTextContains(text);\n break;\n }\n case 'topN':\n case 'bottomN': {\n if (!Number.isFinite(rankN) || rankN <= 0) return false;\n builder = builder.setRank({\n isBottom: s.ruleType === 'bottomN',\n isPercent: s.rankPercent,\n value: rankN,\n });\n break;\n }\n case 'colorScale': {\n // 2-color scale: min endpoint → max endpoint. Value types 'min'/'max'\n // are the CFValueType string literals (base/const.d.ts CFValueType).\n builder = builder.setColorScale([\n { index: 0, color: s.scaleMinColor, value: { type: 'min' } },\n { index: 1, color: s.scaleMaxColor, value: { type: 'max' } },\n ]);\n break;\n }\n }\n\n if (usesHighlight(s.ruleType)) {\n builder = builder.setBackground(s.fillColor);\n builder = builder.setFontColor(s.textColor);\n }\n\n const rule = builder.setRanges([iRange]).build();\n cfSheet.addConditionalFormattingRule(rule);\n return true;\n}\n\n/**\n * The subset of the conditional-formatting builder chain we use, typed here so\n * the call site is checked without importing the facade's private builder\n * classes. Every method is verified in\n * `sheets-conditional-formatting/lib/types/facade/f-conditional-formatting-builder.d.ts`.\n */\ninterface CfBuilder {\n whenNumberGreaterThan: (v: number) => CfBuilder;\n whenNumberGreaterThanOrEqualTo: (v: number) => CfBuilder;\n whenNumberLessThan: (v: number) => CfBuilder;\n whenNumberLessThanOrEqualTo: (v: number) => CfBuilder;\n whenNumberEqualTo: (v: number) => CfBuilder;\n whenNumberNotEqualTo: (v: number) => CfBuilder;\n whenNumberBetween: (a: number, b: number) => CfBuilder;\n whenNumberNotBetween: (a: number, b: number) => CfBuilder;\n whenTextContains: (t: string) => CfBuilder;\n setRank: (config: { isBottom: boolean; isPercent: boolean; value: number }) => CfBuilder;\n setColorScale: (\n config: Array<{ index: number; color: string; value: { type: string; value?: number } }>,\n ) => CfBuilder;\n setBackground: (color?: string) => CfBuilder;\n setFontColor: (color?: string) => CfBuilder;\n setRanges: (ranges: unknown[]) => CfBuilder;\n build: () => unknown;\n}\n\nconst RANGE_NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 12,\n};\n\nconst CHECK_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n marginBottom: 8,\n cursor: 'pointer',\n};\n\nconst COLOR_INPUT_STYLE: CSSProperties = {\n width: 48,\n height: 30,\n padding: 2,\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n cursor: 'pointer',\n};\n\nconst TWO_COL_STYLE: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: '1fr 1fr',\n gap: 8,\n};\n\nexport function ConditionalFormattingDialog({ api, onClose }: DialogComponentProps) {\n const [state, setState] = useState<DialogState>(INITIAL_STATE);\n\n // Read the selection once for the header hint. `getA1Notation` off the live\n // FRange (verified in @univerjs/sheets/facade f-range.d.ts) gives the\n // user-facing A1 label, e.g. \"A1:B2\".\n const rangeLabel = useMemo(() => {\n const fRange = activeRange(api) as unknown as { getA1Notation?: () => string } | null;\n return fRange?.getA1Notation?.() ?? null;\n }, [api]);\n\n const hasSelection = activeRange(api) !== null;\n\n const update = <K extends keyof DialogState>(key: K, value: DialogState[K]) =>\n setState((prev) => ({ ...prev, [key]: value }));\n\n const apply = () => {\n if (applyRule(api, state)) onClose();\n };\n\n const clearRules = () => {\n const sheet = activeSheet(api) as unknown as {\n clearConditionalFormatRules?: () => unknown;\n } | null;\n sheet?.clearConditionalFormatRules?.();\n onClose();\n };\n\n const showOperator = state.ruleType === 'cellValue';\n const showSecondOperand = showOperator && isRangeOperator(state.operator);\n const isRank = state.ruleType === 'topN' || state.ruleType === 'bottomN';\n\n return (\n <Dialog\n title=\"Conditional formatting\"\n onClose={onClose}\n width={440}\n data-testid=\"cs-conditional-formatting-dialog\"\n footer={\n <>\n <button\n type=\"button\"\n style={DIALOG_BTN_SECONDARY_STYLE}\n data-testid=\"cs-conditional-formatting-clear\"\n onClick={clearRules}\n >\n Clear rules\n </button>\n <span style={{ flex: 1 }} />\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-conditional-formatting-apply\"\n disabled={!hasSelection}\n onClick={apply}\n >\n Apply\n </button>\n </>\n }\n >\n {hasSelection ? (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-conditional-formatting-range\">\n Applies to <strong>{rangeLabel ?? 'the current selection'}</strong>\n </div>\n ) : (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-conditional-formatting-no-selection\">\n Select one or more cells first, then reopen this dialog.\n </div>\n )}\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Condition type</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-conditional-formatting-type\"\n value={state.ruleType}\n onChange={(e) => update('ruleType', e.target.value as RuleType)}\n >\n {RULE_TYPE_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n\n {showOperator && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Condition</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-conditional-formatting-operator\"\n value={state.operator}\n onChange={(e) => update('operator', e.target.value as Operator)}\n >\n {OPERATOR_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n\n <div style={showSecondOperand ? TWO_COL_STYLE : undefined}>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>{showSecondOperand ? 'Minimum' : 'Value'}</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-conditional-formatting-operand1\"\n type=\"number\"\n value={state.operand1}\n onChange={(e) => update('operand1', e.target.value)}\n />\n </label>\n {showSecondOperand && (\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Maximum</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-conditional-formatting-operand2\"\n type=\"number\"\n value={state.operand2}\n onChange={(e) => update('operand2', e.target.value)}\n />\n </label>\n )}\n </div>\n </>\n )}\n\n {state.ruleType === 'textContains' && (\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Text contains</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-conditional-formatting-text\"\n value={state.text}\n placeholder=\"e.g. urgent\"\n onChange={(e) => update('text', e.target.value)}\n />\n </label>\n )}\n\n {isRank && (\n <>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>\n {state.ruleType === 'topN' ? 'Top' : 'Bottom'}{' '}\n {state.rankPercent ? 'percent' : 'count'}\n </span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-conditional-formatting-rank-n\"\n type=\"number\"\n min={1}\n value={state.rankN}\n onChange={(e) => update('rankN', e.target.value)}\n />\n </label>\n <label style={CHECK_STYLE}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-conditional-formatting-rank-percent\"\n checked={state.rankPercent}\n onChange={(e) => update('rankPercent', e.target.checked)}\n />\n <span>Interpret as percent</span>\n </label>\n </>\n )}\n\n {state.ruleType === 'colorScale' ? (\n <div style={TWO_COL_STYLE}>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Min color</span>\n <input\n style={COLOR_INPUT_STYLE}\n data-testid=\"cs-conditional-formatting-scale-min\"\n type=\"color\"\n value={state.scaleMinColor}\n onChange={(e) => update('scaleMinColor', e.target.value)}\n />\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Max color</span>\n <input\n style={COLOR_INPUT_STYLE}\n data-testid=\"cs-conditional-formatting-scale-max\"\n type=\"color\"\n value={state.scaleMaxColor}\n onChange={(e) => update('scaleMaxColor', e.target.value)}\n />\n </label>\n </div>\n ) : (\n <div style={TWO_COL_STYLE}>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Fill color</span>\n <input\n style={COLOR_INPUT_STYLE}\n data-testid=\"cs-conditional-formatting-fill-color\"\n type=\"color\"\n value={state.fillColor}\n onChange={(e) => update('fillColor', e.target.value)}\n />\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Text color</span>\n <input\n style={COLOR_INPUT_STYLE}\n data-testid=\"cs-conditional-formatting-text-color\"\n type=\"color\"\n value={state.textColor}\n onChange={(e) => update('textColor', e.target.value)}\n />\n </label>\n </div>\n )}\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * CustomSortDialog — the SDK chrome's built-in \"Sort range\" modal.\n *\n * Multi-level sort of the active A1 selection: the user adds one or more sort\n * levels (a column + ascending/descending), plus a \"data has header row\" toggle\n * that keeps the header in place and labels the column pickers with the header\n * text. Applied through the `@univerjs/sheets-sort` facade — the\n * `FRange.sort(SortColumnSpec | SortColumnSpec[])` extension, where\n * `SortColumnSpec = { column: number; ascending: boolean } | number` and\n * `column` is 0-based **relative to the sorted range's first column**\n * (verified in `@univerjs/sheets-sort/lib/types/facade/f-range.d.ts` L17-49).\n *\n * The facade `sort()` has no first-class \"has header\" option, so the header row\n * is honoured by sorting a sub-range that starts one row below the selection's\n * top (`FWorksheet.getRange(row, col, numRows, numCols)`, verified in\n * `@univerjs/sheets/lib/types/facade/f-worksheet.d.ts` L258) — the header row is\n * simply excluded from the sorted band, so it stays put.\n *\n * Mounted by `<DialogHost>` when `openDialog('custom-sort')` is called and no\n * host override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties } from 'react';\n// Side-effect import: installs `FRange.sort()` (and the sort mixin's TS\n// augmentation of `@univerjs/sheets/facade`) on the facade prototype. The sort\n// plugin registers the command but does NOT import this facade module, so\n// without it `range.sort(...)` is undefined at runtime. Mirrors the\n// `sheets-data-validation/facade` side-effect import in DataValidationDialog.\nimport '@univerjs/sheets-sort/facade';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_INPUT_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\n/** One sort level: a range-relative column offset + direction. */\ninterface SortLevel {\n /** 0-based offset from the range's first column. */\n column: number;\n ascending: boolean;\n}\n\n/** The `SortColumnSpec` object shape from the sheets-sort facade. */\ntype SortColumnSpec = { column: number; ascending: boolean };\n\n/** The active FRange, or null when there is no selection. */\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/** Minimal shape we lean on off the live FRange (grounded in sheets/facade). */\ninterface RangeGeom {\n getRow(): number;\n getColumn(): number;\n getWidth(): number;\n getHeight(): number;\n getA1Notation?: () => string;\n getValues?: () => Array<Array<unknown>>;\n}\n\n/** Convert a 0-based absolute column index to a spreadsheet letter (A, B, …, AA). */\nfunction columnLetter(index: number): string {\n let n = index;\n let label = '';\n do {\n label = String.fromCharCode(65 + (n % 26)) + label;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n return label;\n}\n\n/** Read geometry + optional header labels off the active range. */\ninterface RangeInfo {\n /** First (absolute) row of the selection. */\n startRow: number;\n /** First (absolute) column of the selection. */\n startColumn: number;\n /** Number of columns in the selection. */\n width: number;\n /** Number of rows in the selection. */\n height: number;\n /** A1 label for the header note, e.g. \"A1:C10\". */\n a1: string | null;\n /** Values of the first row (header candidates), if readable. */\n firstRow: Array<unknown> | null;\n}\n\nfunction readRangeInfo(api: CasualSheetsAPI): RangeInfo | null {\n const range = activeRange(api) as unknown as RangeGeom | null;\n if (!range) return null;\n const values = range.getValues?.();\n return {\n startRow: range.getRow(),\n startColumn: range.getColumn(),\n width: range.getWidth(),\n height: range.getHeight(),\n a1: range.getA1Notation?.() ?? null,\n firstRow: values && values.length > 0 ? values[0] : null,\n };\n}\n\n/**\n * Apply the multi-level sort via the sheets-sort facade. Returns false when\n * there's no selection or nothing sensible to sort.\n */\nfunction applySort(\n api: CasualSheetsAPI,\n info: RangeInfo,\n levels: SortLevel[],\n hasHeader: boolean,\n): boolean {\n const worksheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!worksheet) return false;\n\n // When the data has a header row, exclude it from the sorted band so it stays\n // pinned at the top. Otherwise sort the whole selection.\n const bandStartRow = hasHeader ? info.startRow + 1 : info.startRow;\n const bandHeight = hasHeader ? info.height - 1 : info.height;\n if (bandHeight <= 0) return false;\n\n // getRange(row, column, numRows, numColumns) — sheets/facade f-worksheet.d.ts L258.\n const band = (\n worksheet as unknown as {\n getRange: (row: number, col: number, numRows: number, numCols: number) => unknown;\n }\n ).getRange(bandStartRow, info.startColumn, bandHeight, info.width);\n\n // Clamp each level's column offset to the range and drop invalid ones.\n const specs: SortColumnSpec[] = levels\n .filter((l) => l.column >= 0 && l.column < info.width)\n .map((l) => ({ column: l.column, ascending: l.ascending }));\n if (specs.length === 0) return false;\n\n // FRange.sort(SortColumnSpec[]) — sheets-sort/facade f-range.d.ts L46. Column\n // indices are relative to the (sub-)range's first column, which is exactly the\n // 0-based offset the pickers produce.\n (band as { sort: (c: SortColumnSpec | SortColumnSpec[]) => unknown }).sort(specs);\n return true;\n}\n\nconst RANGE_NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 12,\n};\n\nconst CHECK_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n marginBottom: 12,\n cursor: 'pointer',\n};\n\nconst LEVEL_ROW_STYLE: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: 'auto 1fr 130px 28px',\n alignItems: 'center',\n gap: 8,\n marginBottom: 8,\n};\n\nconst LEVEL_PREFIX_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n whiteSpace: 'nowrap',\n};\n\nconst REMOVE_BTN_STYLE: CSSProperties = {\n width: 28,\n height: 30,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-muted, #605e5c)',\n cursor: 'pointer',\n padding: 0,\n fontSize: 16,\n lineHeight: 1,\n};\n\nconst ADD_BTN_STYLE: CSSProperties = {\n ...DIALOG_BTN_SECONDARY_STYLE,\n marginTop: 4,\n};\n\nexport function CustomSortDialog({ api, onClose }: DialogComponentProps) {\n // Read the selection once when the dialog mounts.\n const info = useMemo(() => readRangeInfo(api), [api]);\n const hasSelection = info !== null;\n const width = info?.width ?? 1;\n\n const [hasHeader, setHasHeader] = useState(false);\n const [levels, setLevels] = useState<SortLevel[]>([{ column: 0, ascending: true }]);\n\n // Column option labels: header text when \"has header\" is on and text exists,\n // otherwise the absolute spreadsheet column letter.\n const columnOptions = useMemo(() => {\n const startCol = info?.startColumn ?? 0;\n return Array.from({ length: width }, (_, offset) => {\n const headerCell = hasHeader ? info?.firstRow?.[offset] : undefined;\n const headerText =\n headerCell !== undefined && headerCell !== null && String(headerCell).trim() !== ''\n ? String(headerCell)\n : null;\n const letter = columnLetter(startCol + offset);\n return {\n value: offset,\n label: headerText ? `${headerText} (${letter})` : `Column ${letter}`,\n };\n });\n }, [width, hasHeader, info]);\n\n const updateLevel = (index: number, patch: Partial<SortLevel>) =>\n setLevels((prev) => prev.map((l, i) => (i === index ? { ...l, ...patch } : l)));\n\n const addLevel = () => {\n // Default the new level to the first column not already used, else column 0.\n const used = new Set(levels.map((l) => l.column));\n let next = 0;\n for (let c = 0; c < width; c += 1) {\n if (!used.has(c)) {\n next = c;\n break;\n }\n }\n setLevels((prev) => [...prev, { column: next, ascending: true }]);\n };\n\n const removeLevel = (index: number) =>\n setLevels((prev) => (prev.length <= 1 ? prev : prev.filter((_, i) => i !== index)));\n\n const apply = () => {\n if (info && applySort(api, info, levels, hasHeader)) onClose();\n };\n\n const canApply = hasSelection && levels.length > 0;\n\n return (\n <Dialog\n title=\"Sort range\"\n onClose={onClose}\n width={480}\n data-testid=\"cs-custom-sort-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-custom-sort-apply\"\n disabled={!canApply}\n onClick={apply}\n >\n Sort\n </button>\n </>\n }\n >\n {hasSelection ? (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-custom-sort-range\">\n Sort <strong>{info?.a1 ?? 'the current selection'}</strong>\n </div>\n ) : (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-custom-sort-no-selection\">\n Select the range you want to sort first, then reopen this dialog.\n </div>\n )}\n\n <label style={CHECK_STYLE} data-testid=\"cs-custom-sort-has-header-label\">\n <input\n type=\"checkbox\"\n data-testid=\"cs-custom-sort-has-header\"\n checked={hasHeader}\n onChange={(e) => setHasHeader(e.target.checked)}\n />\n <span>Data has header row</span>\n </label>\n\n <div style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Sort by</span>\n {levels.map((level, index) => (\n <div key={index} style={LEVEL_ROW_STYLE} data-testid={`cs-custom-sort-level-${index}`}>\n <span style={LEVEL_PREFIX_STYLE}>{index === 0 ? 'Sort by' : 'then by'}</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid={`cs-custom-sort-column-${index}`}\n value={level.column}\n onChange={(e) => updateLevel(index, { column: Number(e.target.value) })}\n >\n {columnOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid={`cs-custom-sort-order-${index}`}\n value={level.ascending ? 'asc' : 'desc'}\n onChange={(e) => updateLevel(index, { ascending: e.target.value === 'asc' })}\n >\n <option value=\"asc\">A → Z (ascending)</option>\n <option value=\"desc\">Z → A (descending)</option>\n </select>\n <button\n type=\"button\"\n style={REMOVE_BTN_STYLE}\n data-testid={`cs-custom-sort-remove-${index}`}\n aria-label=\"Remove sort level\"\n disabled={levels.length <= 1}\n onClick={() => removeLevel(index)}\n >\n −\n </button>\n </div>\n ))}\n\n <button\n type=\"button\"\n style={ADD_BTN_STYLE}\n data-testid=\"cs-custom-sort-add-level\"\n disabled={levels.length >= width}\n onClick={addLevel}\n >\n Add another sort level\n </button>\n </div>\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * PasteSpecialDialog — the SDK chrome's built-in Paste Special modal.\n *\n * Copies the DataValidationDialog/FormatCellsDialog structure: reads the active\n * A1 selection off the FUniver facade, gathers a mode via a small form, and\n * applies through real Univer commands / facade calls (no app context).\n *\n * Modes → mechanism (all grounded in the INSTALLED @univerjs/sheets-ui build):\n * - values → `sheet.command.paste` with `{ value: 'special-paste-value' }`\n * - formats → `sheet.command.paste` with `{ value: 'special-paste-format' }`\n * - formulas → `sheet.command.paste` with `{ value: 'special-paste-formula' }`\n *\n * The special-paste hook names live in `PREDEFINED_HOOK_NAME_PASTE`\n * (sheets-ui/lib/es/index.js: SPECIAL_PASTE_VALUE/FORMAT/FORMULA), and the\n * dedicated `SheetPasteValueCommand`/`SheetPasteFormatCommand` handlers just\n * forward `SheetPasteCommand.id` (= 'sheet.command.paste', name verified in\n * the same build) with those `{ value }` params. We dispatch the base\n * `sheet.command.paste` with the matching hook value so all three modes go\n * through one real, installed command — including 'formulas', which has no\n * dedicated `sheet.command.paste-*` id but IS a valid paste hook.\n *\n * - transpose → in-place matrix flip via the sheets facade:\n * `FRange.getValues()` → transpose → `getRange(row, col, cols, rows)` →\n * `.setValues()`. There is NO transpose paste command anywhere in the\n * installed sheets/sheets-ui build (grep 'transpose' returns nothing), so\n * rather than stub it we transpose the CURRENT selection in place using the\n * real `getValues`/`getRange`/`setValues` facade methods (verified in\n * @univerjs/sheets/facade f-range.d.ts + f-worksheet.d.ts). See the\n * `limitations` note: this transposes the selection itself, not clipboard\n * contents (the facade exposes no clipboard-transpose primitive).\n *\n * Mounted by `<DialogHost>` when `openDialog('paste-special')` is called and no\n * host override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties } from 'react';\n// Side-effect import: installs the sheets-ui facade extensions and registers\n// the clipboard/paste commands on the FUniver facade so\n// `executeCommand('sheet.command.paste', …)` resolves at runtime. Mirrors the\n// `@univerjs/sheets/facade` side-effect import the SDK's api.ts already does for\n// the core sheets mixins.\nimport '@univerjs/sheets-ui/facade';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\n/** Paste-special modes this dialog offers. */\ntype PasteMode = 'values' | 'formats' | 'formulas' | 'transpose';\n\nconst MODE_OPTIONS: Array<{ value: PasteMode; label: string; hint: string }> = [\n {\n value: 'values',\n label: 'Values only',\n hint: 'Paste cell values, dropping formatting and formulas.',\n },\n {\n value: 'formats',\n label: 'Formats only',\n hint: 'Paste number formats, fonts, borders and fills — no values.',\n },\n {\n value: 'formulas',\n label: 'Formulas only',\n hint: 'Paste formulas, adjusting relative references.',\n },\n {\n value: 'transpose',\n label: 'Transpose',\n hint: 'Flip the current selection — rows become columns and columns become rows, in place.',\n },\n];\n\n/** Paste hook names from sheets-ui `PREDEFINED_HOOK_NAME_PASTE`. */\nconst PASTE_HOOK: Record<'values' | 'formats' | 'formulas', string> = {\n values: 'special-paste-value',\n formats: 'special-paste-format',\n formulas: 'special-paste-formula',\n};\n\n/** The base sheets paste command; the special modes are `{ value: <hook> }`. */\nconst SHEET_PASTE_COMMAND = 'sheet.command.paste';\n\n/** Minimal shape of the FRange we lean on for the transpose path. */\ninterface TransposableRange {\n getRow(): number;\n getColumn(): number;\n getWidth(): number;\n getHeight(): number;\n getValues(): unknown[][];\n getA1Notation?(): string;\n}\n\n/** The active FRange, or null when there is no selection. */\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/**\n * Transpose the current selection in place using the sheets facade: read the\n * value matrix, flip it, then write it back into a range whose rows/columns are\n * swapped, anchored at the same top-left cell. Returns false when there is no\n * selection or nothing to transpose.\n */\nfunction transposeSelection(api: CasualSheetsAPI): boolean {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n const range = sheet?.getActiveRange() as unknown as TransposableRange | null;\n if (!sheet || !range) return false;\n\n const rows = range.getHeight();\n const cols = range.getWidth();\n if (rows <= 0 || cols <= 0) return false;\n\n const values = range.getValues();\n const transposed: unknown[][] = [];\n for (let c = 0; c < cols; c++) {\n const newRow: unknown[] = [];\n for (let r = 0; r < rows; r++) {\n newRow.push(values[r]?.[c] ?? null);\n }\n transposed.push(newRow);\n }\n\n // New range: same anchor, swapped dimensions (cols rows × rows columns).\n const target = sheet.getRange(range.getRow(), range.getColumn(), cols, rows) as unknown as {\n setValues: (v: unknown[][]) => unknown;\n };\n target.setValues(transposed);\n return true;\n}\n\n/**\n * Apply the chosen paste-special mode. Values/formats/formulas dispatch the real\n * `sheet.command.paste` with the matching special-paste hook; transpose flips the\n * selection in place. Returns a promise that resolves to whether it ran.\n */\nasync function applyPasteSpecial(api: CasualSheetsAPI, mode: PasteMode): Promise<boolean> {\n if (activeRange(api) === null) return false;\n\n if (mode === 'transpose') {\n return transposeSelection(api);\n }\n\n return api.executeCommand(SHEET_PASTE_COMMAND, { value: PASTE_HOOK[mode] });\n}\n\nconst MODE_RADIO_ROW_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'flex-start',\n gap: 8,\n padding: '8px 10px',\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n marginBottom: 8,\n cursor: 'pointer',\n};\n\nconst MODE_RADIO_ROW_ACTIVE_STYLE: CSSProperties = {\n ...MODE_RADIO_ROW_STYLE,\n borderColor: 'var(--cs-chrome-active-fg, #0e7490)',\n background: 'var(--cs-chrome-active-bg, rgba(14, 116, 144, 0.06))',\n};\n\nconst MODE_LABEL_STYLE: CSSProperties = {\n fontSize: 13,\n fontWeight: 500,\n color: 'var(--cs-chrome-fg, #201f1e)',\n};\n\nconst MODE_HINT_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginTop: 2,\n lineHeight: 1.35,\n};\n\nconst RANGE_NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 12,\n};\n\nexport function PasteSpecialDialog({ api, onClose }: DialogComponentProps) {\n const [mode, setMode] = useState<PasteMode>('values');\n\n // Read the selection once for the header hint (getA1Notation is verified on\n // the sheets facade FRange — f-range.d.ts).\n const rangeLabel = useMemo(() => {\n const fRange = activeRange(api) as unknown as { getA1Notation?: () => string } | null;\n return fRange?.getA1Notation?.() ?? null;\n }, [api]);\n\n const hasSelection = activeRange(api) !== null;\n\n const apply = () => {\n void applyPasteSpecial(api, mode).then((ok) => {\n if (ok) onClose();\n });\n };\n\n return (\n <Dialog\n title=\"Paste special\"\n onClose={onClose}\n width={440}\n data-testid=\"cs-paste-special-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-paste-special-apply\"\n disabled={!hasSelection}\n onClick={apply}\n >\n Paste\n </button>\n </>\n }\n >\n {hasSelection ? (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-paste-special-range\">\n {mode === 'transpose' ? 'Transposes' : 'Pastes into'}{' '}\n <strong>{rangeLabel ?? 'the current selection'}</strong>\n </div>\n ) : (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-paste-special-no-selection\">\n Select the destination cell(s) first, then reopen this dialog.\n </div>\n )}\n\n <div style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Paste</span>\n <div role=\"radiogroup\" aria-label=\"Paste special mode\">\n {MODE_OPTIONS.map((opt) => {\n const active = mode === opt.value;\n return (\n <label\n key={opt.value}\n style={active ? MODE_RADIO_ROW_ACTIVE_STYLE : MODE_RADIO_ROW_STYLE}\n data-testid={`cs-paste-special-mode-${opt.value}`}\n >\n <input\n type=\"radio\"\n name=\"cs-paste-special-mode\"\n value={opt.value}\n checked={active}\n onChange={() => setMode(opt.value)}\n style={{ marginTop: 2 }}\n />\n <span>\n <span style={MODE_LABEL_STYLE}>{opt.label}</span>\n <span style={MODE_HINT_STYLE}>{opt.hint}</span>\n </span>\n </label>\n );\n })}\n </div>\n </div>\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * InsertFunctionDialog — the SDK chrome's built-in Insert Function picker.\n *\n * A searchable, category-grouped list of common spreadsheet functions. Picking a\n * function seeds the active cell with `=NAME(` so the user can type arguments,\n * then focuses the grid. Applying is grounded in the real Sheets FUniver facade:\n * - `api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange()` gives\n * the live FRange (see FormatCellsDialog `activeRange`);\n * - `FRange.setValue('=NAME(')` writes the formula stub into the range's\n * top-left cell (verified in `@univerjs/sheets/lib/types/facade/f-range.d.ts`\n * L814 `setValue(value: CellValue | ICellData): FRange`);\n * - `FRange.getA1Notation()` (f-range.d.ts L1220) labels the target cell;\n * - `api.focus()` returns keyboard focus to the grid for argument entry.\n *\n * Note on the caret: the installed FRange facade has no \"enter cell edit mode\n * with the caret parked after the open-paren\" method — `setValue` commits the\n * cell content and Univer re-parses it. So on choose we write `=NAME(` and focus\n * the grid; the user double-clicks / F2s to continue typing arguments. That's the\n * closest real, installed behaviour (recorded in the dialog's limitations).\n *\n * Mounted by `<DialogHost>` when `openDialog('insert-function')` is called and no\n * host override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties } from 'react';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_INPUT_STYLE,\n} from './dialog-styles';\n\n/** A single function entry in the picker. */\ninterface FunctionEntry {\n /** Canonical function name (upper-case), inserted verbatim. */\n name: string;\n /** Category bucket for grouping. */\n category: string;\n /** One-line description shown under the list / in the preview. */\n description: string;\n /** Argument-signature hint shown in the preview, e.g. `SUM(value1, [value2, …])`. */\n syntax: string;\n}\n\n/**\n * The common-function catalog. Deliberately a focused, Google-Sheets-style\n * \"common functions\" set rather than the full library — this is a quick-insert\n * picker, not a reference. Grouped by `category`.\n */\nconst FUNCTIONS: FunctionEntry[] = [\n // Math\n {\n name: 'SUM',\n category: 'Math',\n description: 'Sum of a set of numbers.',\n syntax: 'SUM(value1, [value2, …])',\n },\n {\n name: 'PRODUCT',\n category: 'Math',\n description: 'Product of a set of numbers.',\n syntax: 'PRODUCT(factor1, [factor2, …])',\n },\n {\n name: 'ROUND',\n category: 'Math',\n description: 'Round a number to a given number of places.',\n syntax: 'ROUND(value, [places])',\n },\n {\n name: 'ABS',\n category: 'Math',\n description: 'Absolute value of a number.',\n syntax: 'ABS(value)',\n },\n {\n name: 'MOD',\n category: 'Math',\n description: 'Remainder after division.',\n syntax: 'MOD(dividend, divisor)',\n },\n {\n name: 'POWER',\n category: 'Math',\n description: 'A number raised to a power.',\n syntax: 'POWER(base, exponent)',\n },\n // Statistical\n {\n name: 'AVERAGE',\n category: 'Statistical',\n description: 'Arithmetic mean of a set of numbers.',\n syntax: 'AVERAGE(value1, [value2, …])',\n },\n {\n name: 'COUNT',\n category: 'Statistical',\n description: 'Count of numeric values in a range.',\n syntax: 'COUNT(value1, [value2, …])',\n },\n {\n name: 'COUNTA',\n category: 'Statistical',\n description: 'Count of non-empty values in a range.',\n syntax: 'COUNTA(value1, [value2, …])',\n },\n {\n name: 'MAX',\n category: 'Statistical',\n description: 'Largest value in a set.',\n syntax: 'MAX(value1, [value2, …])',\n },\n {\n name: 'MIN',\n category: 'Statistical',\n description: 'Smallest value in a set.',\n syntax: 'MIN(value1, [value2, …])',\n },\n {\n name: 'MEDIAN',\n category: 'Statistical',\n description: 'Median of a set of numbers.',\n syntax: 'MEDIAN(value1, [value2, …])',\n },\n // Logical\n {\n name: 'IF',\n category: 'Logical',\n description: 'Return one value if a condition is true, another if false.',\n syntax: 'IF(condition, value_if_true, value_if_false)',\n },\n {\n name: 'IFS',\n category: 'Logical',\n description: 'Test multiple conditions, return the first match.',\n syntax: 'IFS(condition1, value1, [condition2, value2, …])',\n },\n {\n name: 'AND',\n category: 'Logical',\n description: 'True when all arguments are true.',\n syntax: 'AND(logical1, [logical2, …])',\n },\n {\n name: 'OR',\n category: 'Logical',\n description: 'True when any argument is true.',\n syntax: 'OR(logical1, [logical2, …])',\n },\n {\n name: 'IFERROR',\n category: 'Logical',\n description: 'Return a fallback when a formula errors.',\n syntax: 'IFERROR(value, value_if_error)',\n },\n // Lookup\n {\n name: 'VLOOKUP',\n category: 'Lookup',\n description: 'Search a column for a key, return a value from the same row.',\n syntax: 'VLOOKUP(search_key, range, index, [is_sorted])',\n },\n {\n name: 'HLOOKUP',\n category: 'Lookup',\n description: 'Search a row for a key, return a value from the same column.',\n syntax: 'HLOOKUP(search_key, range, index, [is_sorted])',\n },\n {\n name: 'INDEX',\n category: 'Lookup',\n description: 'Value at a given row/column offset in a range.',\n syntax: 'INDEX(reference, [row], [column])',\n },\n {\n name: 'MATCH',\n category: 'Lookup',\n description: 'Position of a value within a range.',\n syntax: 'MATCH(search_key, range, [search_type])',\n },\n {\n name: 'XLOOKUP',\n category: 'Lookup',\n description: 'Search a range and return a corresponding value.',\n syntax: 'XLOOKUP(search_key, lookup_range, result_range)',\n },\n // Text\n {\n name: 'CONCATENATE',\n category: 'Text',\n description: 'Join strings end to end.',\n syntax: 'CONCATENATE(string1, [string2, …])',\n },\n {\n name: 'LEFT',\n category: 'Text',\n description: 'Leftmost characters of a string.',\n syntax: 'LEFT(string, [num_chars])',\n },\n {\n name: 'RIGHT',\n category: 'Text',\n description: 'Rightmost characters of a string.',\n syntax: 'RIGHT(string, [num_chars])',\n },\n {\n name: 'MID',\n category: 'Text',\n description: 'Characters from the middle of a string.',\n syntax: 'MID(string, start, length)',\n },\n { name: 'LEN', category: 'Text', description: 'Length of a string.', syntax: 'LEN(string)' },\n {\n name: 'TRIM',\n category: 'Text',\n description: 'Remove leading/trailing/duplicate spaces.',\n syntax: 'TRIM(string)',\n },\n // Date\n { name: 'TODAY', category: 'Date', description: \"Today's date.\", syntax: 'TODAY()' },\n { name: 'NOW', category: 'Date', description: 'Current date and time.', syntax: 'NOW()' },\n {\n name: 'DATE',\n category: 'Date',\n description: 'Build a date from year, month, day.',\n syntax: 'DATE(year, month, day)',\n },\n {\n name: 'DATEDIF',\n category: 'Date',\n description: 'Difference between two dates in a chosen unit.',\n syntax: 'DATEDIF(start_date, end_date, unit)',\n },\n];\n\n/** Ordered category list, so groups render in a stable, sensible order. */\nconst CATEGORY_ORDER = ['Math', 'Statistical', 'Logical', 'Lookup', 'Text', 'Date'];\n\n/** The active FRange, or null when there is no selection. */\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/**\n * Insert `=NAME(` into the top-left cell of the active range via the facade,\n * then focus the grid for argument entry. Returns false when there's no\n * selection to write into.\n */\nfunction insertFunction(api: CasualSheetsAPI, fn: FunctionEntry): boolean {\n const range = activeRange(api);\n if (!range) return false;\n\n // Zero-arg functions (TODAY / NOW) are complete on their own; for the rest,\n // leave the open-paren so the user continues typing arguments.\n const zeroArg = fn.syntax.endsWith('()');\n const formula = zeroArg ? `=${fn.name}()` : `=${fn.name}(`;\n\n // FRange.setValue writes into the range's top-left cell (f-range.d.ts L814).\n range.setValue(formula);\n\n // Return keyboard focus to the grid so the user can keep typing arguments.\n api.focus();\n return true;\n}\n\nconst SEARCH_STYLE: CSSProperties = {\n ...DIALOG_INPUT_STYLE,\n width: '100%',\n marginBottom: 12,\n};\n\nconst RANGE_NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 12,\n};\n\nconst LIST_STYLE: CSSProperties = {\n maxHeight: 280,\n overflow: 'auto',\n border: '1px solid var(--cs-chrome-border, #edeff3)',\n borderRadius: 8,\n};\n\nconst GROUP_HEADER_STYLE: CSSProperties = {\n position: 'sticky',\n top: 0,\n padding: '6px 12px',\n fontSize: 11,\n fontWeight: 600,\n letterSpacing: 0.4,\n textTransform: 'uppercase',\n color: 'var(--cs-chrome-muted, #605e5c)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n borderBottom: '1px solid var(--cs-chrome-border, #edeff3)',\n};\n\nfunction itemStyle(selected: boolean): CSSProperties {\n return {\n display: 'block',\n width: '100%',\n textAlign: 'left',\n padding: '8px 12px',\n border: 'none',\n borderBottom: '1px solid var(--cs-chrome-border, #f3f4f6)',\n background: selected ? 'var(--cs-chrome-hover-bg, #eef6f8)' : 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n };\n}\n\nconst ITEM_NAME_STYLE: CSSProperties = {\n fontWeight: 600,\n fontFamily: 'var(--cs-chrome-mono, ui-monospace, SFMono-Regular, Menlo, monospace)',\n};\n\nconst ITEM_DESC_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginTop: 2,\n};\n\nconst PREVIEW_STYLE: CSSProperties = {\n marginTop: 12,\n padding: '10px 12px',\n borderRadius: 8,\n background: 'var(--cs-chrome-subtle-bg, #f6f8fa)',\n fontSize: 12,\n color: 'var(--cs-chrome-fg, #201f1e)',\n};\n\nconst PREVIEW_SYNTAX_STYLE: CSSProperties = {\n fontFamily: 'var(--cs-chrome-mono, ui-monospace, SFMono-Regular, Menlo, monospace)',\n fontWeight: 600,\n marginBottom: 4,\n};\n\nexport function InsertFunctionDialog({ api, onClose }: DialogComponentProps) {\n const [query, setQuery] = useState('');\n const [selectedName, setSelectedName] = useState<string | null>(null);\n\n // Label the target cell once for the header hint.\n const rangeLabel = useMemo(() => {\n const fRange = activeRange(api) as unknown as { getA1Notation?: () => string } | null;\n return fRange?.getA1Notation?.() ?? null;\n }, [api]);\n\n const hasSelection = activeRange(api) !== null;\n\n // Filter by name / description / category, case-insensitive.\n const filtered = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return FUNCTIONS;\n return FUNCTIONS.filter(\n (fn) =>\n fn.name.toLowerCase().includes(q) ||\n fn.description.toLowerCase().includes(q) ||\n fn.category.toLowerCase().includes(q),\n );\n }, [query]);\n\n // Group the filtered set by category, preserving CATEGORY_ORDER.\n const grouped = useMemo(() => {\n const byCat = new Map<string, FunctionEntry[]>();\n for (const fn of filtered) {\n const list = byCat.get(fn.category);\n if (list) list.push(fn);\n else byCat.set(fn.category, [fn]);\n }\n return CATEGORY_ORDER.filter((c) => byCat.has(c)).map((c) => ({\n category: c,\n items: byCat.get(c)!,\n }));\n }, [filtered]);\n\n const selected = useMemo(\n () => FUNCTIONS.find((fn) => fn.name === selectedName) ?? null,\n [selectedName],\n );\n\n const choose = (fn: FunctionEntry) => {\n if (insertFunction(api, fn)) onClose();\n };\n\n const insertSelected = () => {\n if (selected && insertFunction(api, selected)) onClose();\n };\n\n return (\n <Dialog\n title=\"Insert function\"\n onClose={onClose}\n width={460}\n data-testid=\"cs-insert-function-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-insert-function-insert\"\n disabled={!hasSelection || !selected}\n onClick={insertSelected}\n >\n Insert\n </button>\n </>\n }\n >\n {hasSelection ? (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-insert-function-range\">\n Inserts into <strong>{rangeLabel ?? 'the active cell'}</strong>\n </div>\n ) : (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-insert-function-no-selection\">\n Select a cell first, then reopen this dialog.\n </div>\n )}\n\n <input\n style={SEARCH_STYLE}\n data-testid=\"cs-insert-function-search\"\n type=\"search\"\n placeholder=\"Search functions (name, category, or description)\"\n value={query}\n autoFocus\n onChange={(e) => setQuery(e.target.value)}\n />\n\n <div\n style={LIST_STYLE}\n role=\"listbox\"\n aria-label=\"Functions\"\n data-testid=\"cs-insert-function-list\"\n >\n {grouped.length === 0 && (\n <div style={{ padding: '12px', fontSize: 13, color: 'var(--cs-chrome-muted, #605e5c)' }}>\n No functions match &ldquo;{query}&rdquo;.\n </div>\n )}\n {grouped.map((group) => (\n <div key={group.category}>\n <div style={GROUP_HEADER_STYLE}>{group.category}</div>\n {group.items.map((fn) => (\n <button\n key={fn.name}\n type=\"button\"\n role=\"option\"\n aria-selected={selectedName === fn.name}\n data-testid={`cs-insert-function-item-${fn.name}`}\n style={itemStyle(selectedName === fn.name)}\n onClick={() => setSelectedName(fn.name)}\n onDoubleClick={() => choose(fn)}\n >\n <div style={ITEM_NAME_STYLE}>{fn.name}</div>\n <div style={ITEM_DESC_STYLE}>{fn.description}</div>\n </button>\n ))}\n </div>\n ))}\n </div>\n\n {selected && (\n <div style={PREVIEW_STYLE} data-testid=\"cs-insert-function-preview\">\n <div style={PREVIEW_SYNTAX_STYLE}>{selected.syntax}</div>\n <div>{selected.description}</div>\n </div>\n )}\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * NameManagerDialog — the SDK chrome's built-in Name Manager (defined names).\n *\n * Mirrors the Data Validation / Format Cells exemplars: it reaches the workbook\n * off the FUniver facade and drives the workbook's defined-name API to list,\n * add, edit, and delete named ranges. Grounded in\n * `@univerjs/sheets/lib/types/facade/f-workbook.d.ts`:\n * - `getDefinedNames(): FDefinedName[]` (L571)\n * - `getDefinedName(name): FDefinedName | null` (L559)\n * - `insertDefinedName(name, formulaOrRefString): FWorkbook` (L639)\n * - `deleteDefinedName(name): boolean` (L651)\n * - `updateDefinedNameBuilder(param): void` (L626)\n * and `f-defined-name.d.ts`: `FDefinedName.getName()` (L221) /\n * `getFormulaOrRefString()` (L265) / `toBuilder()` (L385); the builder's\n * `setName` (L44) / `setRef` (L74) / `build()` (L175). The \"add from selection\"\n * ref comes from `FRange.getA1Notation(true)` (sheet-qualified, e.g.\n * `Sheet1!A1:B2` — `f-range.d.ts` L1220), which is exactly the shape\n * `insertDefinedName`'s `formulaOrRefString` accepts.\n *\n * Univer's defined-name API is unscoped by name (no id needed here): to \"edit\" a\n * name we rebuild it from `getDefinedName(oldName).toBuilder()`, preserving its\n * identity while updating name + ref, then `updateDefinedNameBuilder`.\n *\n * Mounted by `<DialogHost>` when `openDialog('name-manager')` is called and no\n * host override is registered.\n */\n\nimport { useCallback, useMemo, useState, type CSSProperties } from 'react';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_INPUT_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\n/** Minimal shape of the FDefinedNameBuilder chain we use (grounded in f-defined-name.ts). */\ninterface FDefinedNameBuilderLike {\n setName(name: string): FDefinedNameBuilderLike;\n setRef(a1Notation: string): FDefinedNameBuilderLike;\n build(): unknown;\n}\n\n/** Minimal shape of an FDefinedName we read (grounded in f-defined-name.ts). */\ninterface FDefinedNameLike {\n getName(): string;\n getFormulaOrRefString(): string;\n toBuilder(): FDefinedNameBuilderLike;\n}\n\n/** Minimal shape of the FWorkbook defined-name surface (grounded in f-workbook.d.ts). */\ninterface FWorkbookLike {\n getDefinedNames(): FDefinedNameLike[];\n getDefinedName(name: string): FDefinedNameLike | null;\n insertDefinedName(name: string, formulaOrRefString: string): unknown;\n deleteDefinedName(name: string): boolean;\n updateDefinedNameBuilder(param: unknown): void;\n getActiveSheet(): {\n getActiveRange(): { getA1Notation(withSheet?: boolean): string } | null;\n } | null;\n}\n\ninterface NameRow {\n name: string;\n refersTo: string;\n}\n\n/** Names must start with a letter/underscore and avoid A1-like tokens; keep it\n * loose but block the common mistakes (spaces, leading digit, empty). */\nconst NAME_RE = /^[A-Za-z_][A-Za-z0-9_.]*$/;\n\nfunction workbook(api: CasualSheetsAPI): FWorkbookLike | null {\n return (api.univer.getActiveWorkbook() as unknown as FWorkbookLike | null) ?? null;\n}\n\nfunction readRows(api: CasualSheetsAPI): NameRow[] {\n const wb = workbook(api);\n if (!wb) return [];\n return wb.getDefinedNames().map((dn) => ({\n name: dn.getName(),\n refersTo: dn.getFormulaOrRefString(),\n }));\n}\n\n/** Sheet-qualified A1 of the current selection, e.g. `Sheet1!A1:B2`, or ''. */\nfunction selectionRef(api: CasualSheetsAPI): string {\n const range = workbook(api)?.getActiveSheet()?.getActiveRange();\n return range?.getA1Notation(true) ?? '';\n}\n\nconst ROW_STYLE: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: '1fr 1.3fr auto',\n alignItems: 'center',\n gap: 8,\n padding: '6px 8px',\n borderBottom: '1px solid var(--cs-chrome-border, #edeff3)',\n};\n\nconst LIST_STYLE: CSSProperties = {\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 6,\n maxHeight: 200,\n overflow: 'auto',\n marginBottom: 16,\n};\n\nconst EMPTY_STYLE: CSSProperties = {\n padding: '16px 8px',\n fontSize: 13,\n color: 'var(--cs-chrome-muted, #605e5c)',\n textAlign: 'center',\n};\n\nconst REF_CELL_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n};\n\nconst ROW_ACTIONS_STYLE: CSSProperties = {\n display: 'flex',\n gap: 4,\n};\n\nconst SMALL_BTN_STYLE: CSSProperties = {\n ...DIALOG_BTN_SECONDARY_STYLE,\n height: 24,\n padding: '0 8px',\n fontSize: 12,\n};\n\nconst SECTION_TITLE_STYLE: CSSProperties = {\n fontSize: 13,\n fontWeight: 600,\n color: 'var(--cs-chrome-fg, #201f1e)',\n margin: '0 0 8px',\n};\n\nconst ERROR_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-danger, #b91c1c)',\n marginBottom: 8,\n};\n\nconst TWO_COL_STYLE: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: '1fr 1.3fr',\n gap: 8,\n};\n\nexport function NameManagerDialog({ api, onClose }: DialogComponentProps) {\n const [rows, setRows] = useState<NameRow[]>(() => readRows(api));\n // When editing, this holds the ORIGINAL name of the row being edited (used to\n // locate + update it). null means we're adding a new name.\n const [editingOriginal, setEditingOriginal] = useState<string | null>(null);\n const [nameInput, setNameInput] = useState('');\n const [refInput, setRefInput] = useState('');\n const [error, setError] = useState<string | null>(null);\n\n const initialSelRef = useMemo(() => selectionRef(api), [api]);\n\n const refresh = useCallback(() => setRows(readRows(api)), [api]);\n\n const resetForm = useCallback(() => {\n setEditingOriginal(null);\n setNameInput('');\n setRefInput('');\n setError(null);\n }, []);\n\n const startEdit = (row: NameRow) => {\n setEditingOriginal(row.name);\n setNameInput(row.name);\n setRefInput(row.refersTo);\n setError(null);\n };\n\n const useSelection = () => {\n const ref = selectionRef(api);\n if (ref) setRefInput(ref);\n };\n\n const remove = (row: NameRow) => {\n const wb = workbook(api);\n if (!wb) return;\n wb.deleteDefinedName(row.name);\n if (editingOriginal === row.name) resetForm();\n refresh();\n };\n\n const submit = () => {\n const wb = workbook(api);\n if (!wb) {\n setError('No active workbook.');\n return;\n }\n const name = nameInput.trim();\n const ref = refInput.trim();\n if (!name) {\n setError('Enter a name.');\n return;\n }\n if (!NAME_RE.test(name)) {\n setError('Names must start with a letter or underscore and contain no spaces.');\n return;\n }\n if (!ref) {\n setError('Enter a range or formula (e.g. Sheet1!A1:B2).');\n return;\n }\n\n // Duplicate-name guard: allow keeping the same name while editing, but block\n // colliding with a different existing name.\n const collides = rows.some(\n (r) => r.name.toLowerCase() === name.toLowerCase() && r.name !== editingOriginal,\n );\n if (collides) {\n setError(`A defined name \"${name}\" already exists.`);\n return;\n }\n\n if (editingOriginal === null) {\n // Add.\n wb.insertDefinedName(name, ref);\n } else {\n // Edit — rebuild from the existing name to preserve identity/scope, then\n // update. If the row vanished (e.g. deleted elsewhere) fall back to insert.\n const existing = wb.getDefinedName(editingOriginal);\n if (existing) {\n const param = existing.toBuilder().setName(name).setRef(ref).build();\n wb.updateDefinedNameBuilder(param);\n } else {\n wb.insertDefinedName(name, ref);\n }\n }\n\n refresh();\n resetForm();\n };\n\n const isEditing = editingOriginal !== null;\n\n return (\n <Dialog\n title=\"Name manager\"\n onClose={onClose}\n width={480}\n data-testid=\"cs-name-manager-dialog\"\n footer={\n <>\n <span style={{ flex: 1 }} />\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Close\n </button>\n </>\n }\n >\n <h3 style={SECTION_TITLE_STYLE}>Defined names</h3>\n <div style={LIST_STYLE} data-testid=\"cs-name-manager-list\">\n {rows.length === 0 ? (\n <div style={EMPTY_STYLE} data-testid=\"cs-name-manager-empty\">\n No defined names yet. Add one below.\n </div>\n ) : (\n rows.map((row) => (\n <div key={row.name} style={ROW_STYLE} data-testid=\"cs-name-manager-row\">\n <span style={{ fontWeight: 500 }}>{row.name}</span>\n <span style={REF_CELL_STYLE} title={row.refersTo}>\n {row.refersTo}\n </span>\n <span style={ROW_ACTIONS_STYLE}>\n <button\n type=\"button\"\n style={SMALL_BTN_STYLE}\n data-testid=\"cs-name-manager-edit\"\n onClick={() => startEdit(row)}\n >\n Edit\n </button>\n <button\n type=\"button\"\n style={SMALL_BTN_STYLE}\n data-testid=\"cs-name-manager-delete\"\n onClick={() => remove(row)}\n >\n Delete\n </button>\n </span>\n </div>\n ))\n )}\n </div>\n\n <h3 style={SECTION_TITLE_STYLE}>{isEditing ? 'Edit name' : 'Add a name'}</h3>\n\n {error && (\n <div style={ERROR_STYLE} data-testid=\"cs-name-manager-error\">\n {error}\n </div>\n )}\n\n <div style={TWO_COL_STYLE}>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Name</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-name-manager-name\"\n value={nameInput}\n placeholder=\"MyRange\"\n onChange={(e) => setNameInput(e.target.value)}\n />\n </label>\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Refers to</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-name-manager-ref\"\n value={refInput}\n placeholder={initialSelRef || 'Sheet1!A1:B2'}\n onChange={(e) => setRefInput(e.target.value)}\n />\n </label>\n </div>\n\n <div style={{ display: 'flex', gap: 8, marginTop: 4 }}>\n <button\n type=\"button\"\n style={DIALOG_BTN_SECONDARY_STYLE}\n data-testid=\"cs-name-manager-use-selection\"\n onClick={useSelection}\n >\n Use selection\n </button>\n <span style={{ flex: 1 }} />\n {isEditing && (\n <button\n type=\"button\"\n style={DIALOG_BTN_SECONDARY_STYLE}\n data-testid=\"cs-name-manager-cancel-edit\"\n onClick={resetForm}\n >\n Cancel\n </button>\n )}\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-name-manager-submit\"\n onClick={submit}\n >\n {isEditing ? 'Update' : 'Add'}\n </button>\n </div>\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * InsertCellsDialog — the SDK chrome's built-in Insert Cells modal.\n *\n * Follows the DataValidationDialog / FormatCellsDialog pattern: reads the active\n * A1 selection off the FUniver facade, offers the four Excel/Sheets shift\n * choices, and applies via real, installed facade methods:\n *\n * - Shift cells right → `FRange.insertCells(Dimension.COLUMNS)`\n * - Shift cells down → `FRange.insertCells(Dimension.ROWS)`\n * - Entire row → `FWorksheet.insertRows(startRow, rowCount)`\n * - Entire column → `FWorksheet.insertColumns(startColumn, colCount)`\n *\n * The shift-direction ↔ Dimension mapping is grounded in the `insertCells`\n * doc-example in `@univerjs/sheets/lib/types/facade/f-range.d.ts` (line 1484):\n * `insertCells(Dimension.COLUMNS)` pushes existing data to the RIGHT, and\n * `insertCells(Dimension.ROWS)` pushes it DOWN. `Dimension` is verified in\n * `@univerjs/core/lib/types/types/enum/dimension.d.ts` (COLUMNS=0, ROWS=1).\n * `FWorksheet.insertRows` / `insertColumns` are verified in\n * `@univerjs/sheets/lib/types/facade/f-worksheet.d.ts` (lines 355 / 679), and\n * the range extents come from `FRange.getRow/getColumn/getLastRow/getLastColumn`\n * (f-range.d.ts lines 115/141/128/154).\n *\n * Mounted by `<DialogHost>` when `openDialog('insert-cells')` is called and no\n * host override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties } from 'react';\nimport { Dimension } from '@univerjs/core';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport { DIALOG_BTN_PRIMARY_STYLE, DIALOG_BTN_SECONDARY_STYLE } from './dialog-styles';\n\n/** The four shift choices, matching Excel / Google Sheets \"Insert cells\". */\ntype ShiftChoice = 'right' | 'down' | 'row' | 'column';\n\nconst SHIFT_OPTIONS: Array<{ value: ShiftChoice; label: string }> = [\n { value: 'right', label: 'Shift cells right' },\n { value: 'down', label: 'Shift cells down' },\n { value: 'row', label: 'Entire row' },\n { value: 'column', label: 'Entire column' },\n];\n\n/** The active FRange, or null when there is no selection. */\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/**\n * Insert cells at the active selection with the chosen shift. Returns false when\n * there is no active range (nothing to insert against).\n */\nfunction applyInsert(api: CasualSheetsAPI, shift: ShiftChoice): boolean {\n const range = activeRange(api);\n if (!range) return false;\n\n switch (shift) {\n case 'right':\n // COLUMNS dimension pushes existing data to the right (f-range.d.ts:1484).\n range.insertCells(Dimension.COLUMNS);\n return true;\n case 'down':\n // ROWS dimension pushes existing data down.\n range.insertCells(Dimension.ROWS);\n return true;\n case 'row': {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sheet) return false;\n const startRow = range.getRow();\n const rowCount = range.getLastRow() - startRow + 1;\n sheet.insertRows(startRow, rowCount);\n return true;\n }\n case 'column': {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sheet) return false;\n const startColumn = range.getColumn();\n const colCount = range.getLastColumn() - startColumn + 1;\n sheet.insertColumns(startColumn, colCount);\n return true;\n }\n }\n}\n\nconst RANGE_NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 14,\n};\n\nconst RADIO_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n marginBottom: 10,\n cursor: 'pointer',\n};\n\nexport function InsertCellsDialog({ api, onClose }: DialogComponentProps) {\n const [shift, setShift] = useState<ShiftChoice>('down');\n\n // Read the selection once for the header hint. `getA1Notation` off the live\n // FRange (verified in @univerjs/sheets/facade f-range.d.ts) gives the\n // user-facing A1 label, e.g. \"A1:B2\".\n const rangeLabel = useMemo(() => {\n const fRange = activeRange(api) as unknown as { getA1Notation?: () => string } | null;\n return fRange?.getA1Notation?.() ?? null;\n }, [api]);\n\n const hasSelection = activeRange(api) !== null;\n\n const apply = () => {\n if (applyInsert(api, shift)) onClose();\n };\n\n return (\n <Dialog\n title=\"Insert cells\"\n onClose={onClose}\n width={380}\n data-testid=\"cs-insert-cells-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-insert-cells-apply\"\n disabled={!hasSelection}\n onClick={apply}\n >\n Insert\n </button>\n </>\n }\n >\n {hasSelection ? (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-insert-cells-range\">\n Insert at <strong>{rangeLabel ?? 'the current selection'}</strong>\n </div>\n ) : (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-insert-cells-no-selection\">\n Select one or more cells first, then reopen this dialog.\n </div>\n )}\n\n <div role=\"radiogroup\" aria-label=\"Shift direction\">\n {SHIFT_OPTIONS.map((opt) => (\n <label\n key={opt.value}\n style={RADIO_STYLE}\n data-testid={`cs-insert-cells-shift-${opt.value}-label`}\n >\n <input\n type=\"radio\"\n name=\"cs-insert-cells-shift\"\n data-testid={`cs-insert-cells-shift-${opt.value}`}\n checked={shift === opt.value}\n onChange={() => setShift(opt.value)}\n />\n <span>{opt.label}</span>\n </label>\n ))}\n </div>\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * DeleteCellsDialog — the SDK chrome's built-in Delete Cells modal.\n *\n * Excel/Sheets \"Delete cells…\" dialog: delete the active selection with a\n * shift choice — shift the surviving cells left, shift them up, or delete the\n * selection's entire rows / entire columns.\n *\n * Applied through the FUniver facade (no invented commands):\n * - shift left → `FRange.deleteCells(Dimension.COLUMNS)`\n * - shift up → `FRange.deleteCells(Dimension.ROWS)`\n * - entire row → `FWorksheet.deleteRows(startRow, rowCount)`\n * - entire column → `FWorksheet.deleteColumns(startColumn, columnCount)`\n *\n * Grounded in the installed facade types:\n * - `Dimension` enum (COLUMNS=0, ROWS=1) — @univerjs/core dimension.d.ts.\n * - `FRange.deleteCells(shiftDimension: Dimension)` — @univerjs/sheets\n * facade f-range.d.ts L1541; `getRow/getColumn/getLastRow/getLastColumn`\n * L115/141/128/154; `getA1Notation` L1200.\n * - `FWorksheet.deleteRows(pos, howMany)` L418 / `deleteColumns(pos, howMany)`\n * L742 — @univerjs/sheets facade f-worksheet.d.ts.\n *\n * Mounted by `<DialogHost>` when `openDialog('delete-cells')` is called and no\n * host override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties } from 'react';\nimport { Dimension } from '@univerjs/core';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport { DIALOG_BTN_PRIMARY_STYLE, DIALOG_BTN_SECONDARY_STYLE } from './dialog-styles';\n\n/** How surviving cells move (or what dimension is removed wholesale). */\ntype ShiftChoice = 'left' | 'up' | 'row' | 'column';\n\nconst SHIFT_OPTIONS: Array<{ value: ShiftChoice; label: string }> = [\n { value: 'left', label: 'Shift cells left' },\n { value: 'up', label: 'Shift cells up' },\n { value: 'row', label: 'Entire row' },\n { value: 'column', label: 'Entire column' },\n];\n\n/** The active FRange, or null when there is no selection. */\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/**\n * Apply the delete via the facade. Returns false when there's no active range\n * (or no active sheet for the whole-row / whole-column paths).\n */\nfunction applyDelete(api: CasualSheetsAPI, choice: ShiftChoice): boolean {\n const range = activeRange(api);\n if (!range) return false;\n\n if (choice === 'left') {\n // Existing data to the right shifts left into the gap.\n range.deleteCells(Dimension.COLUMNS);\n return true;\n }\n if (choice === 'up') {\n // Existing data below shifts up into the gap.\n range.deleteCells(Dimension.ROWS);\n return true;\n }\n\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sheet) return false;\n\n if (choice === 'row') {\n const start = range.getRow();\n const count = range.getLastRow() - start + 1;\n if (count <= 0) return false;\n sheet.deleteRows(start, count);\n return true;\n }\n\n // choice === 'column'\n const start = range.getColumn();\n const count = range.getLastColumn() - start + 1;\n if (count <= 0) return false;\n sheet.deleteColumns(start, count);\n return true;\n}\n\nconst RANGE_NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 12,\n};\n\nconst OPTION_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n padding: '6px 4px',\n cursor: 'pointer',\n};\n\nexport function DeleteCellsDialog({ api, onClose }: DialogComponentProps) {\n const [choice, setChoice] = useState<ShiftChoice>('left');\n\n // Read the selection once for the header hint. `getA1Notation` off the live\n // FRange (verified in @univerjs/sheets/facade f-range.d.ts) gives the\n // user-facing A1 label, e.g. \"A1:B2\".\n const rangeLabel = useMemo(() => {\n const fRange = activeRange(api) as unknown as { getA1Notation?: () => string } | null;\n return fRange?.getA1Notation?.() ?? null;\n }, [api]);\n\n const hasSelection = activeRange(api) !== null;\n\n const apply = () => {\n if (applyDelete(api, choice)) onClose();\n };\n\n return (\n <Dialog\n title=\"Delete cells\"\n onClose={onClose}\n width={360}\n data-testid=\"cs-delete-cells-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-delete-cells-apply\"\n disabled={!hasSelection}\n onClick={apply}\n >\n Delete\n </button>\n </>\n }\n >\n {hasSelection ? (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-delete-cells-range\">\n Delete <strong>{rangeLabel ?? 'the current selection'}</strong> and…\n </div>\n ) : (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-delete-cells-no-selection\">\n Select one or more cells first, then reopen this dialog.\n </div>\n )}\n\n <div role=\"radiogroup\" aria-label=\"Delete option\">\n {SHIFT_OPTIONS.map((opt) => (\n <label key={opt.value} style={OPTION_STYLE}>\n <input\n type=\"radio\"\n name=\"cs-delete-cells-shift\"\n data-testid={`cs-delete-cells-${opt.value}`}\n value={opt.value}\n checked={choice === opt.value}\n onChange={() => setChoice(opt.value)}\n />\n <span>{opt.label}</span>\n </label>\n ))}\n </div>\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * GoalSeekDialog — the SDK chrome's built-in What-If Goal Seek modal.\n *\n * Excel's Goal Seek: pick a formula cell (\"Set cell\"), a target result\n * (\"To value\"), and one input cell (\"By changing cell\"). The solver drives the\n * input cell until the formula cell reaches the target.\n *\n * The installed Univer facade ships NO goal-seek command (verified: no `goalSeek`\n * anywhere under the `@univerjs/sheets` facade modules), so this dialog implements\n * the solver client-side against real facade primitives only:\n *\n * - read/write cells → `FWorksheet.getRange(a1)` → `FRange.setValue(n)` /\n * `FRange.getValue()` (`@univerjs/sheets/facade`\n * f-range.d.ts L814 / L309, f-worksheet.d.ts getRange L279)\n * - settle the formula → `univerAPI.getFormula().onCalculationEnd()` returns a\n * `Promise<void>` that resolves once the async formula\n * engine has applied results (`@univerjs/engine-formula/facade`\n * f-formula.d.ts L127; the mixin `getFormula()` is on\n * f-univer.d.ts L22). Univer recomputes formulas\n * asynchronously after a `setValue` mutation, so we await\n * this before reading the formula cell back.\n *\n * Numerics: a damped secant iteration (finite-difference seeded when the two\n * probes coincide), with a bisection-style bracket fallback. Non-convergence\n * within the iteration budget restores the input cell to its original value and\n * surfaces a message — no silent partial writes.\n *\n * Mounted by `<DialogHost>` when `openDialog('goal-seek')` is called and no host\n * override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties } from 'react';\n// Side-effect import: installs the formula-engine facade mixin\n// (`univerAPI.getFormula()` + FFormula.onCalculationEnd) onto the facade\n// prototype. `@univerjs/sheets/facade` (imported by sheets/api.ts) pulls the\n// sheet mixins; this one guarantees the formula engine surface is present at the\n// call site regardless of which facade groups a host registered.\nimport '@univerjs/sheets-formula/facade';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_INPUT_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\n/** Loosely-typed slice of the FUniver facade this dialog leans on. */\ninterface Solver {\n worksheet: {\n getRange: (a1: string) => {\n setValue: (value: number) => unknown;\n getValue: () => unknown;\n } | null;\n };\n /** Wait for the async formula engine to apply results after a mutation. */\n settle: () => Promise<void>;\n}\n\n/** Resolve the active-sheet range/settle helpers, or null when unavailable. */\nfunction getSolver(api: CasualSheetsAPI): Solver | null {\n const worksheet = api.univer.getActiveWorkbook()?.getActiveSheet() ?? null;\n if (!worksheet) return null;\n const formula = (\n api.univer as unknown as { getFormula?: () => { onCalculationEnd?: () => Promise<void> } }\n ).getFormula?.();\n return {\n worksheet: worksheet as unknown as Solver['worksheet'],\n settle: async () => {\n // onCalculationEnd resolves on the next completed calc pass. If the facade\n // is missing it (older group set), fall back to a microtask + rAF so the\n // engine's async recompute has a chance to flush before we read back.\n if (formula?.onCalculationEnd) {\n await formula.onCalculationEnd();\n return;\n }\n await new Promise<void>((resolve) => {\n if (typeof requestAnimationFrame === 'function') requestAnimationFrame(() => resolve());\n else setTimeout(resolve, 16);\n });\n },\n };\n}\n\n/** Coerce a Univer cell value to a finite number, or NaN. */\nfunction toNumber(value: unknown): number {\n if (typeof value === 'number') return value;\n if (typeof value === 'boolean') return value ? 1 : 0;\n if (typeof value === 'string' && value.trim() !== '') return Number(value);\n return Number.NaN;\n}\n\n/** Basic A1 single-cell validation (letters + digits, no range colon). */\nfunction isSingleCellA1(ref: string): boolean {\n return /^[A-Za-z]{1,3}[1-9][0-9]*$/.test(ref.trim());\n}\n\ninterface DialogState {\n /** The formula cell whose result we're steering (A1). */\n setCell: string;\n /** The target value the formula cell should reach. */\n toValue: string;\n /** The input cell the solver adjusts (A1). */\n byChangingCell: string;\n}\n\nconst INITIAL_STATE: DialogState = { setCell: '', toValue: '', byChangingCell: '' };\n\n/** Convergence tolerance on |formula(x) - target|. */\nconst TOLERANCE = 1e-6;\n/** Max solver iterations before declaring non-convergence. */\nconst MAX_ITERATIONS = 100;\n\ntype SeekResult = { ok: true; solution: number; result: number } | { ok: false; reason: string };\n\n/**\n * Drive `byChangingCell` until `setCell`'s formula result reaches `target`.\n * Restores the original input on failure so the sheet is never left mid-solve.\n */\nasync function goalSeek(\n solver: Solver,\n setCellRef: string,\n target: number,\n changeCellRef: string,\n): Promise<SeekResult> {\n const setRange = solver.worksheet.getRange(setCellRef);\n const changeRange = solver.worksheet.getRange(changeCellRef);\n if (!setRange || !changeRange) return { ok: false, reason: 'Could not resolve the cells.' };\n\n const original = toNumber(changeRange.getValue());\n const x0Seed = Number.isFinite(original) ? original : 0;\n\n // Evaluate the formula cell after setting the input to `x`.\n const evalAt = async (x: number): Promise<number> => {\n changeRange.setValue(x);\n await solver.settle();\n return toNumber(setRange.getValue());\n };\n\n const restore = async () => {\n changeRange.setValue(x0Seed);\n await solver.settle();\n };\n\n // f(x) = formula(x) - target; we want a root of f.\n let x0 = x0Seed;\n let f0 = (await evalAt(x0)) - target;\n if (!Number.isFinite(f0)) {\n await restore();\n return { ok: false, reason: 'The set cell is not a number (check that it holds a formula).' };\n }\n if (Math.abs(f0) <= TOLERANCE) return { ok: true, solution: x0, result: f0 + target };\n\n // Second probe: nudge x0. Use a step scaled to the magnitude of x0 so we get a\n // meaningful finite-difference slope even for large/small inputs.\n let x1 = x0 !== 0 ? x0 * 1.01 + 0.01 : 1;\n let f1 = (await evalAt(x1)) - target;\n\n for (let i = 0; i < MAX_ITERATIONS; i++) {\n if (Number.isFinite(f1) && Math.abs(f1) <= TOLERANCE) {\n return { ok: true, solution: x1, result: f1 + target };\n }\n\n const denom = f1 - f0;\n let x2: number;\n if (!Number.isFinite(f1) || denom === 0) {\n // Flat/undefined slope — perturb to break the stall rather than divide by 0.\n x2 = x1 + (x1 !== 0 ? x1 * 0.1 : 0.1);\n } else {\n // Secant step, damped to avoid overshoot on stiff curves.\n const step = (f1 * (x1 - x0)) / denom;\n x2 = x1 - step;\n if (!Number.isFinite(x2)) x2 = x1 + (x1 !== 0 ? x1 * 0.1 : 0.1);\n }\n\n const f2 = (await evalAt(x2)) - target;\n x0 = x1;\n f0 = f1;\n x1 = x2;\n f1 = f2;\n }\n\n await restore();\n return {\n ok: false,\n reason: `Could not converge after ${MAX_ITERATIONS} iterations. Try an input cell whose value the set cell actually depends on.`,\n };\n}\n\nconst NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 12,\n};\n\nconst STATUS_OK_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-active-fg, #0e7490)',\n marginTop: 4,\n};\n\nconst STATUS_ERR_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-danger, #b91c1c)',\n marginTop: 4,\n};\n\ntype Status =\n | { kind: 'idle' }\n | { kind: 'running' }\n | { kind: 'done'; solution: number; result: number }\n | { kind: 'error'; message: string };\n\nexport function GoalSeekDialog({ api, onClose }: DialogComponentProps) {\n // Seed \"Set cell\" with the current single-cell selection, if any.\n const initialSetCell = useMemo(() => {\n const range = api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange();\n const a1 = (range as unknown as { getA1Notation?: () => string } | null)?.getA1Notation?.();\n return a1 && isSingleCellA1(a1) ? a1 : '';\n }, [api]);\n\n const [state, setState] = useState<DialogState>({ ...INITIAL_STATE, setCell: initialSetCell });\n const [status, setStatus] = useState<Status>({ kind: 'idle' });\n\n const update = <K extends keyof DialogState>(key: K, value: DialogState[K]) => {\n setState((prev) => ({ ...prev, [key]: value }));\n setStatus({ kind: 'idle' });\n };\n\n const setCellValid = isSingleCellA1(state.setCell);\n const changeCellValid = isSingleCellA1(state.byChangingCell);\n const targetNum = Number(state.toValue);\n const targetValid = state.toValue.trim() !== '' && Number.isFinite(targetNum);\n const canRun =\n setCellValid &&\n changeCellValid &&\n targetValid &&\n state.setCell.trim().toUpperCase() !== state.byChangingCell.trim().toUpperCase() &&\n status.kind !== 'running';\n\n const run = async () => {\n const solver = getSolver(api);\n if (!solver) {\n setStatus({ kind: 'error', message: 'No active sheet.' });\n return;\n }\n setStatus({ kind: 'running' });\n try {\n const result = await goalSeek(\n solver,\n state.setCell.trim(),\n targetNum,\n state.byChangingCell.trim(),\n );\n if (result.ok) {\n setStatus({ kind: 'done', solution: result.solution, result: result.result });\n } else {\n setStatus({ kind: 'error', message: result.reason });\n }\n } catch (err) {\n setStatus({\n kind: 'error',\n message: err instanceof Error ? err.message : 'Goal seek failed.',\n });\n }\n };\n\n const running = status.kind === 'running';\n\n return (\n <Dialog\n title=\"Goal seek\"\n onClose={onClose}\n width={420}\n data-testid=\"cs-goal-seek-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n {status.kind === 'done' ? 'Done' : 'Cancel'}\n </button>\n <button\n type=\"button\"\n style={{ ...DIALOG_BTN_PRIMARY_STYLE, opacity: canRun ? 1 : 0.5 }}\n data-testid=\"cs-goal-seek-run\"\n disabled={!canRun}\n onClick={run}\n >\n {running ? 'Solving…' : 'Solve'}\n </button>\n </>\n }\n >\n <div style={NOTE_STYLE} data-testid=\"cs-goal-seek-note\">\n Drives the input cell until the formula cell reaches your target value.\n </div>\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Set cell (formula cell)</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-goal-seek-set-cell\"\n placeholder=\"e.g. B5\"\n value={state.setCell}\n onChange={(e) => update('setCell', e.target.value)}\n />\n </label>\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>To value</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-goal-seek-to-value\"\n type=\"number\"\n placeholder=\"e.g. 1000\"\n value={state.toValue}\n onChange={(e) => update('toValue', e.target.value)}\n />\n </label>\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>By changing cell (input cell)</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-goal-seek-change-cell\"\n placeholder=\"e.g. B2\"\n value={state.byChangingCell}\n onChange={(e) => update('byChangingCell', e.target.value)}\n />\n </label>\n\n {status.kind === 'done' && (\n <div style={STATUS_OK_STYLE} data-testid=\"cs-goal-seek-success\">\n Solved: <strong>{state.byChangingCell.trim().toUpperCase()}</strong> ={' '}\n {formatNumber(status.solution)} makes{' '}\n <strong>{state.setCell.trim().toUpperCase()}</strong> = {formatNumber(status.result)}.\n </div>\n )}\n {status.kind === 'error' && (\n <div style={STATUS_ERR_STYLE} data-testid=\"cs-goal-seek-error\">\n {status.message}\n </div>\n )}\n </Dialog>\n );\n}\n\n/** Trim solver float noise for display without losing precision users care about. */\nfunction formatNumber(n: number): string {\n if (!Number.isFinite(n)) return String(n);\n const rounded = Math.round(n * 1e6) / 1e6;\n return String(rounded);\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * InsertChartDialog — the SDK chrome's built-in Insert Chart modal.\n *\n * Reads the active A1 selection off the FUniver facade, lets the user pick a\n * chart type (column / bar / line / pie) and confirm the source range, then\n * inserts a chart over the grid.\n *\n * Facade grounding / capability note\n * ----------------------------------\n * Univer 0.25 (the version pinned in this SDK's peerDependencies) ships NO\n * `@univerjs/*chart*` package — there is no `FUniver.newChart()` builder and no\n * `FRange.insertChart()` the way `@univerjs/sheets-data-validation` gives us\n * `newDataValidation()` / `setDataValidation()`. (Verified: no chart package\n * under node_modules/@univerjs, and none listed in the SDK peerDependencies.)\n *\n * The closest REAL, installed facade capability for placing a positioned visual\n * artifact over the grid is the float-DOM API contributed by\n * `@univerjs/sheets-drawing-ui/facade` — the same mechanism Univer's own chart\n * and image plugins use to anchor content over cells:\n * - `univerAPI.registerComponent(key, Component)` (@univerjs/ui f-univer.d.ts L390)\n * - `FWorksheet.addFloatDomToRange(range, { componentKey, data }, domLayout, id)`\n * (@univerjs/sheets-drawing-ui/lib/types/facade/f-worksheet.d.ts L305; the\n * `declare module '@univerjs/sheets/facade' { interface FWorksheet … }`\n * augmentation at L428 is what puts the method on the live sheet)\n *\n * So on Apply we: register a small self-contained SVG chart-preview component\n * (once), read the selected range's numeric values off the SDK snapshot, and\n * insert a float DOM over the selection rendering that preview for the chosen\n * type. This is a genuine facade insertion (real, disposable, positioned),\n * reads the real selection data, and closes.\n *\n * LIMITATION (recorded): without a chart engine in the SDK's dep tree, the\n * inserted artifact is a static, computed SVG preview of the selected values —\n * not a live, re-calculating, fully-styled chart series. When a host installs a\n * real Univer chart plugin it can OVERRIDE this dialog by registering its own\n * `insert-chart` extension (extensions.dialogs['insert-chart']); the built-in is\n * the always-available default.\n *\n * Mounted by `<DialogHost>` when `openDialog('insert-chart')` is called and no\n * host override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties, type ReactNode } from 'react';\n// Side-effect import: installs `FWorksheet.addFloatDomToRange` (+ the other\n// float-dom methods) on the facade prototype AND augments\n// `@univerjs/sheets/facade`'s FWorksheet at type-check time. Without it, the\n// method is undefined at runtime. Mirrors DataValidationDialog's\n// `@univerjs/sheets-data-validation/facade` side-effect import.\nimport '@univerjs/sheets-drawing-ui/facade';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_INPUT_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\n/** Chart families the dialog can insert. */\ntype ChartType = 'column' | 'bar' | 'line' | 'pie';\n\nconst CHART_TYPE_OPTIONS: Array<{ value: ChartType; label: string }> = [\n { value: 'column', label: 'Column' },\n { value: 'bar', label: 'Bar' },\n { value: 'line', label: 'Line' },\n { value: 'pie', label: 'Pie' },\n];\n\n/** Stable component key we register the preview under (once per FUniver). */\nconst CHART_COMPONENT_KEY = 'cs-builtin-chart-preview';\n\n/** Palette for the preview series (kept small + colour-blind-friendly-ish). */\nconst PALETTE = ['#0e7490', '#f59e0b', '#10b981', '#ef4444', '#6366f1', '#ec4899'];\n\ninterface DialogState {\n chartType: ChartType;\n /** A1 range the chart reads from (seeded from the live selection). */\n rangeA1: string;\n}\n\n/** The active FRange, or null when there is no selection. */\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/** The active FWorksheet, or null. */\nfunction activeSheet(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet() ?? null;\n}\n\n/**\n * Pull the numeric values out of the selected range off the SDK snapshot (the\n * same read path FormatCellsDialog uses to seed itself). Flattened + coerced;\n * non-numeric cells drop out. Returns [] when nothing usable is present.\n */\nfunction readRangeNumbers(api: CasualSheetsAPI): number[] {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const snap = api.getSnapshot() as any;\n const sel = api.getSelection();\n if (!snap || !sel) return [];\n const sheet = snap.sheets?.[sel.sheetId];\n if (!sheet) return [];\n const { startRow, endRow, startColumn, endColumn } = sel.range;\n const out: number[] = [];\n for (let r = startRow; r <= endRow; r++) {\n for (let c = startColumn; c <= endColumn; c++) {\n const raw = sheet.cellData?.[r]?.[c]?.v;\n const n = typeof raw === 'number' ? raw : Number(raw);\n if (Number.isFinite(n)) out.push(n);\n }\n }\n return out;\n}\n\n/**\n * Register the SVG chart-preview component on the FUniver facade if it hasn't\n * been registered yet. Idempotent per FUniver instance: we stash a flag on the\n * facade object so re-opening the dialog doesn't re-register (registerComponent\n * returns a disposable, but we intentionally keep the registration alive for the\n * lifetime of the editor so previously-inserted charts keep rendering).\n */\nfunction ensureChartComponent(api: CasualSheetsAPI): void {\n const uni = api.univer as unknown as {\n registerComponent?: (key: string, comp: unknown) => { dispose(): void };\n __csChartRegistered?: boolean;\n };\n if (uni.__csChartRegistered || typeof uni.registerComponent !== 'function') return;\n uni.registerComponent(CHART_COMPONENT_KEY, ChartPreview);\n uni.__csChartRegistered = true;\n}\n\n/**\n * Insert the chart over the current selection via the drawing-ui float-DOM\n * facade. Returns false when there's no selection or the facade method is\n * missing (host didn't register the drawing-ui plugin). Reads the range's\n * numbers and hands them to the preview component as `data`.\n */\nfunction insertChart(api: CasualSheetsAPI, s: DialogState): boolean {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return false;\n\n ensureChartComponent(api);\n\n const values = readRangeNumbers(api);\n\n // `addFloatDomToRange` is contributed by @univerjs/sheets-drawing-ui/facade\n // (f-worksheet.d.ts L305). Typed loosely at the call site so the SDK doesn't\n // hard-depend on the ambient FWorksheet augmentation here.\n const domSheet = sheet as unknown as {\n addFloatDomToRange?: (\n range: unknown,\n layer: { componentKey: string; data?: unknown; allowTransform?: boolean },\n domLayout: {\n width?: number;\n height?: number;\n marginX?: number | string;\n marginY?: number | string;\n },\n id?: string,\n ) => { id: string; dispose: () => void } | null;\n };\n if (typeof domSheet.addFloatDomToRange !== 'function') return false;\n\n const result = domSheet.addFloatDomToRange(\n range,\n {\n componentKey: CHART_COMPONENT_KEY,\n allowTransform: true,\n data: { type: s.chartType, values, rangeA1: s.rangeA1 },\n },\n { width: 360, height: 240, marginX: 0, marginY: 0 },\n `cs-chart-${Date.now()}`,\n );\n return result != null;\n}\n\n/**\n * Self-contained SVG chart preview rendered inside the float DOM. Univer passes\n * the `layer.data` object through as the component's `data` prop. Deliberately\n * dependency-free (no echarts) so the SDK bundle stays lean and the built-in\n * works without any host chart engine.\n */\nfunction ChartPreview({\n data,\n}: {\n data?: { type?: ChartType; values?: number[]; rangeA1?: string };\n}) {\n const type = data?.type ?? 'column';\n const values = (data?.values ?? []).slice(0, 24);\n const label = data?.rangeA1 ?? '';\n\n const wrapStyle: CSSProperties = {\n width: '100%',\n height: '100%',\n boxSizing: 'border-box',\n background: '#ffffff',\n border: '1px solid #cdd3db',\n borderRadius: 6,\n padding: 8,\n display: 'flex',\n flexDirection: 'column',\n font: '12px system-ui, sans-serif',\n color: '#201f1e',\n overflow: 'hidden',\n };\n const titleStyle: CSSProperties = {\n fontWeight: 600,\n marginBottom: 4,\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n };\n\n const W = 340;\n const H = 176;\n const max = values.length ? Math.max(...values, 0) : 0;\n const min = values.length ? Math.min(...values, 0) : 0;\n const span = max - min || 1;\n\n let body: ReactNode;\n if (values.length === 0) {\n body = (\n <text x={W / 2} y={H / 2} textAnchor=\"middle\" fill=\"#605e5c\">\n No numeric data in range\n </text>\n );\n } else if (type === 'pie') {\n const total = values.reduce((a, v) => a + Math.abs(v), 0) || 1;\n const cx = W / 2;\n const cy = H / 2;\n const rad = Math.min(W, H) / 2 - 6;\n let angle = -Math.PI / 2;\n body = (\n <>\n {values.map((v, i) => {\n const frac = Math.abs(v) / total;\n const next = angle + frac * Math.PI * 2;\n const x1 = cx + rad * Math.cos(angle);\n const y1 = cy + rad * Math.sin(angle);\n const x2 = cx + rad * Math.cos(next);\n const y2 = cy + rad * Math.sin(next);\n const large = frac > 0.5 ? 1 : 0;\n const d = `M ${cx} ${cy} L ${x1} ${y1} A ${rad} ${rad} 0 ${large} 1 ${x2} ${y2} Z`;\n angle = next;\n return <path key={i} d={d} fill={PALETTE[i % PALETTE.length]} />;\n })}\n </>\n );\n } else if (type === 'line') {\n const step = values.length > 1 ? W / (values.length - 1) : W;\n const pts = values.map((v, i) => `${i * step},${H - ((v - min) / span) * H}`).join(' ');\n body = <polyline points={pts} fill=\"none\" stroke={PALETTE[0]} strokeWidth={2} />;\n } else {\n // column (vertical) or bar (horizontal)\n const horizontal = type === 'bar';\n const n = values.length;\n const gap = 4;\n body = (\n <>\n {values.map((v, i) => {\n const fill = PALETTE[i % PALETTE.length];\n if (horizontal) {\n const bh = H / n - gap;\n const bw = ((v - min) / span) * W;\n return (\n <rect\n key={i}\n x={0}\n y={i * (bh + gap)}\n width={Math.max(bw, 1)}\n height={bh}\n fill={fill}\n />\n );\n }\n const bw = W / n - gap;\n const bh = ((v - min) / span) * H;\n return (\n <rect\n key={i}\n x={i * (bw + gap)}\n y={H - bh}\n width={bw}\n height={Math.max(bh, 1)}\n fill={fill}\n />\n );\n })}\n </>\n );\n }\n\n return (\n <div style={wrapStyle}>\n {label && (\n <div style={titleStyle}>{`${type[0].toUpperCase()}${type.slice(1)} chart · ${label}`}</div>\n )}\n <svg viewBox={`0 0 ${W} ${H}`} width=\"100%\" height=\"100%\" preserveAspectRatio=\"xMidYMid meet\">\n {body}\n </svg>\n </div>\n );\n}\n\nconst RANGE_NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 12,\n};\n\nconst TYPE_ROW_STYLE: CSSProperties = {\n display: 'grid',\n gridTemplateColumns: 'repeat(4, 1fr)',\n gap: 8,\n marginBottom: 12,\n};\n\nfunction typeCardStyle(selected: boolean): CSSProperties {\n return {\n display: 'flex',\n flexDirection: 'column',\n alignItems: 'center',\n gap: 6,\n padding: '10px 4px',\n border: `1px solid ${selected ? 'var(--cs-chrome-active-fg, #0e7490)' : 'var(--cs-chrome-border, #cdd3db)'}`,\n borderRadius: 8,\n background: selected\n ? 'var(--cs-chrome-active-bg, #ecfeff)'\n : 'var(--cs-chrome-input-bg, #fff)',\n color: selected ? 'var(--cs-chrome-active-fg, #0e7490)' : 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 12,\n cursor: 'pointer',\n };\n}\n\n/** Tiny inline SVG glyph per chart type — no icon-font dependency. */\nfunction TypeGlyph({ type }: { type: ChartType }) {\n const c = 'currentColor';\n switch (type) {\n case 'column':\n return (\n <svg width={22} height={22} viewBox=\"0 0 22 22\" fill={c} aria-hidden=\"true\">\n <rect x={2} y={10} width={4} height={10} />\n <rect x={9} y={5} width={4} height={15} />\n <rect x={16} y={2} width={4} height={18} />\n </svg>\n );\n case 'bar':\n return (\n <svg width={22} height={22} viewBox=\"0 0 22 22\" fill={c} aria-hidden=\"true\">\n <rect x={2} y={2} width={10} height={4} />\n <rect x={2} y={9} width={16} height={4} />\n <rect x={2} y={16} width={7} height={4} />\n </svg>\n );\n case 'line':\n return (\n <svg\n width={22}\n height={22}\n viewBox=\"0 0 22 22\"\n fill=\"none\"\n stroke={c}\n strokeWidth={2}\n aria-hidden=\"true\"\n >\n <polyline points=\"2,16 8,9 13,13 20,3\" />\n </svg>\n );\n case 'pie':\n return (\n <svg width={22} height={22} viewBox=\"0 0 22 22\" fill={c} aria-hidden=\"true\">\n <path d=\"M11 11 L11 2 A9 9 0 0 1 20 11 Z\" />\n <circle cx={11} cy={11} r={9} fill=\"none\" stroke={c} strokeWidth={1.5} />\n </svg>\n );\n }\n}\n\nexport function InsertChartDialog({ api, onClose }: DialogComponentProps) {\n // Read the selection once for the header hint + as the seed source range.\n // `getA1Notation` off the live FRange (verified in @univerjs/sheets/facade\n // f-range.d.ts) gives the user-facing A1 label, e.g. \"A1:B5\".\n const rangeLabel = useMemo(() => {\n const fRange = activeRange(api) as unknown as { getA1Notation?: () => string } | null;\n return fRange?.getA1Notation?.() ?? null;\n }, [api]);\n\n const [state, setState] = useState<DialogState>(() => ({\n chartType: 'column',\n rangeA1: rangeLabel ?? '',\n }));\n\n const hasSelection = activeRange(api) !== null;\n\n const update = <K extends keyof DialogState>(key: K, value: DialogState[K]) =>\n setState((prev) => ({ ...prev, [key]: value }));\n\n const apply = () => {\n if (insertChart(api, state)) onClose();\n };\n\n return (\n <Dialog\n title=\"Insert chart\"\n onClose={onClose}\n width={440}\n data-testid=\"cs-insert-chart-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-insert-chart-apply\"\n disabled={!hasSelection}\n onClick={apply}\n >\n Insert\n </button>\n </>\n }\n >\n {hasSelection ? (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-insert-chart-range\">\n Chart from <strong>{rangeLabel ?? 'the current selection'}</strong>\n </div>\n ) : (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-insert-chart-no-selection\">\n Select the data range first, then reopen this dialog.\n </div>\n )}\n\n <div style={DIALOG_LABEL_STYLE}>Chart type</div>\n <div style={TYPE_ROW_STYLE} role=\"radiogroup\" aria-label=\"Chart type\">\n {CHART_TYPE_OPTIONS.map((opt) => (\n <button\n key={opt.value}\n type=\"button\"\n role=\"radio\"\n aria-checked={state.chartType === opt.value}\n data-testid={`cs-insert-chart-type-${opt.value}`}\n style={typeCardStyle(state.chartType === opt.value)}\n onClick={() => update('chartType', opt.value)}\n >\n <TypeGlyph type={opt.value} />\n <span>{opt.label}</span>\n </button>\n ))}\n </div>\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Data range</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-insert-chart-range-input\"\n value={state.rangeA1}\n placeholder=\"A1:B5\"\n onChange={(e) => update('rangeA1', e.target.value)}\n />\n </label>\n <div style={RANGE_NOTE_STYLE}>\n The chart is placed over the current selection. Numeric cells in the range become the\n series.\n </div>\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * InsertSparklineDialog — the SDK chrome's built-in \"Insert sparkline\" modal.\n *\n * Excel/Sheets-style in-cell sparklines: pick a type (line / column / win-loss),\n * a data range (the values to plot), and a location cell (where the mini-chart\n * renders). Follows the FormatCells/DataValidation exemplars: reads the active\n * A1 selection off the FUniver facade to seed the fields, gathers the form, and\n * applies through the SDK API.\n *\n * FACADE NOTE — no first-class Univer sparkline facade is installed. Unlike\n * data-validation (`@univerjs/sheets-data-validation/facade`), there is no\n * `@univerjs/sheets-sparkline` package in `node_modules/@univerjs/*`, so there is\n * no `univerAPI.newSparkline()` builder or `FRange.setSparkline(...)` to call.\n * Sparklines in this workbook are a Casual-Sheets feature persisted on\n * `IWorkbookData.resources['__casual_sheets_sparklines__']` — the resource the\n * app's `SparklineLayer` renders from and that round-trips through xlsx/collab\n * (see apps/web/src/sparklines/{types,resources}.ts). The dialog therefore wires\n * the REAL op the feature owns: it merges a new `SparklineModel` into that\n * resource on the live snapshot via `api.getContent()` and re-mounts it via\n * `api.setContent()` (the canonical cross-editor content accessors on\n * `CasualSheetsAPI`). The resource name + model shape are duplicated locally so\n * the SDK stays decoupled from the app package.\n *\n * Mounted by `<DialogHost>` when `openDialog('insert-sparkline')` is called and\n * no host override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties } from 'react';\nimport type { IWorkbookData } from '@univerjs/core';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_INPUT_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\n/** Excel-canonical sparkline families. Mirrors apps/web sparklines `SparklineType`. */\ntype SparklineType = 'line' | 'column' | 'win-loss';\n\n/** A single source rectangle in row/column indices. */\ninterface SourceRange {\n startRow: number;\n endRow: number;\n startColumn: number;\n endColumn: number;\n}\n\n/**\n * Sparkline model persisted on the workbook resource. Structurally identical to\n * the app's `SparklineModel` (apps/web/src/sparklines/types.ts) — duplicated here\n * so the SDK doesn't depend on the app package. `SparklineLayer` reads this shape.\n */\ninterface SparklineModel {\n id: string;\n type: SparklineType;\n unitId: string;\n sheetId: string;\n source: SourceRange;\n anchor: { row: number; col: number };\n}\n\n/** Resource key + payload envelope — mirrors `SPARKLINES_RESOURCE_NAME` /\n * `SparklinesResourceV1` in apps/web/src/sparklines/types.ts. */\nconst SPARKLINES_RESOURCE_NAME = '__casual_sheets_sparklines__';\ninterface SparklinesResourceV1 {\n v: 1;\n sparklines: SparklineModel[];\n}\n\nconst TYPE_OPTIONS: Array<{ value: SparklineType; label: string }> = [\n { value: 'line', label: 'Line' },\n { value: 'column', label: 'Column' },\n { value: 'win-loss', label: 'Win / Loss' },\n];\n\ninterface DialogState {\n type: SparklineType;\n /** Data range in A1, e.g. \"A1:F1\". */\n sourceA1: string;\n /** Location cell in A1, e.g. \"G1\". */\n anchorA1: string;\n}\n\n/** The active FRange, or null when there is no selection. */\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/** Convert column letters (A, B, …, AA) to a 0-based index. */\nfunction colLettersToIndex(letters: string): number {\n let n = 0;\n for (let i = 0; i < letters.length; i += 1) {\n n = n * 26 + (letters.charCodeAt(i) - 64);\n }\n return n - 1;\n}\n\n/** Parse an A1 range (\"A1:F1\" or a single \"A1\") into row/column indices. */\nfunction parseRange(s: string): SourceRange | null {\n const m = /^\\$?([A-Z]+)\\$?(\\d+)(?::\\$?([A-Z]+)\\$?(\\d+))?$/.exec(s.trim().toUpperCase());\n if (!m) return null;\n const c1 = colLettersToIndex(m[1]);\n const r1 = parseInt(m[2], 10) - 1;\n const c2 = m[3] ? colLettersToIndex(m[3]) : c1;\n const r2 = m[4] ? parseInt(m[4], 10) - 1 : r1;\n return {\n startRow: Math.min(r1, r2),\n endRow: Math.max(r1, r2),\n startColumn: Math.min(c1, c2),\n endColumn: Math.max(c1, c2),\n };\n}\n\n/** Parse a single A1 cell (\"G1\") into row/col indices. */\nfunction parseSingleCell(s: string): { row: number; col: number } | null {\n const m = /^\\$?([A-Z]+)\\$?(\\d+)$/.exec(s.trim().toUpperCase());\n if (!m) return null;\n return { col: colLettersToIndex(m[1]), row: parseInt(m[2], 10) - 1 };\n}\n\n/**\n * Merge a new sparkline into the workbook's sparklines resource and re-mount the\n * snapshot. Returns false when there is no active workbook.\n *\n * This is the REAL persistence path for sparklines in this workbook (there is no\n * Univer sparkline facade — see the file header). `getContent()` yields the live\n * `IWorkbookData` including `resources`; we splice our model into the\n * `__casual_sheets_sparklines__` entry and hand it back through `setContent()`,\n * exactly the shape `SparklineLayer` renders and xlsx/collab round-trip.\n */\nfunction insertSparkline(api: CasualSheetsAPI, model: SparklineModel): boolean {\n const data = api.getContent();\n if (!data) return false;\n\n const resources = data.resources ? [...data.resources] : [];\n const idx = resources.findIndex((r) => r.name === SPARKLINES_RESOURCE_NAME);\n\n let existing: SparklineModel[] = [];\n if (idx >= 0 && resources[idx]?.data) {\n try {\n const parsed = JSON.parse(resources[idx].data) as Partial<SparklinesResourceV1>;\n if (parsed?.v === 1 && Array.isArray(parsed.sparklines)) existing = parsed.sparklines;\n } catch {\n existing = [];\n }\n }\n\n const payload: SparklinesResourceV1 = { v: 1, sparklines: [...existing, model] };\n const entry = { name: SPARKLINES_RESOURCE_NAME, data: JSON.stringify(payload) };\n if (idx >= 0) resources[idx] = entry;\n else resources.push(entry);\n\n const next: IWorkbookData = { ...data, resources };\n api.setContent(next);\n return true;\n}\n\n/** Read the active workbook's unitId + active sheetId for the model. */\nfunction activeIds(api: CasualSheetsAPI): { unitId: string; sheetId: string } | null {\n const wb = api.univer.getActiveWorkbook();\n const sheet = wb?.getActiveSheet();\n if (!wb || !sheet) return null;\n return { unitId: wb.getId(), sheetId: sheet.getSheetId() };\n}\n\nconst RANGE_NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 12,\n};\n\nconst RADIO_ROW_STYLE: CSSProperties = {\n display: 'flex',\n gap: 16,\n marginTop: 2,\n};\n\nconst RADIO_OPT_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n cursor: 'pointer',\n};\n\nconst ERROR_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-danger-fg, #b91c1c)',\n marginTop: 4,\n};\n\nexport function InsertSparklineDialog({ api, onClose }: DialogComponentProps) {\n // Seed the data range from the current selection (its A1 label), leaving the\n // location cell for the user to pick — mirrors Excel's Insert Sparkline flow.\n const selectedA1 = useMemo(() => {\n const fRange = activeRange(api) as unknown as { getA1Notation?: () => string } | null;\n return fRange?.getA1Notation?.() ?? '';\n }, [api]);\n\n const [state, setState] = useState<DialogState>({\n type: 'line',\n sourceA1: selectedA1,\n anchorA1: '',\n });\n const [error, setError] = useState<string | null>(null);\n\n const hasWorkbook = api.univer.getActiveWorkbook() != null;\n\n const update = <K extends keyof DialogState>(key: K, value: DialogState[K]) => {\n setState((prev) => ({ ...prev, [key]: value }));\n setError(null);\n };\n\n const apply = () => {\n const source = parseRange(state.sourceA1);\n if (!source) {\n setError('Data range must be a range like A1:F1.');\n return;\n }\n const anchor = parseSingleCell(state.anchorA1);\n if (!anchor) {\n setError('Location must be a single cell like G1.');\n return;\n }\n const ids = activeIds(api);\n if (!ids) {\n setError('No active sheet.');\n return;\n }\n\n const model: SparklineModel = {\n id: `spark-${Math.random().toString(36).slice(2, 10)}`,\n type: state.type,\n unitId: ids.unitId,\n sheetId: ids.sheetId,\n source,\n anchor,\n };\n if (insertSparkline(api, model)) onClose();\n else setError('Could not read the active workbook.');\n };\n\n return (\n <Dialog\n title=\"Insert sparkline\"\n onClose={onClose}\n width={420}\n data-testid=\"cs-insert-sparkline-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-insert-sparkline-apply\"\n disabled={!hasWorkbook}\n onClick={apply}\n >\n Insert\n </button>\n </>\n }\n >\n <div style={RANGE_NOTE_STYLE}>\n Draws an in-cell mini-chart in the location cell from the values in the data range.\n </div>\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Type</span>\n <div\n style={RADIO_ROW_STYLE}\n role=\"radiogroup\"\n aria-label=\"Sparkline type\"\n data-testid=\"cs-insert-sparkline-type\"\n >\n {TYPE_OPTIONS.map((opt) => (\n <label key={opt.value} style={RADIO_OPT_STYLE}>\n <input\n type=\"radio\"\n name=\"cs-sparkline-type\"\n value={opt.value}\n data-testid={`cs-insert-sparkline-type-${opt.value}`}\n checked={state.type === opt.value}\n onChange={() => update('type', opt.value)}\n />\n <span>{opt.label}</span>\n </label>\n ))}\n </div>\n </label>\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Data range</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-insert-sparkline-source\"\n value={state.sourceA1}\n placeholder=\"A1:F1\"\n spellCheck={false}\n onChange={(e) => update('sourceA1', e.target.value.toUpperCase())}\n />\n </label>\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Location</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-insert-sparkline-anchor\"\n value={state.anchorA1}\n placeholder=\"G1\"\n spellCheck={false}\n onChange={(e) => update('anchorA1', e.target.value.toUpperCase())}\n />\n </label>\n\n {error && (\n <div style={ERROR_STYLE} data-testid=\"cs-insert-sparkline-error\">\n {error}\n </div>\n )}\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * InsertPivotDialog — the SDK chrome's built-in \"Insert pivot table\" modal\n * (dialog kind `'insert-pivot'`).\n *\n * Facade note / LIMITATION\n * ------------------------\n * Univer's first-class pivot-table feature lives in the commercial\n * `@univerjs/sheets-pivot(-ui)` packages, which are NOT installed in this SDK\n * (the workspace ships only the OSS `@univerjs/*` set — verified: no `pivot`\n * package under `packages/sdk/node_modules/@univerjs/` or `.pnpm/`, and none in\n * `package.json`). So there is no `univerAPI.newPivotTable()` / FRange pivot\n * facade to call.\n *\n * Rather than stub, this dialog implements a REAL, self-contained group-by\n * summary — the practical core of a pivot — entirely on the installed\n * `@univerjs/sheets` facade:\n * - reads the active source range's values via `FRange.getValues()`\n * (f-range.d.ts L386),\n * - groups rows by a chosen \"Rows\" column and aggregates a chosen \"Values\"\n * column (Sum · Count · Average · Min · Max),\n * - writes the resulting table to the destination:\n * • New sheet → `FWorkbook.create(name, rows, cols)` (f-workbook.d.ts\n * L178) then `FWorksheet.getRange(...).setValues(...)`.\n * • This location → `FWorksheet.getRange(a1).setValues(...)`\n * (f-worksheet.d.ts L279 / f-range.d.ts L953).\n *\n * When the real pivot packages are added later, swap `buildPivot`/`writePivot`\n * for the `newPivotTable()` builder; the dialog's inputs already map 1:1 to a\n * pivot's Rows / Values / aggregation configuration.\n *\n * Mounted by `<DialogHost>` when `openDialog('insert-pivot')` is called and no\n * host override is registered.\n */\n\nimport { useMemo, useState, type CSSProperties } from 'react';\nimport type { DialogComponentProps } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Dialog } from './Dialog';\nimport {\n DIALOG_BTN_PRIMARY_STYLE,\n DIALOG_BTN_SECONDARY_STYLE,\n DIALOG_FIELD_STYLE,\n DIALOG_INPUT_STYLE,\n DIALOG_LABEL_STYLE,\n} from './dialog-styles';\n\n/** Aggregation functions the summary can apply to the Values column. */\ntype AggFn = 'sum' | 'count' | 'average' | 'min' | 'max';\n\n/** Where the resulting pivot table is written. */\ntype Destination = 'newSheet' | 'existing';\n\nconst AGG_OPTIONS: Array<{ value: AggFn; label: string }> = [\n { value: 'sum', label: 'Sum' },\n { value: 'count', label: 'Count' },\n { value: 'average', label: 'Average' },\n { value: 'min', label: 'Min' },\n { value: 'max', label: 'Max' },\n];\n\n/** A cell value as read off the facade — Univer returns primitives or null. */\ntype Cell = string | number | boolean | null;\n\n/** The active FRange, or null when there is no selection. */\nfunction activeRange(api: CasualSheetsAPI) {\n return api.univer.getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\n/** Loosely-typed FRange view — only the facade methods this dialog calls. */\ninterface RangeView {\n getValues: () => Cell[][];\n getA1Notation?: () => string;\n}\n\n/** Loosely-typed FWorksheet view — sheet name + a range handle by A1. */\ninterface SheetView {\n getSheetName: () => string;\n getRange: (a1: string) => RangeView & { setValues: (v: Cell[][]) => unknown };\n}\n\n/** Read the source grid once. Returns [] when there's no usable selection. */\nfunction readSource(api: CasualSheetsAPI): Cell[][] {\n const range = activeRange(api) as unknown as RangeView | null;\n const grid = range?.getValues?.() ?? [];\n return Array.isArray(grid) ? grid : [];\n}\n\n/** A column label for the header dropdowns — \"A\", \"B\", or a header-row title. */\nfunction columnLabel(index: number, headerRow: Cell[] | undefined, useHeader: boolean): string {\n if (useHeader) {\n const raw = headerRow?.[index];\n if (raw != null && String(raw).trim().length > 0) return String(raw);\n }\n // Spreadsheet-style A, B, …, Z, AA — relative to the source's first column.\n let n = index;\n let label = '';\n do {\n label = String.fromCharCode(65 + (n % 26)) + label;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n return `Column ${label}`;\n}\n\nfunction toNumber(v: Cell): number | null {\n if (typeof v === 'number') return Number.isFinite(v) ? v : null;\n if (typeof v === 'boolean') return v ? 1 : 0;\n if (typeof v === 'string' && v.trim() !== '') {\n const n = Number(v);\n return Number.isFinite(n) ? n : null;\n }\n return null;\n}\n\n/** Apply the chosen aggregation to a bucket of numeric values. */\nfunction aggregate(fn: AggFn, values: number[], rowCount: number): number {\n if (fn === 'count') return rowCount;\n if (values.length === 0) return 0;\n switch (fn) {\n case 'sum':\n return values.reduce((a, b) => a + b, 0);\n case 'average':\n return values.reduce((a, b) => a + b, 0) / values.length;\n case 'min':\n return Math.min(...values);\n case 'max':\n return Math.max(...values);\n }\n}\n\ninterface PivotResult {\n /** Full 2D grid (header row + one row per group) ready for setValues. */\n grid: Cell[][];\n}\n\n/**\n * Build the group-by summary grid from the source values. Groups the data rows\n * by `groupCol`, aggregates `valueCol` with `fn`, and returns a 2-column table:\n * [group label, aggregated value], preceded by a header row.\n */\nfunction buildPivot(\n source: Cell[][],\n useHeader: boolean,\n groupCol: number,\n valueCol: number,\n fn: AggFn,\n): PivotResult | null {\n if (source.length === 0) return null;\n const headerRow = useHeader ? source[0] : undefined;\n const dataRows = useHeader ? source.slice(1) : source;\n if (dataRows.length === 0) return null;\n\n // Preserve first-seen group order for a stable, predictable output.\n const order: string[] = [];\n const buckets = new Map<string, number[]>();\n const counts = new Map<string, number>();\n\n for (const row of dataRows) {\n const rawKey = row[groupCol];\n const key = rawKey == null ? '' : String(rawKey);\n if (!buckets.has(key)) {\n buckets.set(key, []);\n counts.set(key, 0);\n order.push(key);\n }\n counts.set(key, (counts.get(key) ?? 0) + 1);\n const num = toNumber(row[valueCol]);\n if (num != null) buckets.get(key)!.push(num);\n }\n\n const groupHeader = columnLabel(groupCol, headerRow, useHeader);\n const valueHeader = columnLabel(valueCol, headerRow, useHeader);\n const aggLabel = AGG_OPTIONS.find((o) => o.value === fn)?.label ?? 'Sum';\n\n const grid: Cell[][] = [[groupHeader, `${aggLabel} of ${valueHeader}`]];\n for (const key of order) {\n grid.push([key === '' ? '(blank)' : key, aggregate(fn, buckets.get(key)!, counts.get(key)!)]);\n }\n return { grid };\n}\n\n/** Convert a 0-based (row, col) to A1, e.g. (0,0) -> \"A1\". */\nfunction toA1(row: number, col: number): string {\n let n = col;\n let letters = '';\n do {\n letters = String.fromCharCode(65 + (n % 26)) + letters;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n return `${letters}${row + 1}`;\n}\n\ninterface DialogState {\n useHeader: boolean;\n groupCol: number;\n valueCol: number;\n aggFn: AggFn;\n destination: Destination;\n /** New-sheet name (destination === 'newSheet'). */\n sheetName: string;\n /** Top-left anchor for an in-place write (destination === 'existing'). */\n anchor: string;\n}\n\nconst RANGE_NOTE_STYLE: CSSProperties = {\n fontSize: 12,\n color: 'var(--cs-chrome-muted, #605e5c)',\n marginBottom: 12,\n};\n\nconst CHECK_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n marginBottom: 12,\n cursor: 'pointer',\n};\n\nconst RADIO_ROW_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n marginBottom: 6,\n cursor: 'pointer',\n};\n\nexport function InsertPivotDialog({ api, onClose }: DialogComponentProps) {\n // Read the source grid + its A1 label once on mount.\n const source = useMemo(() => readSource(api), [api]);\n const rangeLabel = useMemo(() => {\n const r = activeRange(api) as unknown as RangeView | null;\n return r?.getA1Notation?.() ?? null;\n }, [api]);\n\n const hasSource = source.length > 0 && (source[0]?.length ?? 0) > 0;\n const colCount = hasSource ? source[0].length : 0;\n\n const [state, setState] = useState<DialogState>({\n useHeader: true,\n groupCol: 0,\n valueCol: colCount > 1 ? 1 : 0,\n aggFn: 'sum',\n destination: 'newSheet',\n sheetName: 'Pivot',\n anchor: '',\n });\n const [error, setError] = useState<string | null>(null);\n\n const update = <K extends keyof DialogState>(key: K, value: DialogState[K]) => {\n setState((prev) => ({ ...prev, [key]: value }));\n setError(null);\n };\n\n // Column choices, labelled from the header row when \"first row is header\".\n const columnOptions = useMemo(() => {\n const header = state.useHeader ? source[0] : undefined;\n return Array.from({ length: colCount }, (_, i) => ({\n value: i,\n label: columnLabel(i, header, state.useHeader),\n }));\n }, [source, colCount, state.useHeader]);\n\n const apply = () => {\n const pivot = buildPivot(source, state.useHeader, state.groupCol, state.valueCol, state.aggFn);\n if (!pivot) {\n setError('The selection has no data rows to summarize.');\n return;\n }\n\n const wb = api.univer.getActiveWorkbook();\n if (!wb) {\n setError('No active workbook.');\n return;\n }\n\n try {\n if (state.destination === 'newSheet') {\n const name = state.sheetName.trim() || 'Pivot';\n const rows = Math.max(pivot.grid.length + 2, 10);\n // create(name, rows, columns) → FWorksheet (f-workbook.d.ts L178).\n const sheet = (\n wb as unknown as { create: (n: string, r: number, c: number) => SheetView }\n ).create(name, rows, 4);\n const target = sheet.getRange(`A1:${toA1(pivot.grid.length - 1, 1)}`);\n target.setValues(pivot.grid);\n } else {\n const anchor = state.anchor.trim().toUpperCase();\n if (!/^[A-Z]+[0-9]+$/.test(anchor)) {\n setError('Enter a valid top-left cell, e.g. E1.');\n return;\n }\n const sheet = wb.getActiveSheet() as unknown as SheetView | null;\n if (!sheet) {\n setError('No active sheet to write into.');\n return;\n }\n // Anchor + grid extent -> destination A1 range, then setValues.\n const m = /^([A-Z]+)([0-9]+)$/.exec(anchor)!;\n let col = 0;\n for (const ch of m[1]) col = col * 26 + (ch.charCodeAt(0) - 64);\n col -= 1;\n const startRow = Number(m[2]) - 1;\n const end = toA1(startRow + pivot.grid.length - 1, col + 1);\n sheet.getRange(`${anchor}:${end}`).setValues(pivot.grid);\n }\n } catch (e) {\n setError(e instanceof Error ? e.message : 'Failed to create the pivot table.');\n return;\n }\n\n onClose();\n };\n\n return (\n <Dialog\n title=\"Insert pivot table\"\n onClose={onClose}\n width={460}\n data-testid=\"cs-insert-pivot-dialog\"\n footer={\n <>\n <button type=\"button\" style={DIALOG_BTN_SECONDARY_STYLE} onClick={onClose}>\n Cancel\n </button>\n <button\n type=\"button\"\n style={DIALOG_BTN_PRIMARY_STYLE}\n data-testid=\"cs-insert-pivot-create\"\n disabled={!hasSource}\n onClick={apply}\n >\n Create\n </button>\n </>\n }\n >\n {hasSource ? (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-insert-pivot-source\">\n Source data <strong>{rangeLabel ?? 'the current selection'}</strong> ({source.length} rows\n × {colCount} columns)\n </div>\n ) : (\n <div style={RANGE_NOTE_STYLE} data-testid=\"cs-insert-pivot-no-selection\">\n Select the source data range first (including its header row), then reopen this dialog.\n </div>\n )}\n\n <label style={CHECK_STYLE} data-testid=\"cs-insert-pivot-header-label\">\n <input\n type=\"checkbox\"\n data-testid=\"cs-insert-pivot-header\"\n checked={state.useHeader}\n onChange={(e) => update('useHeader', e.target.checked)}\n disabled={!hasSource}\n />\n <span>First row is a header</span>\n </label>\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Rows (group by)</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-insert-pivot-group-col\"\n value={state.groupCol}\n disabled={!hasSource}\n onChange={(e) => update('groupCol', Number(e.target.value))}\n >\n {columnOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Values</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-insert-pivot-value-col\"\n value={state.valueCol}\n disabled={!hasSource}\n onChange={(e) => update('valueCol', Number(e.target.value))}\n >\n {columnOptions.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Summarize by</span>\n <select\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-insert-pivot-agg\"\n value={state.aggFn}\n disabled={!hasSource}\n onChange={(e) => update('aggFn', e.target.value as AggFn)}\n >\n {AGG_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n\n <div style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Destination</span>\n <label style={RADIO_ROW_STYLE}>\n <input\n type=\"radio\"\n name=\"cs-insert-pivot-destination\"\n data-testid=\"cs-insert-pivot-dest-new\"\n checked={state.destination === 'newSheet'}\n onChange={() => update('destination', 'newSheet')}\n />\n <span>New sheet</span>\n </label>\n <label style={RADIO_ROW_STYLE}>\n <input\n type=\"radio\"\n name=\"cs-insert-pivot-destination\"\n data-testid=\"cs-insert-pivot-dest-existing\"\n checked={state.destination === 'existing'}\n onChange={() => update('destination', 'existing')}\n />\n <span>Existing sheet (choose top-left cell)</span>\n </label>\n </div>\n\n {state.destination === 'newSheet' ? (\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>New sheet name</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-insert-pivot-sheet-name\"\n value={state.sheetName}\n placeholder=\"Pivot\"\n onChange={(e) => update('sheetName', e.target.value)}\n />\n </label>\n ) : (\n <label style={DIALOG_FIELD_STYLE}>\n <span style={DIALOG_LABEL_STYLE}>Top-left cell (on the active sheet)</span>\n <input\n style={DIALOG_INPUT_STYLE}\n data-testid=\"cs-insert-pivot-anchor\"\n value={state.anchor}\n placeholder=\"e.g. E1\"\n onChange={(e) => update('anchor', e.target.value)}\n />\n </label>\n )}\n\n {error && (\n <div\n style={{\n ...RANGE_NOTE_STYLE,\n color: 'var(--cs-chrome-danger, #b3261e)',\n marginBottom: 0,\n }}\n data-testid=\"cs-insert-pivot-error\"\n role=\"alert\"\n >\n {error}\n </div>\n )}\n </Dialog>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * FormulaBar — minimal built-in formula bar for `<CasualSheets chrome>`.\n *\n * The formula bar: a NameBox (active-cell ref + go-to navigation) and an editable\n * input that shows the active cell's formula (or value) and commits edits through\n * the facade — `=…` as a formula, a number as a number, else text. Typing a\n * function name after `=` shows an autocomplete dropdown (arrows + Enter/Tab to\n * complete, Escape to dismiss). Self-contained: drives the editor only via\n * `CasualSheetsAPI`.\n */\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n} from 'react';\nimport { ICommandService } from '@univerjs/core';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { NameBox } from './NameBox';\n\n// Curated common spreadsheet functions for the autocomplete dropdown. (Univer\n// ships ~530; this covers what people actually type without bundling them all.)\nconst FUNCTIONS = [\n 'ABS',\n 'AND',\n 'AVERAGE',\n 'AVERAGEIF',\n 'AVERAGEIFS',\n 'CEILING',\n 'CHOOSE',\n 'COLUMN',\n 'COLUMNS',\n 'CONCAT',\n 'CONCATENATE',\n 'COUNT',\n 'COUNTA',\n 'COUNTBLANK',\n 'COUNTIF',\n 'COUNTIFS',\n 'DATE',\n 'DATEDIF',\n 'DAY',\n 'EDATE',\n 'EOMONTH',\n 'EXACT',\n 'FILTER',\n 'FIND',\n 'FLOOR',\n 'HLOOKUP',\n 'HOUR',\n 'IF',\n 'IFERROR',\n 'IFNA',\n 'IFS',\n 'INDEX',\n 'INDIRECT',\n 'INT',\n 'ISBLANK',\n 'ISERROR',\n 'ISNA',\n 'ISNUMBER',\n 'ISTEXT',\n 'LEFT',\n 'LEN',\n 'LOOKUP',\n 'LOWER',\n 'MATCH',\n 'MAX',\n 'MAXIFS',\n 'MEDIAN',\n 'MID',\n 'MIN',\n 'MINIFS',\n 'MINUTE',\n 'MOD',\n 'MONTH',\n 'NETWORKDAYS',\n 'NOT',\n 'NOW',\n 'OFFSET',\n 'OR',\n 'POWER',\n 'PRODUCT',\n 'PROPER',\n 'RAND',\n 'RANDBETWEEN',\n 'RANK',\n 'REPLACE',\n 'REPT',\n 'RIGHT',\n 'ROUND',\n 'ROUNDDOWN',\n 'ROUNDUP',\n 'ROW',\n 'ROWS',\n 'SEARCH',\n 'SECOND',\n 'SORT',\n 'SQRT',\n 'SUBSTITUTE',\n 'SUM',\n 'SUMIF',\n 'SUMIFS',\n 'SUMPRODUCT',\n 'SWITCH',\n 'TEXT',\n 'TEXTJOIN',\n 'TODAY',\n 'TRANSPOSE',\n 'TRIM',\n 'UNIQUE',\n 'UPPER',\n 'VALUE',\n 'VLOOKUP',\n 'WEEKDAY',\n 'WORKDAY',\n 'XLOOKUP',\n 'XMATCH',\n 'YEAR',\n];\n\nconst TOKEN_RE = /([A-Za-z][A-Za-z0-9._]*)$/;\n\n/** Function suggestions for the trailing identifier of a formula draft. */\nfunction suggestFor(draft: string | null): string[] {\n if (!draft || !draft.startsWith('=')) return [];\n const m = TOKEN_RE.exec(draft);\n if (!m) return [];\n const prefix = m[1].toUpperCase();\n return FUNCTIONS.filter((f) => f.startsWith(prefix) && f !== prefix).slice(0, 8);\n}\n\n/** A1 column letters from a 0-based column index (0→A, 26→AA). */\nfunction colToLetters(col: number): string {\n let s = '';\n let n = col;\n do {\n s = String.fromCharCode(65 + (n % 26)) + s;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n return s;\n}\n\ninterface ActiveCell {\n a1: string;\n /** Formula text (`=…`) if the cell has one, else the raw value as a string. */\n text: string;\n}\n\nfunction readActiveCell(api: CasualSheetsAPI): ActiveCell | null {\n const sel = api.getSelection();\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sel || !sheet) return null;\n const { startRow, startColumn } = sel.range;\n const range = sheet.getRange(startRow, startColumn);\n const formula = range.getFormula?.() || '';\n const raw = range.getValue?.();\n return {\n a1: colToLetters(startColumn) + (startRow + 1),\n text: formula || (raw == null ? '' : String(raw)),\n };\n}\n\nconst BAR_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 6,\n padding: '3px 6px',\n borderBottom: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.12))',\n background: 'var(--cs-chrome-bg, #f8f9fa)',\n flex: '0 0 auto',\n font: 'inherit',\n fontSize: 13,\n};\n\nconst FX_STYLE: CSSProperties = {\n flex: '0 0 auto',\n fontStyle: 'italic',\n color: 'var(--cs-chrome-muted, #6b7280)',\n};\n\nconst INPUT_STYLE: CSSProperties = {\n width: '100%',\n height: 24,\n padding: '0 8px',\n border: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.18))',\n borderRadius: 4,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #1f2329)',\n font: 'inherit',\n fontSize: 13,\n boxSizing: 'border-box',\n};\n\nconst INPUT_WRAP_STYLE: CSSProperties = { position: 'relative', flex: '1 1 auto', minWidth: 0 };\n\nconst AC_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: 2,\n minWidth: 200,\n maxHeight: 240,\n overflowY: 'auto',\n zIndex: 1000,\n padding: 4,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n borderRadius: 8,\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.16)',\n};\n\nconst AC_ITEM_STYLE: CSSProperties = {\n display: 'block',\n width: '100%',\n textAlign: 'left',\n height: 26,\n padding: '0 8px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n};\n\nexport interface FormulaBarProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function FormulaBar({ api }: FormulaBarProps) {\n const [cell, setCell] = useState<ActiveCell | null>(null);\n // null = mirror the active cell; a string = the user is editing.\n const [draft, setDraft] = useState<string | null>(null);\n const draftRef = useRef<string | null>(null);\n draftRef.current = draft;\n // Autocomplete: active suggestion index + a dismissed flag (Escape closes the\n // dropdown without cancelling the edit).\n const [acIdx, setAcIdx] = useState(0);\n const [acDismissed, setAcDismissed] = useState(false);\n\n useEffect(() => {\n if (!api) return;\n const refresh = () => {\n // Don't clobber an in-progress edit on unrelated command activity.\n if (draftRef.current !== null) return;\n setCell(readActiveCell(api));\n };\n refresh();\n const injector = (api.univer as unknown as { _injector?: { get(t: unknown): unknown } })\n ._injector;\n const cmd = injector?.get(ICommandService) as\n | { onCommandExecuted: (cb: () => void) => { dispose: () => void } }\n | undefined;\n const sub = cmd?.onCommandExecuted(() => refresh());\n return () => sub?.dispose();\n }, [api]);\n\n const suggestions = useMemo(() => suggestFor(draft), [draft]);\n const acOpen = !acDismissed && suggestions.length > 0;\n\n const commit = (text: string) => {\n setDraft(null);\n setAcDismissed(false);\n if (!api) return;\n const sel = api.getSelection();\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sel || !sheet) return;\n const range = sheet.getRange(sel.range.startRow, sel.range.startColumn);\n const t = text.trim();\n if (t.startsWith('=')) range.setValue({ f: t });\n else if (t !== '' && !Number.isNaN(Number(t))) range.setValue(Number(t));\n else range.setValue(t);\n };\n\n const onType = (v: string) => {\n setDraft(v);\n setAcIdx(0);\n setAcDismissed(false);\n };\n\n // Replace the trailing identifier with the chosen function + '('.\n const complete = (fn: string) => {\n const base = draft ?? '';\n setDraft(base.replace(TOKEN_RE, `${fn}(`));\n setAcIdx(0);\n };\n\n const onKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (acOpen) {\n if (e.key === 'ArrowDown') {\n e.preventDefault();\n setAcIdx((i) => Math.min(i + 1, suggestions.length - 1));\n return;\n }\n if (e.key === 'ArrowUp') {\n e.preventDefault();\n setAcIdx((i) => Math.max(i - 1, 0));\n return;\n }\n if (e.key === 'Enter' || e.key === 'Tab') {\n e.preventDefault();\n complete(suggestions[acIdx] ?? suggestions[0]);\n return;\n }\n if (e.key === 'Escape') {\n e.preventDefault();\n setAcDismissed(true);\n return;\n }\n }\n if (e.key === 'Enter') {\n e.preventDefault();\n commit((e.target as HTMLInputElement).value);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setDraft(null);\n (e.target as HTMLInputElement).blur();\n }\n };\n\n const shown = draft ?? cell?.text ?? '';\n\n return (\n <div style={BAR_STYLE} data-testid=\"casual-sheets-formula-bar\">\n <NameBox api={api} />\n <span style={FX_STYLE} aria-hidden>\n fx\n </span>\n <div style={INPUT_WRAP_STYLE}>\n <input\n type=\"text\"\n aria-label=\"Formula bar\"\n data-testid=\"casual-sheets-formula-input\"\n style={INPUT_STYLE}\n value={shown}\n onChange={(e) => onType(e.target.value)}\n onKeyDown={onKeyDown}\n onBlur={(e) => {\n if (draftRef.current !== null) commit(e.target.value);\n }}\n disabled={!api}\n />\n {acOpen && (\n <div style={AC_STYLE} data-testid=\"cs-formula-suggestions\" role=\"listbox\">\n {suggestions.map((fn, i) => (\n <button\n key={fn}\n type=\"button\"\n role=\"option\"\n aria-selected={i === acIdx}\n data-testid={`cs-formula-suggestion-${fn}`}\n style={{\n ...AC_ITEM_STYLE,\n background: i === acIdx ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent',\n color: i === acIdx ? 'var(--cs-chrome-active-fg, #0e7490)' : AC_ITEM_STYLE.color,\n }}\n // mousedown+preventDefault so the input keeps focus (no blur-commit).\n onMouseDown={(e) => {\n e.preventDefault();\n complete(fn);\n }}\n onMouseEnter={() => setAcIdx(i)}\n >\n {fn}\n </button>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * NameBox — the Excel \"Name Box\" for `<CasualSheets chrome>`.\n *\n * A small editable box that mirrors the active cell's A1 reference live, and\n * lets you navigate by typing a reference (e.g. `B5` or `A1:C3`) + Enter. Self-\n * contained: reads the active selection through `CasualSheetsAPI` and navigates\n * through the FUniver facade (`getRange(a1).activate()`) — no app context, no\n * named-range support (defined names land with the rich name-box later).\n *\n * The orchestrator uses this to replace the static name-box span currently\n * inside FormulaBar.tsx; this component does NOT edit FormulaBar.\n */\n\nimport { useEffect, useRef, useState, type CSSProperties, type KeyboardEvent } from 'react';\nimport { ICommandService } from '@univerjs/core';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\n\n/** A defined name as surfaced by the FWorkbook facade. */\ninterface DefinedNameEntry {\n name: string;\n ref: string;\n}\n\n/**\n * Read the active workbook's defined names through the FWorkbook facade\n * (`getDefinedNames()` → `FDefinedName[]`, each with `getName()` +\n * `getFormulaOrRefString()`). Returns [] when the facade/API is unavailable —\n * never invents an API.\n */\nfunction readDefinedNames(api: CasualSheetsAPI | null): DefinedNameEntry[] {\n if (!api) return [];\n try {\n const wb = api.univer.getActiveWorkbook() as unknown as {\n getDefinedNames?: () => Array<{\n getName?: () => string;\n getFormulaOrRefString?: () => string;\n }>;\n } | null;\n const names = wb?.getDefinedNames?.();\n if (!names) return [];\n return names\n .map((dn) => ({\n name: dn.getName?.() ?? '',\n ref: dn.getFormulaOrRefString?.() ?? '',\n }))\n .filter((e) => e.name !== '');\n } catch {\n return [];\n }\n}\n\n/** A1 column letters from a 0-based column index (0→A, 26→AA). */\nfunction colToLetters(col: number): string {\n let s = '';\n let n = col;\n do {\n s = String.fromCharCode(65 + (n % 26)) + s;\n n = Math.floor(n / 26) - 1;\n } while (n >= 0);\n return s;\n}\n\n/** The active selection's top-left A1 reference, or '' when unavailable. */\nfunction readActiveRef(api: CasualSheetsAPI): string {\n const sel = api.getSelection();\n if (!sel) return '';\n const { startRow, startColumn } = sel.range;\n return colToLetters(startColumn) + (startRow + 1);\n}\n\nconst BOX_STYLE: CSSProperties = {\n flex: '0 0 auto',\n width: 80,\n height: 24,\n padding: '0 8px',\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n borderRadius: 4,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n textAlign: 'center',\n boxSizing: 'border-box',\n};\n\nconst ROOT_STYLE: CSSProperties = {\n flex: '0 0 auto',\n display: 'inline-flex',\n alignItems: 'center',\n position: 'relative',\n};\n\nconst DROPDOWN_BTN_STYLE: CSSProperties = {\n flex: '0 0 auto',\n width: 20,\n height: 24,\n marginLeft: 2,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 4,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n cursor: 'pointer',\n padding: 0,\n};\n\nconst MENU_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: 4,\n zIndex: 1000,\n minWidth: 160,\n maxHeight: 280,\n overflowY: 'auto',\n padding: 4,\n borderRadius: 8,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.18)',\n};\n\nconst MENU_ITEM_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'baseline',\n justifyContent: 'space-between',\n gap: 12,\n width: '100%',\n height: 28,\n padding: '0 8px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n textAlign: 'left',\n cursor: 'pointer',\n boxSizing: 'border-box',\n};\n\nconst MENU_EMPTY_STYLE: CSSProperties = {\n padding: '6px 8px',\n color: 'var(--cs-chrome-muted, #8a8886)',\n fontSize: 12,\n whiteSpace: 'nowrap',\n};\n\nconst ITEM_REF_STYLE: CSSProperties = {\n color: 'var(--cs-chrome-muted, #8a8886)',\n fontSize: 11,\n flex: '0 0 auto',\n};\n\nexport interface NameBoxProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function NameBox({ api }: NameBoxProps) {\n // The A1 reference of the active cell.\n const [ref, setRef] = useState('');\n // null = mirror the active cell; a string = the user is typing.\n const [draft, setDraft] = useState<string | null>(null);\n const draftRef = useRef<string | null>(null);\n draftRef.current = draft;\n const inputRef = useRef<HTMLInputElement>(null);\n // The defined-names dropdown: open state, current entries, and a root ref for\n // outside-pointerdown detection (mirrors ColorPicker's popover pattern).\n const [open, setOpen] = useState(false);\n const [names, setNames] = useState<DefinedNameEntry[]>([]);\n const rootRef = useRef<HTMLDivElement>(null);\n\n // Reflect the active cell: subscribe to command activity (covers selection\n // moves) and re-read the reference — unless the user is mid-edit.\n useEffect(() => {\n if (!api) return;\n const refresh = () => {\n if (draftRef.current !== null) return;\n setRef(readActiveRef(api));\n };\n refresh();\n const injector = (api.univer as unknown as { _injector?: { get(t: unknown): unknown } })\n ._injector;\n const cmd = injector?.get(ICommandService) as\n | { onCommandExecuted: (cb: () => void) => { dispose: () => void } }\n | undefined;\n const sub = cmd?.onCommandExecuted(() => refresh());\n return () => sub?.dispose();\n }, [api]);\n\n // While the dropdown is open, close it on Escape or any outside pointerdown.\n useEffect(() => {\n if (!open) return;\n const onPointerDown = (e: PointerEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n };\n const onKeyDown = (e: globalThis.KeyboardEvent) => {\n if (e.key === 'Escape') setOpen(false);\n };\n document.addEventListener('pointerdown', onPointerDown, true);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('pointerdown', onPointerDown, true);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [open]);\n\n /** Navigate to the typed A1 reference / range. Invalid input is ignored. */\n const navigate = (text: string) => {\n const t = text.trim();\n setDraft(null);\n if (!api || t === '') {\n setRef(readActiveRef(api ?? ({} as CasualSheetsAPI)));\n return;\n }\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sheet) return;\n try {\n // FRange.getRange parses an A1 string (\"B5\") or range (\"A1:C3\").\n const range = (sheet as unknown as { getRange(a1: string): { activate(): void } }).getRange(\n t,\n );\n range.activate();\n } catch {\n // Invalid reference — fall back to the current selection.\n setRef(readActiveRef(api));\n }\n };\n\n // Open the dropdown: refresh the defined-name list from the live workbook,\n // then toggle. mousedown (not click) so the grid selection isn't lost first.\n const toggleDropdown = () => {\n setOpen((cur) => {\n const next = !cur;\n if (next) setNames(readDefinedNames(api));\n return next;\n });\n };\n\n // Navigate to a defined name's range. The ref may carry a sheet prefix\n // (\"Sheet1!$A$1\") and absolute `$` markers — strip both, then reuse the same\n // getRange(...).activate() path the typed-reference navigation uses.\n const navigateName = (entry: DefinedNameEntry) => {\n setOpen(false);\n const raw = entry.ref.trim();\n if (raw === '') return;\n const afterSheet = raw.includes('!') ? raw.slice(raw.lastIndexOf('!') + 1) : raw;\n const a1 = afterSheet.replace(/\\$/g, '');\n navigate(a1);\n };\n\n const onKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n navigate((e.target as HTMLInputElement).value);\n (e.target as HTMLInputElement).blur();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setDraft(null);\n setRef(api ? readActiveRef(api) : '');\n (e.target as HTMLInputElement).blur();\n }\n };\n\n const shown = draft ?? ref;\n\n return (\n <div ref={rootRef} style={ROOT_STYLE}>\n <input\n ref={inputRef}\n type=\"text\"\n aria-label=\"Name box\"\n title=\"Name box\"\n data-testid=\"cs-namebox-input\"\n style={BOX_STYLE}\n value={shown}\n disabled={!api}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onKeyDown}\n onFocus={(e) => e.currentTarget.select()}\n onBlur={() => {\n // Abandon any uncommitted edit without navigating.\n if (draftRef.current !== null) {\n setDraft(null);\n setRef(api ? readActiveRef(api) : '');\n }\n }}\n />\n <button\n type=\"button\"\n title=\"Defined names\"\n aria-label=\"Defined names\"\n aria-haspopup=\"true\"\n aria-expanded={open}\n data-testid=\"cs-namebox-dropdown\"\n style={{\n ...DROPDOWN_BTN_STYLE,\n background: open ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent',\n color: open ? 'var(--cs-chrome-active-fg, #0e7490)' : DROPDOWN_BTN_STYLE.color,\n }}\n disabled={!api}\n // mousedown (not click) so the grid's selection isn't lost first.\n onMouseDown={(e) => {\n e.preventDefault();\n toggleDropdown();\n }}\n >\n <Icon name=\"expand_more\" size={18} />\n </button>\n {open && (\n <div style={MENU_STYLE} role=\"menu\" data-testid=\"cs-namebox-menu\">\n {names.length === 0 ? (\n <div style={MENU_EMPTY_STYLE}>No names</div>\n ) : (\n names.map((entry, i) => (\n <button\n key={entry.name}\n type=\"button\"\n role=\"menuitem\"\n title={entry.ref || entry.name}\n data-testid={`cs-namebox-name-${i}`}\n style={MENU_ITEM_STYLE}\n onMouseDown={(e) => {\n e.preventDefault();\n navigateName(entry);\n }}\n onMouseEnter={(e) => {\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n >\n <span>{entry.name}</span>\n {entry.ref && <span style={ITEM_REF_STYLE}>{entry.ref}</span>}\n </button>\n ))\n )}\n </div>\n )}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * StatusBar — built-in status bar for `<CasualSheets chrome>`.\n *\n * Self-contained: reads the active selection through `CasualSheetsAPI` and shows\n * Excel-style aggregates over it (Average / Count / Numerical Count / Min / Max\n * / Sum), plus a zoom control on the right (− / level / +, click the level to\n * reset to 100%). Drives the editor only through the facade + commands.\n *\n * Count = non-empty cells (any type); Numerical Count = numeric cells; the\n * numeric aggregates (Average/Min/Max/Sum) run over the numeric cells only —\n * matching Excel's status-bar semantics.\n *\n * Zoom dispatches the OPERATION `sheet.operation.set-zoom-ratio` (not the\n * `set-zoom-ratio` / `change-zoom-ratio` commands, which bail when Univer's\n * always-present formula-bar editor unit reports visible). The operation's\n * render controller registers in sheets-ui's `onRendered` lifecycle — i.e. a\n * frame or two after `onReady` — so the buttons just no-op until the grid has\n * painted; in practice the user can't click that fast.\n */\n\nimport { useEffect, useState, type CSSProperties } from 'react';\nimport { ICommandService } from '@univerjs/core';\nimport type { CasualSheetsAPI } from '../sheets/api';\n\ninterface Stats {\n /** Non-empty cells (any type). */\n count: number;\n /** Numeric cells. */\n numCount: number;\n sum: number;\n avg: number;\n min: number;\n max: number;\n}\n\nfunction readStats(api: CasualSheetsAPI): Stats | null {\n const sel = api.getSelection();\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sel || !sheet) return null;\n const { startRow, startColumn, endRow, endColumn } = sel.range;\n // Single cell → nothing to aggregate (matches Excel).\n if (startRow === endRow && startColumn === endColumn) return null;\n const values = sheet.getRange(sel.range).getValues?.() as unknown[][] | undefined;\n if (!values) return null;\n let count = 0;\n let numCount = 0;\n let sum = 0;\n let min = Infinity;\n let max = -Infinity;\n for (const row of values) {\n for (const v of row) {\n if (v == null || v === '') continue;\n count += 1;\n if (typeof v === 'number' && Number.isFinite(v)) {\n numCount += 1;\n sum += v;\n if (v < min) min = v;\n if (v > max) max = v;\n }\n }\n }\n if (count === 0) return null;\n return { count, numCount, sum, avg: numCount ? sum / numCount : 0, min, max };\n}\n\n/** Current zoom as a fraction (1 = 100%). Reads the live worksheet config via\n * the facade's `getSheet()` escape hatch; falls back to 1. */\nfunction readZoom(api: CasualSheetsAPI): number {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ws = (sheet as any)?.getSheet?.();\n const z = ws?.getConfig?.().zoomRatio;\n return typeof z === 'number' && z > 0 ? z : 1;\n}\n\n// Trim float noise without locking to a fixed precision.\nfunction fmt(n: number): string {\n return Number(n.toFixed(10)).toLocaleString();\n}\n\nconst BAR_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'flex-end',\n gap: 16,\n height: 24,\n padding: '0 12px',\n borderTop: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.12))',\n background: 'var(--cs-chrome-bg, #f8f9fa)',\n color: 'var(--cs-chrome-muted, #4b5563)',\n flex: '0 0 auto',\n font: 'inherit',\n fontSize: 12,\n userSelect: 'none',\n};\n\nconst ZOOM_GROUP_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n};\n\nconst ZOOM_BTN_STYLE: CSSProperties = {\n width: 20,\n height: 18,\n border: 'none',\n borderRadius: 4,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n cursor: 'pointer',\n fontSize: 14,\n lineHeight: 1,\n padding: 0,\n};\n\nconst ZOOM_LEVEL_STYLE: CSSProperties = {\n minWidth: 40,\n height: 18,\n border: 'none',\n borderRadius: 4,\n background: 'transparent',\n color: 'var(--cs-chrome-muted, #4b5563)',\n cursor: 'pointer',\n font: 'inherit',\n fontSize: 12,\n textAlign: 'center',\n};\n\nexport interface StatusBarProps {\n api: CasualSheetsAPI | null;\n}\n\nexport function StatusBar({ api }: StatusBarProps) {\n const [stats, setStats] = useState<Stats | null>(null);\n const [zoom, setZoom] = useState(1);\n\n useEffect(() => {\n if (!api) return;\n const refresh = () => {\n setStats(readStats(api));\n setZoom(readZoom(api));\n };\n refresh();\n const injector = (api.univer as unknown as { _injector?: { get(t: unknown): unknown } })\n ._injector;\n const cmd = injector?.get(ICommandService) as\n | { onCommandExecuted: (cb: () => void) => { dispose: () => void } }\n | undefined;\n const sub = cmd?.onCommandExecuted(() => refresh());\n return () => sub?.dispose();\n }, [api]);\n\n // Drive the zoom OPERATION directly — see file header for why not the commands.\n const setZoomRatio = (ratio: number) => {\n const wb = api?.univer.getActiveWorkbook();\n const sheet = wb?.getActiveSheet();\n if (!wb || !sheet) return;\n const clamped = Math.min(4, Math.max(0.1, ratio));\n void api?.executeCommand('sheet.operation.set-zoom-ratio', {\n unitId: wb.getId(),\n subUnitId: sheet.getSheetId(),\n zoomRatio: clamped,\n });\n // Optimistic local update — the onCommandExecuted refresh will reconcile.\n setZoom(clamped);\n };\n const zoomBy = (delta: number) => setZoomRatio(Math.round((zoom + delta) * 100) / 100);\n const resetZoom = () => setZoomRatio(1);\n\n return (\n <div style={BAR_STYLE} data-testid=\"casual-sheets-status-bar\">\n {stats && (\n <>\n {stats.numCount > 0 && <span data-stat=\"average\">Average: {fmt(stats.avg)}</span>}\n <span data-stat=\"count\">Count: {stats.count}</span>\n {stats.numCount > 0 && (\n <>\n <span data-stat=\"num-count\">Numerical Count: {stats.numCount}</span>\n <span data-stat=\"min\">Min: {fmt(stats.min)}</span>\n <span data-stat=\"max\">Max: {fmt(stats.max)}</span>\n <span data-stat=\"sum\">Sum: {fmt(stats.sum)}</span>\n </>\n )}\n </>\n )}\n <span style={ZOOM_GROUP_STYLE} data-testid=\"cs-zoom\">\n <button\n type=\"button\"\n style={ZOOM_BTN_STYLE}\n aria-label=\"Zoom out\"\n title=\"Zoom out\"\n data-testid=\"cs-zoom-out\"\n disabled={!api}\n onMouseDown={(e) => {\n e.preventDefault();\n zoomBy(-0.1);\n }}\n >\n −\n </button>\n <button\n type=\"button\"\n style={ZOOM_LEVEL_STYLE}\n aria-label=\"Reset zoom to 100%\"\n title=\"Reset zoom to 100%\"\n data-testid=\"cs-zoom-level\"\n disabled={!api}\n onMouseDown={(e) => {\n e.preventDefault();\n resetZoom();\n }}\n >\n {Math.round(zoom * 100)}%\n </button>\n <button\n type=\"button\"\n style={ZOOM_BTN_STYLE}\n aria-label=\"Zoom in\"\n title=\"Zoom in\"\n data-testid=\"cs-zoom-in\"\n disabled={!api}\n onMouseDown={(e) => {\n e.preventDefault();\n zoomBy(0.1);\n }}\n >\n +\n </button>\n </span>\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * MenuBar — the built-in dropdown menu row for `<CasualSheets chrome>`.\n *\n * Office / Google-Sheets-style horizontal menu strip (no logo, no title — the\n * host frames the editor with its own bar): File · Edit · View · Insert ·\n * Format · Data · Help. Each top-level button opens a dropdown of items that\n * either dispatch a verified Univer command / facade call through the\n * `CasualSheetsAPI` (no app context), or — for actions that need a dialog the\n * SDK doesn't ship — route through the optional `onDialogRequest` host hook.\n *\n * This mirrors `apps/web/src/shell/MenuBar.tsx`, but reimplements every action\n * INLINE against `api` / `api.univer` (the FUniver facade) + `api.executeCommand`.\n * The command ids + facade logic are copied verbatim from\n * `apps/web/src/shell/home-tab-actions.ts` + `tab-actions.ts` so behaviour\n * matches the real app exactly.\n *\n * Feature flags: pass `features` to hide a control or whole menu group when its\n * feature is disabled. Defaults to all-enabled. A control whose feature is\n * `false` does not render. An entire top-level menu that ends up with no\n * runnable items is dropped.\n *\n * Dialog routing: items marked `dialog: '<kind>'` (Format Cells, Insert Chart,\n * PivotTable, Find & Replace, Insert/Delete cells, Sparkline, Name Manager,\n * Goal Seek, Data Validation, Conditional Formatting, …) call\n * `onDialogRequest(kind, context)` so the host renders its own UI. When\n * `onDialogRequest` is not provided, those items are omitted (the SDK never\n * fakes a dialog).\n *\n * Self-contained: only one menu is open at a time; Escape and an outside\n * pointerdown close it.\n */\n\nimport { useEffect, useRef, useState, type CSSProperties, type ReactNode } from 'react';\nimport { BorderStyleTypes, BorderType } from '@univerjs/core';\nimport { openExternal } from './openExternal';\nimport type { FUniver } from '@univerjs/core/facade';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { ensurePluginByName } from '../univer';\nimport { Icon } from './Icon';\nimport { ensureChromeFonts } from './fonts';\nimport { useDialogs } from './dialog-context';\nimport type { ChromeExtensions } from './extensions';\nimport {\n computeVisibleMenus,\n type MenuDef,\n type MenuId,\n type MenuItemDef,\n type RunFn,\n} from './menu-model';\n\nexport type { MenuDialogKind } from './menu-model';\n\n/**\n * The menu data model + pure gating engine live in `./menu-model` (univer-free,\n * so unit-testable). `RunFn` / `MenuItemDef` / `MenuDef` / `MenuId` /\n * `MenuDialogKind` are re-imported above; the `run` handlers that populate\n * `MENUS` are defined inline below against the `@univerjs/core` facade.\n */\n\n/**\n * Pretty-print a `Ctrl+Shift+X` shortcut for the current platform. The SDK\n * doesn't import the app's `formatShortcut`, so this is a compact inline\n * equivalent: on macOS, swap Ctrl→⌘, Alt→⌥, Shift→⇧ and drop the `+`.\n */\nfunction fmtShortcut(shortcut: string): string {\n const isMac =\n typeof navigator !== 'undefined' && /Mac|iPhone|iPad/i.test(navigator.platform || '');\n if (!isMac) return shortcut;\n return shortcut\n .split('+')\n .map((part) => {\n switch (part) {\n case 'Ctrl':\n return '⌘';\n case 'Alt':\n return '⌥';\n case 'Shift':\n return '⇧';\n default:\n return part;\n }\n })\n .join('');\n}\n\n/* ───────────────────────── inline action helpers ─────────────────────────\n * Every helper below is a faithful port of the corresponding function in\n * apps/web/src/shell/home-tab-actions.ts + tab-actions.ts, reimplemented over\n * the SDK's `api` (CasualSheetsAPI) / `api.univer` (FUniver) so the chrome\n * never imports app context. Command ids are identical to the app's.\n */\n\nfunction fu(api: CasualSheetsAPI): FUniver {\n return api.univer;\n}\n\nfunction activeRange(api: CasualSheetsAPI) {\n return fu(api).getActiveWorkbook()?.getActiveSheet()?.getActiveRange() ?? null;\n}\n\nfunction activeSheet(api: CasualSheetsAPI) {\n return fu(api).getActiveWorkbook()?.getActiveSheet() ?? null;\n}\n\n/** Selection as A1 (e.g. `B2:D10`), or null. Used to seed dialog context. */\nfunction selectionA1(api: CasualSheetsAPI): string | null {\n const range = activeRange(api);\n if (!range) return null;\n try {\n return range.getA1Notation();\n } catch {\n return null;\n }\n}\n\n/* ── Edit ─────────────────────────────────────────────────────────────── */\n\nconst undo: RunFn = (api) => void api.executeCommand('univer.command.undo');\nconst redo: RunFn = (api) => void api.executeCommand('univer.command.redo');\nconst cut: RunFn = (api) => void api.executeCommand('univer.command.cut');\nconst copy: RunFn = (api) => void api.executeCommand('univer.command.copy');\nconst paste: RunFn = (api) => void api.executeCommand('univer.command.paste');\nconst pasteFormattingOnly: RunFn = (api) => void api.executeCommand('sheet.command.paste-format');\n\n/* ── Insert (facade-driven; mirror tab-actions.ts) ─────────────────────── */\n\nconst insertRowAbove: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.insertRowBefore(range.getRow());\n};\n\nconst insertRowBelow: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.insertRowAfter(range.getRow() + range.getHeight() - 1);\n};\n\nconst insertColumnLeft: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.insertColumnBefore(range.getColumn());\n};\n\nconst insertColumnRight: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.insertColumnAfter(range.getColumn() + range.getWidth() - 1);\n};\n\nconst deleteSelectedRow: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.deleteRows(range.getRow(), range.getHeight());\n};\n\nconst deleteSelectedColumn: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n sheet.deleteColumns(range.getColumn(), range.getWidth());\n};\n\nconst insertNewSheet: RunFn = (api) => {\n fu(api).getActiveWorkbook()?.insertSheet();\n};\n\nconst insertImage: RunFn = (api) => void api.executeCommand('sheet.command.insert-float-image');\n\nconst insertHyperlink: RunFn = (api) =>\n void api.executeCommand('sheet.operation.insert-hyper-link');\n\nconst insertComment: RunFn = (api) => void api.executeCommand('sheet.operation.show-comment-modal');\n\nconst insertTodayDate: RunFn = (api) => {\n const range = activeRange(api);\n if (!range) return;\n const today = new Date();\n const pad = (n: number) => n.toString().padStart(2, '0');\n const v = `${today.getFullYear()}-${pad(today.getMonth() + 1)}-${pad(today.getDate())}`;\n range.setValue({ v });\n};\n\nconst insertCurrentTime: RunFn = (api) => {\n const range = activeRange(api);\n if (!range) return;\n const now = new Date();\n const pad = (n: number) => n.toString().padStart(2, '0');\n const v = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;\n range.setValue({ v });\n};\n\nconst insertTable: RunFn = (api) => {\n void (async () => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n const wb = fu(api).getActiveWorkbook();\n if (!range || !sheet || !wb) return;\n await ensurePluginByName('table');\n await api.executeCommand('sheet.command.add-table', {\n unitId: wb.getId(),\n subUnitId: sheet.getSheetId(),\n range: {\n startRow: range.getRow(),\n startColumn: range.getColumn(),\n endRow: range.getRow() + range.getHeight() - 1,\n endColumn: range.getColumn() + range.getWidth() - 1,\n },\n });\n })();\n};\n\nconst autoFitColumns: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n const withAutoWidth = sheet as unknown as {\n setColumnAutoWidth?: (col: number, n: number) => unknown;\n };\n withAutoWidth.setColumnAutoWidth?.(range.getColumn(), range.getWidth());\n};\n\nconst AUTO_FIT_ROW_CAP = 500;\nconst autoFitRows: RunFn = (api) => {\n const range = activeRange(api);\n const sheet = activeSheet(api);\n if (!range || !sheet) return;\n const start = range.getRow();\n const count = Math.min(range.getHeight(), AUTO_FIT_ROW_CAP);\n for (let r = 0; r < count; r++) sheet.autoFitRow(start + r);\n};\n\n/* ── Format ───────────────────────────────────────────────────────────── */\n\n// Patterns copied from home-tab-actions.ts NUMBER_FORMAT_PATTERNS.\nconst NUMBER_FORMAT_PATTERNS = {\n general: '',\n number: '#,##0.00',\n integer: '#,##0',\n currency: '\"$\"#,##0.00',\n accounting: '_(\"$\"* #,##0.00_);_(\"$\"* (#,##0.00);_(\"$\"* \"-\"??_);_(@_)',\n percent: '0.00%',\n date: 'yyyy-mm-dd',\n time: 'hh:mm:ss',\n scientific: '0.00E+00',\n text: '@',\n} as const;\ntype NumberFormatKey = keyof typeof NUMBER_FORMAT_PATTERNS;\n\nconst NUM_FORMAT_ORDER: NumberFormatKey[] = [\n 'general',\n 'number',\n 'integer',\n 'currency',\n 'accounting',\n 'percent',\n 'date',\n 'time',\n 'scientific',\n 'text',\n];\n\nconst NUM_FORMAT_SHORTCUT: Partial<Record<NumberFormatKey, string>> = {\n number: 'Ctrl+Shift+1',\n time: 'Ctrl+Shift+2',\n date: 'Ctrl+Shift+3',\n currency: 'Ctrl+Shift+4',\n percent: 'Ctrl+Shift+5',\n scientific: 'Ctrl+Shift+6',\n};\n\nfunction setNumberFormatByKey(api: CasualSheetsAPI, key: NumberFormatKey) {\n // setNumberFormat lives on the sheets-numfmt facade extension (runtime cast).\n const range = activeRange(api) as unknown as { setNumberFormat?: (p: string) => unknown } | null;\n range?.setNumberFormat?.(NUMBER_FORMAT_PATTERNS[key]);\n}\n\nconst increaseDecimal: RunFn = (api) =>\n void api.executeCommand('sheet.command.numfmt.add.decimal.command');\nconst decreaseDecimal: RunFn = (api) =>\n void api.executeCommand('sheet.command.numfmt.subtract.decimal.command');\nconst clearFormat: RunFn = (api) => void api.executeCommand('sheet.command.clear-selection-format');\n\nfunction applyBorders(api: CasualSheetsAPI, choice: 'all' | 'outside' | 'none') {\n const range = activeRange(api);\n if (!range) return;\n const type =\n choice === 'all' ? BorderType.ALL : choice === 'outside' ? BorderType.OUTSIDE : BorderType.NONE;\n const style = choice === 'none' ? BorderStyleTypes.NONE : BorderStyleTypes.THIN;\n range.setBorder(type, style, '#000000');\n}\n\n/* ── Format → Visibility (command-driven; mirror tab-actions.ts) ───────── */\n\nfunction rowSpan(api: CasualSheetsAPI) {\n const wb = fu(api).getActiveWorkbook();\n const sheet = activeSheet(api);\n const range = activeRange(api);\n if (!wb || !sheet || !range) return null;\n const startRow = range.getRow();\n const endRow = startRow + range.getHeight() - 1;\n const maxCol = (sheet as unknown as { getMaxColumns?: () => number }).getMaxColumns?.() ?? 1;\n return { wb, sheet, startRow, endRow, maxCol };\n}\n\nfunction colSpan(api: CasualSheetsAPI) {\n const wb = fu(api).getActiveWorkbook();\n const sheet = activeSheet(api);\n const range = activeRange(api);\n if (!wb || !sheet || !range) return null;\n const startColumn = range.getColumn();\n const endColumn = startColumn + range.getWidth() - 1;\n const maxRow = (sheet as unknown as { getMaxRows?: () => number }).getMaxRows?.() ?? 1;\n return { wb, sheet, startColumn, endColumn, maxRow };\n}\n\nconst hideSelectedRows: RunFn = (api) => {\n const s = rowSpan(api);\n if (!s) return;\n void api.executeCommand('sheet.command.set-rows-hidden', {\n unitId: s.wb.getId(),\n subUnitId: s.sheet.getSheetId(),\n ranges: [\n {\n startRow: s.startRow,\n endRow: s.endRow,\n startColumn: 0,\n endColumn: Math.max(0, s.maxCol - 1),\n rangeType: 1,\n },\n ],\n });\n};\n\nconst unhideSelectedRows: RunFn = (api) => {\n const s = rowSpan(api);\n if (!s) return;\n void api.executeCommand('sheet.command.set-specific-rows-visible', {\n unitId: s.wb.getId(),\n subUnitId: s.sheet.getSheetId(),\n ranges: [\n {\n startRow: s.startRow,\n endRow: s.endRow,\n startColumn: 0,\n endColumn: Math.max(0, s.maxCol - 1),\n rangeType: 1,\n },\n ],\n });\n};\n\nconst hideSelectedColumns: RunFn = (api) => {\n const s = colSpan(api);\n if (!s) return;\n void api.executeCommand('sheet.command.set-col-hidden', {\n unitId: s.wb.getId(),\n subUnitId: s.sheet.getSheetId(),\n ranges: [\n {\n startRow: 0,\n endRow: Math.max(0, s.maxRow - 1),\n startColumn: s.startColumn,\n endColumn: s.endColumn,\n rangeType: 2,\n },\n ],\n });\n};\n\nconst unhideSelectedColumns: RunFn = (api) => {\n const s = colSpan(api);\n if (!s) return;\n // Univer's \"show specific cols\" id is asymmetric with the row variant.\n void api.executeCommand('sheet.command.set-col-visible-on-cols', {\n unitId: s.wb.getId(),\n subUnitId: s.sheet.getSheetId(),\n ranges: [\n {\n startRow: 0,\n endRow: Math.max(0, s.maxRow - 1),\n startColumn: s.startColumn,\n endColumn: s.endColumn,\n rangeType: 2,\n },\n ],\n });\n};\n\n/* ── View ─────────────────────────────────────────────────────────────── */\n\ntype FreezeCapableSheet = {\n setFrozenRows: (n: number) => unknown;\n setFrozenColumns: (n: number) => unknown;\n};\n\nconst freezeFirstRow: RunFn = (api) => {\n (activeSheet(api) as unknown as FreezeCapableSheet | null)?.setFrozenRows(1);\n};\nconst freezeFirstColumn: RunFn = (api) => {\n (activeSheet(api) as unknown as FreezeCapableSheet | null)?.setFrozenColumns(1);\n};\nconst freezeAtSelection: RunFn = (api) =>\n void api.executeCommand('sheet.command.set-selection-frozen');\nconst unfreezePanes: RunFn = (api) => void api.executeCommand('sheet.command.cancel-frozen');\n\nconst toggleGridlines: RunFn = (api) => {\n const wb = fu(api).getActiveWorkbook();\n const sheet = activeSheet(api);\n if (!wb || !sheet) return;\n // BooleanNumber: 0 = hide, 1 = show. The app reads current state; without a\n // reactive UI store here we hide (matches the app's default click path).\n void api.executeCommand('sheet.command.toggle-gridlines', {\n unitId: wb.getId(),\n subUnitId: sheet.getSheetId(),\n showGridlines: 0,\n });\n};\n\nconst toggleCommentPanel: RunFn = (api) =>\n void api.executeCommand('sheet.operation.toggle-comment-panel');\n\nconst jumpToFirstCell: RunFn = (api) => {\n activeSheet(api)?.getRange(0, 0).activate();\n};\n\nconst switchToPreviousSheet: RunFn = (api) => switchSheetByDelta(api, -1);\nconst switchToNextSheet: RunFn = (api) => switchSheetByDelta(api, +1);\n\nfunction switchSheetByDelta(api: CasualSheetsAPI, delta: -1 | 1) {\n const wb = fu(api).getActiveWorkbook();\n const active = wb?.getActiveSheet();\n if (!wb || !active) return;\n const sheets = wb.getSheets();\n const activeId = active.getSheetId();\n const idx = sheets.findIndex((s) => s.getSheetId() === activeId);\n if (idx < 0) return;\n const nextIdx = idx + delta;\n if (nextIdx < 0 || nextIdx >= sheets.length) return;\n wb.setActiveSheet(sheets[nextIdx]);\n}\n\nconst showFormulas: RunFn = (api) => void api.executeCommand('sheet.command.set-show-formula', {});\n\n/* ── Data ─────────────────────────────────────────────────────────────── */\n\nconst sortAsc: RunFn = (api) => sortRange(api, true);\nconst sortDesc: RunFn = (api) => sortRange(api, false);\n\nfunction sortRange(api: CasualSheetsAPI, ascending: boolean) {\n const range = activeRange(api);\n if (!range) return;\n // sort() comes from the sheets-sort facade extension (runtime cast).\n const withSort = range as unknown as {\n sort?: (spec: { column: number; ascending: boolean }) => unknown;\n };\n withSort.sort?.({ column: range.getColumn(), ascending });\n}\n\nconst toggleFilter: RunFn = (api) => {\n void (async () => {\n await ensurePluginByName('filter');\n const wb = fu(api).getActiveWorkbook();\n const sheet = activeSheet(api);\n const range = activeRange(api);\n if (!wb || !sheet || !range) return;\n const sheetWithFilter = sheet as unknown as { getFilter?: () => unknown };\n if (sheetWithFilter.getFilter?.()) {\n await api.executeCommand('sheet.command.remove-sheet-filter', {\n unitId: wb.getId(),\n subUnitId: sheet.getSheetId(),\n });\n return;\n }\n await api.executeCommand('sheet.command.set-filter-range', {\n unitId: wb.getId(),\n subUnitId: sheet.getSheetId(),\n range: {\n startRow: range.getRow(),\n startColumn: range.getColumn(),\n endRow: range.getRow() + range.getHeight() - 1,\n endColumn: range.getColumn() + range.getWidth() - 1,\n },\n });\n })();\n};\n\nconst splitTextToColumns: RunFn = (api) =>\n void api.executeCommand('sheet.command.split-text-to-columns');\n\nconst forceRecalculate: RunFn = (api) =>\n void api.executeCommand('formula.mutation.set-formula-calculation-start', {\n forceCalculation: true,\n });\n\n/* ───────────────────────────── menu structure ─────────────────────────── */\n\n// Mirrors the app's menu order. Dialog items resolve `dialog` against\n// `onDialogRequest`; non-dialog items dispatch via the inline helpers above.\nconst MENUS: MenuDef[] = [\n {\n id: 'file',\n label: 'File',\n feature: 'file',\n items: [\n { kind: 'item', id: 'properties', label: 'Properties…', icon: 'info', dialog: 'properties' },\n {\n kind: 'item',\n id: 'about',\n label: 'About casual sheets',\n icon: 'help_outline',\n dialog: 'about',\n feature: 'branding',\n },\n ],\n },\n {\n id: 'edit',\n label: 'Edit',\n items: [\n { kind: 'item', id: 'undo', label: 'Undo', icon: 'undo', shortcut: 'Ctrl+Z', run: undo },\n { kind: 'item', id: 'redo', label: 'Redo', icon: 'redo', shortcut: 'Ctrl+Y', run: redo },\n { kind: 'separator', id: 'sep-clip' },\n { kind: 'item', id: 'cut', label: 'Cut', icon: 'content_cut', shortcut: 'Ctrl+X', run: cut },\n {\n kind: 'item',\n id: 'copy',\n label: 'Copy',\n icon: 'content_copy',\n shortcut: 'Ctrl+C',\n run: copy,\n },\n {\n kind: 'item',\n id: 'paste',\n label: 'Paste',\n icon: 'content_paste',\n shortcut: 'Ctrl+V',\n run: paste,\n },\n {\n kind: 'item',\n id: 'paste-format',\n label: 'Paste formatting only',\n icon: 'content_paste',\n shortcut: 'Ctrl+Shift+V',\n run: pasteFormattingOnly,\n },\n {\n kind: 'item',\n id: 'paste-special',\n label: 'Paste Special…',\n icon: 'content_paste_go',\n shortcut: 'Ctrl+Alt+V',\n dialog: 'paste-special',\n },\n { kind: 'separator', id: 'sep-find' },\n {\n kind: 'item',\n id: 'find-replace',\n label: 'Find & Replace…',\n icon: 'search',\n shortcut: 'Ctrl+F',\n dialog: 'find-replace',\n },\n { kind: 'separator', id: 'sep-cells' },\n {\n kind: 'item',\n id: 'edit-insert-cells',\n label: 'Insert cells…',\n icon: 'add_box',\n shortcut: 'Ctrl++',\n dialog: 'insert-cells',\n },\n {\n kind: 'item',\n id: 'edit-delete-cells',\n label: 'Delete cells…',\n icon: 'indeterminate_check_box',\n shortcut: 'Ctrl+-',\n dialog: 'delete-cells',\n },\n ],\n },\n {\n id: 'view',\n label: 'View',\n items: [\n {\n kind: 'item',\n id: 'show-formulas',\n label: 'Show formulas',\n icon: 'description',\n shortcut: 'Ctrl+`',\n run: showFormulas,\n },\n {\n kind: 'item',\n id: 'toggle-gridlines',\n label: 'Toggle gridlines',\n icon: 'grid_on',\n run: toggleGridlines,\n },\n { kind: 'separator', id: 'sep-freeze' },\n {\n kind: 'item',\n id: 'freeze-row',\n label: 'Freeze top row',\n icon: 'border_horizontal',\n run: freezeFirstRow,\n },\n {\n kind: 'item',\n id: 'freeze-col',\n label: 'Freeze first column',\n icon: 'border_vertical',\n run: freezeFirstColumn,\n },\n {\n kind: 'item',\n id: 'freeze-selection',\n label: 'Freeze panes (at selection)',\n icon: 'grid_4x4',\n run: freezeAtSelection,\n },\n { kind: 'item', id: 'unfreeze', label: 'Unfreeze', icon: 'grid_off', run: unfreezePanes },\n { kind: 'separator', id: 'sep-nav' },\n {\n kind: 'item',\n id: 'jump-home',\n label: 'Jump to A1',\n icon: 'home',\n shortcut: 'Ctrl+Home',\n run: jumpToFirstCell,\n },\n {\n kind: 'item',\n id: 'prev-sheet',\n label: 'Previous sheet',\n icon: 'navigate_before',\n shortcut: 'Ctrl+PageUp',\n run: switchToPreviousSheet,\n },\n {\n kind: 'item',\n id: 'next-sheet',\n label: 'Next sheet',\n icon: 'navigate_next',\n shortcut: 'Ctrl+PageDown',\n run: switchToNextSheet,\n },\n { kind: 'separator', id: 'sep-panels' },\n {\n kind: 'item',\n id: 'comments-panel',\n label: 'Comments panel',\n icon: 'forum',\n run: toggleCommentPanel,\n },\n ],\n },\n {\n id: 'insert',\n label: 'Insert',\n items: [\n {\n kind: 'item',\n id: 'new-sheet',\n label: 'New sheet',\n icon: 'add_box',\n shortcut: 'Shift+F11',\n run: insertNewSheet,\n },\n {\n kind: 'item',\n id: 'insert-table',\n label: 'Table',\n icon: 'table_rows',\n shortcut: 'Ctrl+L',\n run: insertTable,\n feature: 'tables',\n },\n {\n kind: 'item',\n id: 'insert-chart',\n label: 'Chart…',\n icon: 'bar_chart',\n dialog: 'insert-chart',\n feature: 'charts',\n },\n {\n kind: 'item',\n id: 'insert-sparkline',\n label: 'Sparkline…',\n icon: 'show_chart',\n dialog: 'insert-sparkline',\n feature: 'sparklines',\n },\n {\n kind: 'item',\n id: 'insert-pivot',\n label: 'PivotTable…',\n icon: 'pivot_table_chart',\n dialog: 'insert-pivot',\n feature: 'pivots',\n },\n { kind: 'separator', id: 'sep-objects' },\n { kind: 'item', id: 'insert-image', label: 'Image…', icon: 'image', run: insertImage },\n {\n kind: 'item',\n id: 'insert-function',\n label: 'Function…',\n icon: 'functions',\n shortcut: 'Shift+F3',\n dialog: 'insert-function',\n },\n {\n kind: 'item',\n id: 'insert-link',\n label: 'Hyperlink…',\n icon: 'link',\n shortcut: 'Ctrl+K',\n run: insertHyperlink,\n },\n {\n kind: 'item',\n id: 'insert-comment',\n label: 'Comment',\n icon: 'comment',\n shortcut: 'Shift+F2',\n run: insertComment,\n },\n { kind: 'separator', id: 'sep-rowcol' },\n {\n kind: 'submenu',\n id: 'insert-rowcol',\n label: 'Rows & columns',\n icon: 'grid_on',\n items: [\n {\n kind: 'item',\n id: 'insert-row-above',\n label: 'Row above',\n icon: 'vertical_align_top',\n run: insertRowAbove,\n },\n {\n kind: 'item',\n id: 'insert-row-below',\n label: 'Row below',\n icon: 'vertical_align_bottom',\n run: insertRowBelow,\n },\n {\n kind: 'item',\n id: 'insert-col-left',\n label: 'Column left',\n icon: 'keyboard_tab_rtl',\n run: insertColumnLeft,\n },\n {\n kind: 'item',\n id: 'insert-col-right',\n label: 'Column right',\n icon: 'keyboard_tab',\n run: insertColumnRight,\n },\n ],\n },\n { kind: 'separator', id: 'sep-autofit' },\n {\n kind: 'item',\n id: 'autofit-col',\n label: 'Auto-fit column width',\n icon: 'settings_ethernet',\n run: autoFitColumns,\n },\n {\n kind: 'item',\n id: 'autofit-row',\n label: 'Auto-fit row height',\n icon: 'height',\n run: autoFitRows,\n },\n { kind: 'separator', id: 'sep-date' },\n {\n kind: 'item',\n id: 'insert-today',\n label: \"Today's date\",\n icon: 'today',\n shortcut: 'Ctrl+;',\n run: insertTodayDate,\n },\n {\n kind: 'item',\n id: 'insert-time',\n label: 'Current time',\n icon: 'schedule',\n shortcut: 'Ctrl+Shift+:',\n run: insertCurrentTime,\n },\n ],\n },\n {\n id: 'format',\n label: 'Format',\n items: [\n {\n kind: 'item',\n id: 'format-cells',\n label: 'Format cells…',\n icon: 'format_shapes',\n shortcut: 'Ctrl+1',\n dialog: 'format-cells',\n },\n { kind: 'separator', id: 'sep-format-cells' },\n {\n kind: 'item',\n id: 'bold',\n label: 'Bold',\n icon: 'format_bold',\n shortcut: 'Ctrl+B',\n run: (api) => void api.executeCommand('sheet.command.set-range-bold'),\n },\n {\n kind: 'item',\n id: 'italic',\n label: 'Italic',\n icon: 'format_italic',\n shortcut: 'Ctrl+I',\n run: (api) => void api.executeCommand('sheet.command.set-range-italic'),\n },\n {\n kind: 'item',\n id: 'underline',\n label: 'Underline',\n icon: 'format_underlined',\n shortcut: 'Ctrl+U',\n run: (api) => void api.executeCommand('sheet.command.set-range-underline'),\n },\n {\n kind: 'item',\n id: 'wrap-text',\n label: 'Wrap text',\n icon: 'wrap_text',\n run: (api) => void api.executeCommand('sheet.command.set-text-wrap', { value: 3 }),\n },\n { kind: 'separator', id: 'sep-numfmt' },\n {\n kind: 'submenu',\n id: 'num-format',\n label: 'Number format',\n icon: 'looks_one',\n items: NUM_FORMAT_ORDER.map<MenuItemDef>((k) => ({\n kind: 'item',\n id: `num-${k}`,\n label: k[0]!.toUpperCase() + k.slice(1),\n icon: 'looks_one',\n shortcut: NUM_FORMAT_SHORTCUT[k],\n run: (api) => setNumberFormatByKey(api, k),\n })),\n },\n {\n kind: 'item',\n id: 'decimal-up',\n label: 'Increase decimals',\n icon: 'decimal_increase',\n run: increaseDecimal,\n },\n {\n kind: 'item',\n id: 'decimal-down',\n label: 'Decrease decimals',\n icon: 'decimal_decrease',\n run: decreaseDecimal,\n },\n { kind: 'separator', id: 'sep-borders' },\n {\n kind: 'submenu',\n id: 'borders',\n label: 'Borders',\n icon: 'border_all',\n items: [\n {\n kind: 'item',\n id: 'border-all',\n label: 'All borders',\n icon: 'border_all',\n run: (api) => applyBorders(api, 'all'),\n },\n {\n kind: 'item',\n id: 'border-outside',\n label: 'Outside borders',\n icon: 'border_outer',\n run: (api) => applyBorders(api, 'outside'),\n },\n {\n kind: 'item',\n id: 'border-none',\n label: 'No border',\n icon: 'border_clear',\n run: (api) => applyBorders(api, 'none'),\n },\n ],\n },\n { kind: 'separator', id: 'sep-cond' },\n {\n kind: 'item',\n id: 'conditional-formatting',\n label: 'Conditional formatting…',\n icon: 'palette',\n dialog: 'conditional-formatting',\n feature: 'conditionalFormatting',\n },\n { kind: 'separator', id: 'sep-visibility' },\n {\n kind: 'submenu',\n id: 'visibility',\n label: 'Visibility',\n icon: 'visibility',\n items: [\n {\n kind: 'item',\n id: 'hide-row',\n label: 'Hide row',\n icon: 'visibility_off',\n shortcut: 'Ctrl+9',\n run: hideSelectedRows,\n },\n {\n kind: 'item',\n id: 'unhide-row',\n label: 'Unhide row',\n icon: 'visibility',\n shortcut: 'Ctrl+Shift+9',\n run: unhideSelectedRows,\n },\n {\n kind: 'item',\n id: 'hide-col',\n label: 'Hide column',\n icon: 'visibility_off',\n shortcut: 'Ctrl+0',\n run: hideSelectedColumns,\n },\n {\n kind: 'item',\n id: 'unhide-col',\n label: 'Unhide column',\n icon: 'visibility',\n shortcut: 'Ctrl+Shift+0',\n run: unhideSelectedColumns,\n },\n ],\n },\n { kind: 'separator', id: 'sep-clear' },\n {\n kind: 'item',\n id: 'clear-format',\n label: 'Clear formatting',\n icon: 'format_clear',\n run: clearFormat,\n },\n { kind: 'separator', id: 'sep-delete' },\n {\n kind: 'item',\n id: 'delete-row',\n label: 'Delete row',\n icon: 'delete_sweep',\n run: deleteSelectedRow,\n },\n {\n kind: 'item',\n id: 'delete-col',\n label: 'Delete column',\n icon: 'folder_delete',\n run: deleteSelectedColumn,\n },\n ],\n },\n {\n id: 'data',\n label: 'Data',\n items: [\n {\n kind: 'item',\n id: 'sort-asc',\n label: 'Sort ascending',\n icon: 'arrow_upward',\n run: sortAsc,\n },\n {\n kind: 'item',\n id: 'sort-desc',\n label: 'Sort descending',\n icon: 'arrow_downward',\n run: sortDesc,\n },\n {\n kind: 'item',\n id: 'sort-custom',\n label: 'Sort range…',\n icon: 'sort',\n dialog: 'custom-sort',\n },\n {\n kind: 'item',\n id: 'toggle-filter',\n label: 'Toggle filter',\n icon: 'filter_alt',\n shortcut: 'Ctrl+Shift+L',\n run: toggleFilter,\n feature: 'filter',\n },\n { kind: 'separator', id: 'sep-tools' },\n {\n kind: 'item',\n id: 'data-validation',\n label: 'Data validation…',\n icon: 'rule',\n dialog: 'data-validation',\n feature: 'dataValidation',\n },\n {\n kind: 'item',\n id: 'name-manager',\n label: 'Name Manager…',\n icon: 'bookmark_add',\n shortcut: 'Ctrl+F3',\n dialog: 'name-manager',\n },\n {\n kind: 'item',\n id: 'goal-seek',\n label: 'Goal Seek…',\n icon: 'analytics',\n dialog: 'goal-seek',\n },\n { kind: 'separator', id: 'sep-clean' },\n {\n kind: 'item',\n id: 'text-to-columns',\n label: 'Text to Columns',\n icon: 'splitscreen',\n run: splitTextToColumns,\n },\n {\n kind: 'item',\n id: 'recalculate',\n label: 'Recalculate',\n icon: 'autorenew',\n shortcut: 'F9',\n run: forceRecalculate,\n },\n ],\n },\n {\n id: 'help',\n label: 'Help',\n // Whole-menu gate: an embedded host passes `features={{ help: false }}` to\n // drop the Help menu entirely (no editor-branded surface). Individual\n // branding links below also carry `feature: 'branding'` so a host that\n // keeps Help (for keyboard shortcuts) can still hide the About / GitHub\n // links with `features={{ branding: false }}`.\n feature: 'help',\n items: [\n {\n kind: 'item',\n id: 'keyboard-shortcuts',\n label: 'Keyboard shortcuts',\n icon: 'info',\n shortcut: 'Ctrl+/',\n dialog: 'keyboard-shortcuts',\n },\n { kind: 'separator', id: 'sep-help', feature: 'branding' },\n {\n kind: 'item',\n id: 'about',\n label: 'About casual sheets',\n icon: 'info',\n dialog: 'about',\n feature: 'branding',\n },\n {\n kind: 'item',\n id: 'github',\n label: 'View on GitHub',\n icon: 'open_in_new',\n run: () => openExternal('https://github.com/CasualOffice/sheets'),\n feature: 'branding',\n },\n ],\n },\n];\n\n/* ───────────────────────────── styling ────────────────────────────────── */\n\nconst BAR_STYLE: CSSProperties = {\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n gap: 2,\n padding: '2px 6px',\n borderBottom: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-bg, #eef1f5)',\n flex: '0 0 auto',\n userSelect: 'none',\n font: 'inherit',\n fontSize: 13,\n};\n\nconst MENU_BTN_STYLE: CSSProperties = {\n height: 26,\n display: 'inline-flex',\n alignItems: 'center',\n padding: '0 10px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n};\n\nconst DROPDOWN_STYLE: CSSProperties = {\n position: 'absolute',\n top: '100%',\n minWidth: 220,\n marginTop: 2,\n padding: 4,\n display: 'flex',\n flexDirection: 'column',\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n borderRadius: 8,\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.16)',\n zIndex: 1000,\n};\n\nconst ITEM_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: 10,\n width: '100%',\n height: 30,\n padding: '0 10px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n cursor: 'pointer',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n textAlign: 'left',\n};\n\nconst SEPARATOR_STYLE: CSSProperties = {\n height: 1,\n margin: '4px 6px',\n background: 'var(--cs-chrome-border, #e6e9ee)',\n};\n\nconst SHORTCUT_STYLE: CSSProperties = {\n marginLeft: 'auto',\n paddingLeft: 16,\n fontSize: 11,\n color: 'var(--cs-chrome-muted, #6b7280)',\n};\n\nconst SUBMENU_PANEL_STYLE: CSSProperties = {\n position: 'absolute',\n top: -4,\n left: '100%',\n minWidth: 200,\n marginLeft: 2,\n padding: 4,\n display: 'flex',\n flexDirection: 'column',\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n borderRadius: 8,\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.16)',\n zIndex: 1001,\n};\n\n/* ───────────────────────────── component ──────────────────────────────── */\n\nexport interface MenuBarProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n /**\n * Per-feature toggles. A control / menu whose `feature` key is `false` is not\n * rendered. Unknown / omitted keys default to enabled.\n */\n features?: Record<string, boolean>;\n /**\n * Host chrome extensions — custom menu items appended to their target menu.\n * Dialogs/toolbar/panels are handled elsewhere; only `extensions.menu` is read\n * here.\n */\n extensions?: ChromeExtensions;\n}\n\nexport function MenuBar({ api, features = {}, extensions }: MenuBarProps) {\n const dialogs = useDialogs();\n const [open, setOpen] = useState<MenuId | null>(null);\n const [openSubmenu, setOpenSubmenu] = useState<string | null>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n ensureChromeFonts();\n }, []);\n\n // Close on Escape + on a pointerdown outside the menu bar.\n useEffect(() => {\n if (open === null) return;\n const onKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n setOpen(null);\n setOpenSubmenu(null);\n }\n };\n const onDown = (e: PointerEvent) => {\n if (!rootRef.current?.contains(e.target as Node)) {\n setOpen(null);\n setOpenSubmenu(null);\n }\n };\n document.addEventListener('keydown', onKey);\n document.addEventListener('pointerdown', onDown, true);\n return () => {\n document.removeEventListener('keydown', onKey);\n document.removeEventListener('pointerdown', onDown, true);\n };\n }, [open]);\n\n const close = () => {\n setOpen(null);\n setOpenSubmenu(null);\n };\n\n const runItem = (item: Extract<MenuItemDef, { kind: 'item' }>) => {\n close();\n if (!api) return;\n if (item.dialog) {\n // Range-seeded dialogs get the current selection in A1 as context.\n const seeded =\n item.dialog === 'insert-chart' ||\n item.dialog === 'insert-pivot' ||\n item.dialog === 'insert-sparkline' ||\n item.dialog === 'insert-cells' ||\n item.dialog === 'delete-cells';\n // openDialog opens the SDK built-in by default; a host override / host-owned\n // kind / onDialogRequest wins per the resolution rules in DialogProvider.\n dialogs.openDialog(item.dialog, seeded ? selectionA1(api) : undefined);\n return;\n }\n item.run?.(api);\n };\n\n // Compute the visible menus once per render (feature + dialog-open gating +\n // host menu extensions). Extracted to `computeVisibleMenus` so the gating\n // contract is unit-testable without a DOM.\n const visibleMenus = computeVisibleMenus(MENUS, features, dialogs.canOpen, extensions?.menu);\n\n const renderItems = (items: MenuItemDef[]): ReactNode =>\n items.map((item) => {\n if (item.kind === 'separator') {\n return <div key={item.id} style={SEPARATOR_STYLE} role=\"separator\" aria-hidden />;\n }\n if (item.kind === 'submenu') {\n const isSubOpen = openSubmenu === item.id;\n return (\n <div\n key={item.id}\n style={{ position: 'relative' }}\n onMouseEnter={() => setOpenSubmenu(item.id)}\n onMouseLeave={() => setOpenSubmenu((cur) => (cur === item.id ? null : cur))}\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n data-testid={`cs-menuitem-${item.id}`}\n aria-haspopup=\"menu\"\n aria-expanded={isSubOpen}\n disabled={!api}\n style={{ ...ITEM_STYLE, opacity: api ? 1 : 0.5 }}\n onMouseDown={(e) => e.preventDefault()}\n >\n {item.icon ? (\n <Icon name={item.icon} size={18} />\n ) : (\n <span style={{ width: 18 }} aria-hidden />\n )}\n <span>{item.label}</span>\n <Icon name=\"chevron_right\" size={18} style={{ marginLeft: 'auto' }} />\n </button>\n {isSubOpen && (\n <div style={SUBMENU_PANEL_STYLE} role=\"menu\" aria-label={item.label}>\n {renderItems(item.items)}\n </div>\n )}\n </div>\n );\n }\n return (\n <button\n key={item.id}\n type=\"button\"\n role=\"menuitem\"\n data-testid={`cs-menuitem-${item.id}`}\n disabled={!api}\n style={{ ...ITEM_STYLE, opacity: api ? 1 : 0.5 }}\n onMouseDown={(e) => {\n e.preventDefault();\n runItem(item);\n }}\n onMouseEnter={(e) => {\n setOpenSubmenu(null);\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = 'transparent';\n }}\n >\n {item.icon ? (\n <Icon name={item.icon} size={18} />\n ) : (\n <span style={{ width: 18 }} aria-hidden />\n )}\n <span>{item.label}</span>\n {item.shortcut && <span style={SHORTCUT_STYLE}>{fmtShortcut(item.shortcut)}</span>}\n </button>\n );\n });\n\n return (\n <div\n ref={rootRef}\n style={BAR_STYLE}\n data-testid=\"cs-menubar\"\n role=\"menubar\"\n aria-label=\"Menu bar\"\n >\n {visibleMenus.map((menu) => {\n const isOpen = open === menu.id;\n return (\n <div key={menu.id} style={{ position: 'relative' }}>\n <button\n type=\"button\"\n data-menu={menu.id}\n data-testid={`cs-menu-${menu.id}`}\n aria-haspopup=\"menu\"\n aria-expanded={isOpen}\n style={{\n ...MENU_BTN_STYLE,\n background: isOpen ? 'var(--cs-chrome-active, #e6f3f7)' : 'transparent',\n color: isOpen ? 'var(--cs-chrome-active-fg, #0e7490)' : MENU_BTN_STYLE.color,\n }}\n // mousedown (not click) so the grid selection isn't lost first;\n // toggle the menu open/closed.\n onMouseDown={(e) => {\n e.preventDefault();\n setOpenSubmenu(null);\n setOpen((cur) => (cur === menu.id ? null : menu.id));\n }}\n onMouseEnter={(e) => {\n // Hover-to-switch once a menu is already open (Office behaviour).\n if (open !== null && open !== menu.id) {\n setOpen(menu.id);\n setOpenSubmenu(null);\n } else if (!isOpen)\n e.currentTarget.style.background = 'var(--cs-chrome-hover, rgba(0,0,0,0.06))';\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = isOpen\n ? 'var(--cs-chrome-active, #e6f3f7)'\n : 'transparent';\n }}\n >\n {menu.label}\n </button>\n {isOpen && (\n <div style={DROPDOWN_STYLE} role=\"menu\" aria-label={menu.label}>\n {renderItems(menu.items)}\n </div>\n )}\n </div>\n );\n })}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * Open an external link in the user's default browser.\n *\n * Inside the Casual Office desktop shell, `window.open()` silently no-ops in the\n * Tauri webview. Route through the shell's scheme-guarded `open_external`\n * command when the Tauri bridge is present; fall back to `window.open` on web.\n */\nexport function openExternal(url: string): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const invoke = (window as any)?.__TAURI__?.core?.invoke as\n | ((cmd: string, args?: unknown) => Promise<unknown>)\n | undefined;\n if (invoke) {\n void invoke('open_external', { url }).catch(() => {\n window.open(url, '_blank', 'noopener,noreferrer');\n });\n return;\n }\n window.open(url, '_blank', 'noopener,noreferrer');\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Univer, IWorkbookData } from '@univerjs/core';\n\n/**\n * Lazy plugin loading — pipeline Stage 4. The cheap plugins (render,\n * formula, sheets, sheets-ui, numfmt, docs) stay eager because every\n * workbook needs them. The heavy / feature-specific plugins (CF, DV,\n * hyperlink, table, note, thread-comment, drawing, sort, filter,\n * find-replace) load on demand:\n *\n * 1. Eagerly when a snapshot is about to mount and we detect the\n * plugin's resource key on it (e.g. `SHEET_CONDITIONAL_FORMATTING_PLUGIN`\n * in `data.resources`). This is the safety net: missing this would\n * silently drop plugin data on file open.\n * 2. Lazily when the user reaches for the feature — opens the Data\n * tab (sort/filter), hits Ctrl+F (find-replace), uses the Insert\n * tab (drawing), etc. The shell hooks `ensurePlugin(...)` into\n * these triggers and awaits before the action runs.\n *\n * Each loader returns the plugins-to-register in the correct order\n * (base before UI, same as `plugins.ts`). Registration order matters\n * in Univer; the loaders bundle a small group together to keep that\n * locality explicit.\n */\n\nexport type LazyPluginGroup =\n | 'cf'\n | 'dv'\n | 'hyperlink'\n | 'note'\n | 'table'\n | 'threadComment'\n | 'drawing'\n | 'sort'\n | 'filter'\n | 'findReplace';\n\ntype Loader = () => Promise<Array<[unknown, unknown?]>>;\n\nconst LOADERS: Record<LazyPluginGroup, Loader> = {\n cf: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-conditional-formatting'),\n import('@univerjs/sheets-conditional-formatting-ui'),\n ]);\n return [\n [base.UniverSheetsConditionalFormattingPlugin],\n [ui.UniverSheetsConditionalFormattingUIPlugin],\n ];\n },\n dv: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-data-validation'),\n import('@univerjs/sheets-data-validation-ui'),\n ]);\n return [[base.UniverSheetsDataValidationPlugin], [ui.UniverSheetsDataValidationUIPlugin]];\n },\n hyperlink: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-hyper-link'),\n import('@univerjs/sheets-hyper-link-ui'),\n ]);\n return [[base.UniverSheetsHyperLinkPlugin], [ui.UniverSheetsHyperLinkUIPlugin]];\n },\n note: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-note'),\n import('@univerjs/sheets-note-ui'),\n ]);\n return [[base.UniverSheetsNotePlugin], [ui.UniverSheetsNoteUIPlugin]];\n },\n table: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-table'),\n import('@univerjs/sheets-table-ui'),\n ]);\n return [[base.UniverSheetsTablePlugin], [ui.UniverSheetsTableUIPlugin]];\n },\n threadComment: async () => {\n const [tc, tcUi, sheetsTc, sheetsTcUi, mentionUi] = await Promise.all([\n import('@univerjs/thread-comment'),\n import('@univerjs/thread-comment-ui'),\n import('@univerjs/sheets-thread-comment'),\n import('@univerjs/sheets-thread-comment-ui'),\n // @-mention autocomplete for the comment editor. Lists candidates via the\n // core IMentionIOService, which CasualSheets overrides with the\n // host-pluggable CasualMentionIOService (see mention-source.ts). Riding\n // the comment group means it loads exactly when comments do.\n import('@univerjs/docs-mention-ui'),\n // Side-effect imports: install FWorksheet.getComments / FRange.\n // getComments / addCommentAsync on the facade prototype. Without\n // these the CommentsPanel's `getActiveSheet().getComments()` and\n // any facade-driven comment flow (e2e, future shell glue) see an\n // undefined method even though the plugin is registered — mirrors\n // the `drawing` group's facade imports above.\n import('@univerjs/sheets-thread-comment/facade'),\n ]);\n return [\n [tc.UniverThreadCommentPlugin],\n [tcUi.UniverThreadCommentUIPlugin],\n [sheetsTc.UniverSheetsThreadCommentPlugin],\n [sheetsTcUi.UniverSheetsThreadCommentUIPlugin],\n [mentionUi.UniverDocsMentionUIPlugin],\n ];\n },\n drawing: async () => {\n const [d, dUi, sd, sdUi] = await Promise.all([\n import('@univerjs/drawing'),\n import('@univerjs/drawing-ui'),\n import('@univerjs/sheets-drawing'),\n import('@univerjs/sheets-drawing-ui'),\n // Side-effect imports: install FWorksheet.insertImage / getImages /\n // updateImages on the facade prototype. Without these, code that\n // reaches in via the FUniver facade (e2e specs, future shell glue)\n // sees an undefined method even though the plugin is registered.\n import('@univerjs/sheets-drawing/facade'),\n import('@univerjs/sheets-drawing-ui/facade'),\n ]);\n return [\n [d.UniverDrawingPlugin],\n [dUi.UniverDrawingUIPlugin],\n [sd.UniverSheetsDrawingPlugin],\n [sdUi.UniverSheetsDrawingUIPlugin],\n ];\n },\n sort: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-sort'),\n import('@univerjs/sheets-sort-ui'),\n ]);\n return [[base.UniverSheetsSortPlugin], [ui.UniverSheetsSortUIPlugin]];\n },\n filter: async () => {\n const [base, ui] = await Promise.all([\n import('@univerjs/sheets-filter'),\n import('@univerjs/sheets-filter-ui'),\n ]);\n return [[base.UniverSheetsFilterPlugin], [ui.UniverSheetsFilterUIPlugin]];\n },\n findReplace: async () => {\n const [base, sheets] = await Promise.all([\n import('@univerjs/find-replace'),\n import('@univerjs/sheets-find-replace'),\n ]);\n return [[base.UniverFindReplacePlugin], [sheets.UniverSheetsFindReplacePlugin]];\n },\n};\n\n/**\n * Map from a Univer `data.resources[].name` to the lazy group that owns\n * it. Used by `eagerLoadForSnapshot` to pre-register plugins whose\n * state already lives on the workbook so file-open never silently\n * drops a CF rule / table / drawing / etc.\n */\nconst RESOURCE_NAME_TO_GROUP: Record<string, LazyPluginGroup> = {\n SHEET_CONDITIONAL_FORMATTING_PLUGIN: 'cf',\n SHEET_DATA_VALIDATION_PLUGIN: 'dv',\n SHEET_HYPER_LINK_PLUGIN: 'hyperlink',\n SHEET_NOTE_PLUGIN: 'note',\n SHEET_TABLE_PLUGIN: 'table',\n SHEET_THREAD_COMMENT_BASE_PLUGIN: 'threadComment',\n SHEET_DRAWING_PLUGIN: 'drawing',\n SHEET_SORT_PLUGIN: 'sort',\n SHEET_FILTER_PLUGIN: 'filter',\n};\n\nconst loaded = new Set<LazyPluginGroup>();\nconst inflight = new Map<LazyPluginGroup, Promise<void>>();\n\n/**\n * Module-level reference to the live Univer instance, set by\n * `UniverSheet.tsx` immediately after `new Univer()`. Lets shell code\n * call `ensurePluginByName(group)` without plumbing the Univer\n * instance through React context (the FUniver facade doesn't expose\n * its host). Cleared on dispose so callers fail loudly if they hit\n * the lazy path after teardown.\n */\nlet currentUniver: Univer | null = null;\n\nexport function setUniverForLazyLoad(univer: Univer | null): void {\n currentUniver = univer;\n}\n\n/**\n * Idempotent: subsequent calls for the same group resolve immediately\n * if the plugin is already loaded; concurrent calls share the same\n * in-flight promise so we never double-register.\n */\nexport function ensurePlugin(univer: Univer, group: LazyPluginGroup): Promise<void> {\n if (loaded.has(group)) return Promise.resolve();\n const existing = inflight.get(group);\n if (existing) return existing;\n const loader = LOADERS[group];\n if (!loader) return Promise.resolve();\n const p = loader().then((plugins) => {\n for (const [PluginCtor, config] of plugins) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n univer.registerPlugin(PluginCtor as any, config);\n }\n loaded.add(group);\n inflight.delete(group);\n });\n inflight.set(group, p);\n return p;\n}\n\n/**\n * Shell-friendly variant of `ensurePlugin` that pulls the Univer\n * instance from the module-level holder set by `UniverSheet.tsx`. Use\n * this anywhere we only have the FUniver facade (toolbar callbacks,\n * panel handlers). Returns a resolved promise if the holder is empty —\n * the worst case is a no-op, never a throw.\n */\nexport function ensurePluginByName(group: LazyPluginGroup): Promise<void> {\n if (loaded.has(group)) return Promise.resolve();\n if (!currentUniver) return Promise.resolve();\n return ensurePlugin(currentUniver, group);\n}\n\n/**\n * Walk a snapshot for plugin-owned resources + side-channel hyperlinks\n * and eagerly load every group that's referenced. Returns a promise\n * the caller MUST await before `createUnit` — Univer's resource manager\n * silently discards keys for plugins that aren't yet registered.\n */\nexport async function eagerLoadForSnapshot(univer: Univer, snapshot: IWorkbookData): Promise<void> {\n const groups = new Set<LazyPluginGroup>();\n const resources = snapshot.resources ?? [];\n for (const r of resources) {\n const g = RESOURCE_NAME_TO_GROUP[r.name];\n if (g) groups.add(g);\n }\n // Hyperlinks live inline in cell.p (Stage 5) — the hyperlink plugin\n // still owns click handling / context-menu actions, so eager-load\n // when any cell has a HYPERLINK customRange.\n if (snapshotHasHyperlinks(snapshot)) groups.add('hyperlink');\n await Promise.all(Array.from(groups).map((g) => ensurePlugin(univer, g)));\n}\n\n/**\n * Idle-load every remaining lazy group AFTER Univer is mounted. The\n * bundle split (each group ships as its own chunk) is the persistent\n * boot-time win — the initial paint doesn't pay for them. This\n * idle-load just ensures they're all eventually registered so a user\n * clicking \"Insert > Table\" doesn't hit a no-op.\n *\n * Loads in parallel via `requestIdleCallback` so they don't compete\n * with the first paint, falling back to `setTimeout(0)` in browsers\n * without rIC (Safari).\n */\nexport function idleLoadAll(univer: Univer): void {\n const groups = Object.keys(LOADERS) as LazyPluginGroup[];\n schedule(() => {\n for (const g of groups) {\n void ensurePlugin(univer, g);\n }\n });\n}\n\nfunction schedule(fn: () => void): void {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const ric = (globalThis as any).requestIdleCallback as\n | ((cb: () => void, opts?: { timeout: number }) => number)\n | undefined;\n if (ric) ric(fn, { timeout: 500 });\n else setTimeout(fn, 0);\n}\n\nfunction snapshotHasHyperlinks(snapshot: IWorkbookData): boolean {\n const sheetOrder = snapshot.sheetOrder ?? [];\n for (const sid of sheetOrder) {\n const sheet = snapshot.sheets?.[sid];\n if (!sheet?.cellData) continue;\n const cellData = sheet.cellData as Record<\n string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Record<string, { p?: any }>\n >;\n for (const r of Object.keys(cellData)) {\n const row = cellData[r];\n for (const c of Object.keys(row)) {\n const ranges = row[c]?.p?.body?.customRanges ?? [];\n if (ranges.some((cr: { rangeType?: number }) => cr.rangeType === 0)) return true;\n }\n }\n }\n return false;\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * MenuBar data model + pure gating engine.\n *\n * Split out of `MenuBar.tsx` so the feature-gating contract is unit-testable\n * under `node --test`: `MenuBar.tsx` statically imports `@univerjs/core` values\n * (which the vendored typeless-package ESM can't expose as named exports to\n * node), so it can't be imported in a DOM-less test. This module has only\n * type-only imports (all erased at build), so `computeVisibleMenus` — the code\n * that decides which menus/items a host actually sees — can be exercised\n * directly.\n *\n * Feature gates: pass `features` to hide a control or whole menu group when its\n * feature is disabled. Defaults to all-enabled. A control whose feature is\n * `false` does not render. An entire top-level menu whose own `feature` is\n * `false`, or that ends up with no runnable items, is dropped.\n */\n\nimport type { DialogKind } from './dialog-context';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport type { MenuExtension } from './extensions';\n\nexport type MenuId = 'file' | 'edit' | 'view' | 'insert' | 'format' | 'data' | 'help';\n\n/**\n * Dialog kinds the host can choose to render via `onDialogRequest`. These are\n * the actions the SDK chrome can't fulfil on its own (no built-in modal). The\n * string is passed straight to the host hook; the `context` (when present)\n * carries the pre-resolved A1 selection so the host doesn't have to re-read it.\n */\nexport type MenuDialogKind = DialogKind;\n\nexport type RunFn = (api: CasualSheetsAPI) => void;\n\nexport type MenuItemDef =\n | {\n kind: 'item';\n id: string;\n label: string;\n icon?: string;\n shortcut?: string;\n /** Dispatch a command / facade call directly. */\n run?: RunFn;\n /** Route through the host's `onDialogRequest`. Omitted if no host hook. */\n dialog?: MenuDialogKind;\n /** Feature gate — item hidden when `features[feature] === false`. */\n feature?: string;\n }\n | { kind: 'separator'; id: string; feature?: string }\n | {\n kind: 'submenu';\n id: string;\n label: string;\n icon?: string;\n items: MenuItemDef[];\n feature?: string;\n };\n\nexport interface MenuDef {\n id: MenuId;\n label: string;\n /** Feature gate for the whole menu. */\n feature?: string;\n items: MenuItemDef[];\n}\n\n/* ───────────────────────────── filtering ──────────────────────────────── */\n\n/** True when the feature gate (if any) is enabled (default: enabled). */\nexport function featureOn(feature: string | undefined, features: Record<string, boolean>): boolean {\n if (!feature) return true;\n return features[feature] !== false;\n}\n\n/**\n * Keep an item if its feature is on AND — for a dialog item — the chrome can\n * open it (built-in dialog, host override, or `onDialogRequest`). Dialog items\n * with no way to open are dropped (the SDK never fakes a dialog). Submenus are\n * filtered recursively and dropped when empty.\n */\nexport function keepItem(\n item: MenuItemDef,\n features: Record<string, boolean>,\n canOpen: (kind: DialogKind) => boolean,\n): MenuItemDef | null {\n if (!featureOn(item.feature, features)) return null;\n if (item.kind === 'separator') return item;\n if (item.kind === 'submenu') {\n const items = filterItems(item.items, features, canOpen);\n if (items.length === 0) return null;\n return { ...item, items };\n }\n if (item.dialog && !canOpen(item.dialog)) return null;\n return item;\n}\n\n/** Filter a list and collapse leading/trailing/double separators. */\nexport function filterItems(\n items: MenuItemDef[],\n features: Record<string, boolean>,\n canOpen: (kind: DialogKind) => boolean,\n): MenuItemDef[] {\n const kept = items\n .map((i) => keepItem(i, features, canOpen))\n .filter((i): i is MenuItemDef => i !== null);\n // Collapse separators: drop leading, trailing, and runs.\n const out: MenuItemDef[] = [];\n for (const item of kept) {\n if (item.kind === 'separator') {\n if (out.length === 0) continue;\n if (out[out.length - 1].kind === 'separator') continue;\n }\n out.push(item);\n }\n while (out.length > 0 && out[out.length - 1].kind === 'separator') out.pop();\n return out;\n}\n\n/* ─────────────────────────── host extensions ──────────────────────────── */\n\n/**\n * Append host menu extensions to their target top-level menu. Each extension\n * becomes a normal `item` (with a leading separator before the first host item\n * in that menu so it's visually grouped). Host items dispatch via `onClick` or\n * route a `dialog` kind through the dialog host, exactly like built-ins.\n */\nexport function withMenuExtensions(menus: MenuDef[], ext?: MenuExtension[]): MenuDef[] {\n if (!ext || ext.length === 0) return menus;\n const byMenu = new Map<MenuId, MenuExtension[]>();\n for (const e of ext) {\n const list = byMenu.get(e.menu) ?? [];\n list.push(e);\n byMenu.set(e.menu, list);\n }\n return menus.map((menu) => {\n const extras = byMenu.get(menu.id);\n if (!extras || extras.length === 0) return menu;\n const items: MenuItemDef[] = [...menu.items, { kind: 'separator', id: `ext-sep-${menu.id}` }];\n for (const e of extras) {\n items.push({\n kind: 'item',\n id: `ext-${e.id}`,\n label: e.label,\n icon: e.icon,\n shortcut: e.shortcut,\n dialog: e.dialog,\n run: e.onClick ? (api) => e.onClick?.(api) : undefined,\n });\n }\n return { ...menu, items };\n });\n}\n\n/**\n * Resolve the menus a host actually sees: append menu extensions, filter every\n * item by its `feature` gate + dialog-openability, then drop any top-level menu\n * whose own `feature` is off or that ends up empty.\n *\n * Exported (not inlined in the component) so the feature-gating contract — e.g.\n * `features={{ help: false }}` drops the Help menu and\n * `features={{ branding: false }}` drops the \"View on GitHub\" / \"About\" links —\n * is unit-testable without a DOM.\n */\nexport function computeVisibleMenus(\n menus: MenuDef[],\n features: Record<string, boolean>,\n canOpen: (kind: DialogKind) => boolean,\n ext?: MenuExtension[],\n): MenuDef[] {\n return withMenuExtensions(menus, ext)\n .map((menu) => ({\n ...menu,\n items: filterItems(menu.items, features, canOpen),\n }))\n .filter((menu) => featureOn(menu.feature, features) && menu.items.length > 0);\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * SheetTabs — worksheet tab strip for `<CasualSheets chrome>`.\n *\n * The fundamental multi-sheet control the built-in chrome was missing: switch\n * sheets (click), add a sheet (+), rename (double-click), and delete (context\n * menu). Drives the editor through the FUniver facade only — `insertSheet` /\n * `setActiveSheet` / `deleteSheet` / `FWorksheet.setName` — and stays live by\n * subscribing to the sheet-lifecycle facade events (plus the mutation-level\n * fallback so collab/replay-driven changes refresh too).\n *\n * Scope of this batch: switch / add / rename / delete. Drag-reorder, tab\n * colour, hide/unhide, and duplicate are richer host features deferred to\n * later parity batches (the reference app's SheetTabs has them).\n */\n\nimport { useEffect, useState, type CSSProperties, type KeyboardEvent } from 'react';\nimport { createPortal } from 'react-dom';\nimport type { CasualSheetsAPI } from '../sheets/api';\n\ninterface SheetTab {\n id: string;\n name: string;\n hidden: boolean;\n}\n\ninterface SheetsSnapshot {\n tabs: SheetTab[];\n activeId: string | null;\n}\n\nconst EMPTY: SheetsSnapshot = { tabs: [], activeId: null };\n\n/** Sheet-list mutations that must refresh the strip even when they arrive via\n * the collab bridge's mutation-only replay (which bypasses facade events). */\nconst SHEET_LIST_MUTATIONS = new Set([\n 'sheet.mutation.insert-sheet',\n 'sheet.mutation.remove-sheet',\n 'sheet.mutation.set-worksheet-name',\n 'sheet.mutation.set-worksheet-order',\n 'sheet.mutation.set-worksheet-hidden',\n]);\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyFacade = any;\n\nfunction readSheets(api: CasualSheetsAPI): SheetsSnapshot {\n const wb = api.univer.getActiveWorkbook();\n if (!wb) return EMPTY;\n const tabs = wb.getSheets().map((s) => ({\n id: s.getSheetId(),\n name: s.getSheetName(),\n hidden: (s as AnyFacade).isSheetHidden?.() === true,\n }));\n return { tabs, activeId: wb.getActiveSheet()?.getSheetId() ?? null };\n}\n\nconst BAR_STYLE: CSSProperties = {\n display: 'flex',\n alignItems: 'stretch',\n gap: 2,\n height: 30,\n flex: '0 0 auto',\n padding: '0 6px',\n borderTop: '1px solid var(--cs-chrome-border, rgba(0,0,0,0.12))',\n background: 'var(--cs-chrome-bg, #f8f9fa)',\n font: 'inherit',\n fontSize: 13,\n overflowX: 'auto',\n overflowY: 'hidden',\n};\n\nconst ADD_BTN_STYLE: CSSProperties = {\n flex: '0 0 auto',\n width: 28,\n border: 'none',\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n cursor: 'pointer',\n fontSize: 18,\n lineHeight: 1,\n borderRadius: 4,\n};\n\nconst RENAME_INPUT_STYLE: CSSProperties = {\n height: 22,\n alignSelf: 'center',\n padding: '0 6px',\n border: '1px solid var(--cs-chrome-active-fg, #0e7490)',\n borderRadius: 4,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n width: 120,\n};\n\nconst MENU_STYLE: CSSProperties = {\n position: 'fixed',\n zIndex: 1000,\n minWidth: 140,\n padding: 4,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n borderRadius: 8,\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 6px 20px rgba(0,0,0,0.16)',\n};\n\nconst MENU_ITEM_STYLE: CSSProperties = {\n display: 'block',\n width: '100%',\n textAlign: 'left',\n height: 28,\n padding: '0 10px',\n border: 'none',\n borderRadius: 6,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n};\n\nexport interface SheetTabsProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n}\n\nexport function SheetTabs({ api }: SheetTabsProps) {\n const [{ tabs, activeId }, setSnapshot] = useState<SheetsSnapshot>(EMPTY);\n // Inline-rename target sheet id (null = not renaming) + its draft text.\n const [renaming, setRenaming] = useState<string | null>(null);\n const [draft, setDraft] = useState('');\n // Right-click context menu: anchor + target sheet id.\n const [menu, setMenu] = useState<{ x: number; y: number; sheetId: string } | null>(null);\n\n useEffect(() => {\n if (!api) return;\n const refresh = () => setSnapshot(readSheets(api));\n refresh();\n const f = api.univer as AnyFacade;\n const subs: Array<{ dispose(): void }> = [];\n try {\n subs.push(\n f.addEvent(f.Event.SheetCreated, refresh),\n f.addEvent(f.Event.SheetDeleted, refresh),\n f.addEvent(f.Event.SheetNameChanged, refresh),\n f.addEvent(f.Event.ActiveSheetChanged, refresh),\n f.addEvent(f.Event.SheetMoved, refresh),\n // Mutation-level fallback — catches collab/replay-driven changes that\n // don't emit the higher-level facade events.\n f.addEvent(f.Event.CommandExecuted, (e: { id?: string }) => {\n if (e?.id && SHEET_LIST_MUTATIONS.has(e.id)) refresh();\n }),\n );\n // Whole-unit swaps (loadSnapshot / File→Open) don't fire SheetCreated;\n // refresh a tick after the new unit is wired in.\n if (typeof f.onUniverSheetCreated === 'function') {\n subs.push(f.onUniverSheetCreated(() => queueMicrotask(refresh)));\n }\n } catch {\n /* facade event surface differs — the initial read still populated tabs */\n }\n return () => {\n for (const s of subs) s?.dispose?.();\n };\n }, [api]);\n\n // Close the context menu on any outside interaction.\n useEffect(() => {\n if (!menu) return;\n const close = () => setMenu(null);\n window.addEventListener('pointerdown', close);\n window.addEventListener('keydown', close);\n return () => {\n window.removeEventListener('pointerdown', close);\n window.removeEventListener('keydown', close);\n };\n }, [menu]);\n\n if (!api) {\n return <div style={BAR_STYLE} data-testid=\"casual-sheets-tabs\" />;\n }\n\n const visible = tabs.filter((t) => !t.hidden);\n const wb = () => api.univer.getActiveWorkbook();\n\n const switchTo = (id: string) => {\n if (id === activeId) return;\n wb()?.setActiveSheet(id);\n };\n\n const addSheet = () => {\n const created = (wb() as AnyFacade)?.insertSheet?.();\n created?.activate?.();\n };\n\n const startRename = (tab: SheetTab) => {\n setMenu(null);\n setRenaming(tab.id);\n setDraft(tab.name);\n };\n\n const commitRename = () => {\n const id = renaming;\n setRenaming(null);\n if (!id) return;\n const name = draft.trim();\n if (!name) return;\n const sheet = (wb() as AnyFacade)?.getSheetBySheetId?.(id);\n if (sheet && sheet.getSheetName?.() !== name) sheet.setName?.(name);\n };\n\n const deleteSheet = (id: string) => {\n setMenu(null);\n // Excel keeps at least one visible sheet — never delete the last one.\n if (visible.length <= 1) return;\n (wb() as AnyFacade)?.deleteSheet?.(id);\n };\n\n const onRenameKey = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n commitRename();\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setRenaming(null);\n }\n };\n\n return (\n <div style={BAR_STYLE} data-testid=\"casual-sheets-tabs\" role=\"tablist\">\n {visible.map((tab) => {\n const active = tab.id === activeId;\n if (renaming === tab.id) {\n return (\n <input\n key={tab.id}\n autoFocus\n style={RENAME_INPUT_STYLE}\n value={draft}\n data-testid=\"cs-tab-rename-input\"\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={onRenameKey}\n onBlur={commitRename}\n />\n );\n }\n return (\n <button\n key={tab.id}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n data-testid={`cs-tab-${tab.id}`}\n data-active={active || undefined}\n title={tab.name}\n style={{\n flex: '0 0 auto',\n maxWidth: 160,\n padding: '0 12px',\n border: 'none',\n borderTop: active\n ? '2px solid var(--cs-chrome-active-fg, #0e7490)'\n : '2px solid transparent',\n background: active ? 'var(--cs-chrome-input-bg, #fff)' : 'transparent',\n color: active\n ? 'var(--cs-chrome-active-fg, #0e7490)'\n : 'var(--cs-chrome-fg, #201f1e)',\n fontWeight: active ? 600 : 400,\n font: 'inherit',\n fontSize: 13,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n }}\n // mousedown keeps the grid from stealing focus mid-switch.\n onMouseDown={(e) => {\n e.preventDefault();\n switchTo(tab.id);\n }}\n onDoubleClick={() => startRename(tab)}\n onContextMenu={(e) => {\n e.preventDefault();\n setMenu({ x: e.clientX, y: e.clientY, sheetId: tab.id });\n }}\n >\n {tab.name}\n </button>\n );\n })}\n <button\n type=\"button\"\n style={ADD_BTN_STYLE}\n aria-label=\"Add sheet\"\n title=\"Add sheet\"\n data-testid=\"cs-tab-add\"\n onMouseDown={(e) => {\n e.preventDefault();\n addSheet();\n }}\n >\n +\n </button>\n\n {menu &&\n createPortal(\n <div\n // Portaled to <body> so it escapes the tab strip's stacking context\n // (otherwise the fixed menu renders BEHIND the status bar below the\n // tabs). `translateY(-100%)` opens it UPWARD from the click since the\n // tab strip sits at the bottom of the editor.\n style={{ ...MENU_STYLE, left: menu.x, top: menu.y, transform: 'translateY(-100%)' }}\n data-testid=\"cs-tab-menu\"\n role=\"menu\"\n // Keep clicks inside the menu from closing it via the window handler.\n onPointerDown={(e) => e.stopPropagation()}\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n style={MENU_ITEM_STYLE}\n data-testid=\"cs-tab-menu-rename\"\n onMouseDown={(e) => {\n e.preventDefault();\n const tab = tabs.find((t) => t.id === menu.sheetId);\n if (tab) startRename(tab);\n }}\n >\n Rename\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n style={{\n ...MENU_ITEM_STYLE,\n opacity: visible.length <= 1 ? 0.5 : 1,\n cursor: visible.length <= 1 ? 'not-allowed' : 'pointer',\n }}\n data-testid=\"cs-tab-menu-delete\"\n onMouseDown={(e) => {\n e.preventDefault();\n deleteSheet(menu.sheetId);\n }}\n >\n Delete\n </button>\n </div>,\n document.body,\n )}\n </div>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * FindReplace — a custom find/replace dialog for `<CasualSheets chrome>`.\n *\n * Univer's own find-replace dialog doesn't render in the SDK's headless mount\n * (it needs Univer's UI/overlay layer, which is dormant when header/toolbar/\n * footer are off), so the chrome ships its own — driven purely through the\n * facade: search reads the active sheet's `cellData` from `getSnapshot()`,\n * navigation `activate()`s the matching cell, and replace `setValue()`s it.\n *\n * Opens on Ctrl/Cmd+F (find) or Ctrl/Cmd+H (replace) while the editor has focus;\n * Escape closes. Self-managing — just mount it in the chrome with the live api.\n */\n\nimport {\n useEffect,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n} from 'react';\nimport type { CasualSheetsAPI } from '../sheets/api';\nimport { Icon } from './Icon';\n\ninterface Match {\n row: number;\n col: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnySnapshot = any;\n\n/** Collect matches on the active sheet, in row-major order. Searches each\n * cell's value (`v`) and formula (`f`) text. */\nfunction findMatches(api: CasualSheetsAPI, query: string, matchCase: boolean): Match[] {\n if (!query) return [];\n const snap = api.getSnapshot() as AnySnapshot;\n const sheetId =\n api.getSelection()?.sheetId ?? api.univer.getActiveWorkbook()?.getActiveSheet()?.getSheetId();\n const sheet = sheetId ? snap?.sheets?.[sheetId] : undefined;\n const cellData = sheet?.cellData as Record<string, Record<string, AnySnapshot>> | undefined;\n if (!cellData) return [];\n const needle = matchCase ? query : query.toLowerCase();\n const out: Match[] = [];\n for (const rk of Object.keys(cellData).sort((a, b) => Number(a) - Number(b))) {\n const rowObj = cellData[rk];\n if (!rowObj) continue;\n for (const ck of Object.keys(rowObj).sort((a, b) => Number(a) - Number(b))) {\n const cell = rowObj[ck];\n if (!cell) continue;\n const hay = `${cell.v ?? ''}${cell.f ? ` ${cell.f}` : ''}`;\n const cmp = matchCase ? hay : hay.toLowerCase();\n if (cmp.includes(needle)) out.push({ row: Number(rk), col: Number(ck) });\n }\n }\n return out;\n}\n\nconst WRAP_STYLE: CSSProperties = {\n position: 'absolute',\n top: 8,\n right: 12,\n zIndex: 1100,\n width: 320,\n padding: 10,\n borderRadius: 8,\n border: '1px solid var(--cs-chrome-border, #e6e9ee)',\n background: 'var(--cs-chrome-input-bg, #fff)',\n boxShadow: '0 8px 28px rgba(0,0,0,0.18)',\n font: 'inherit',\n fontSize: 13,\n color: 'var(--cs-chrome-fg, #201f1e)',\n};\n\nconst ROW_STYLE: CSSProperties = { display: 'flex', alignItems: 'center', gap: 6, marginBottom: 6 };\n\nconst INPUT_STYLE: CSSProperties = {\n flex: '1 1 auto',\n height: 26,\n padding: '0 8px',\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 4,\n background: 'var(--cs-chrome-input-bg, #fff)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 13,\n boxSizing: 'border-box',\n};\n\nconst BTN_STYLE: CSSProperties = {\n height: 26,\n padding: '0 10px',\n border: '1px solid var(--cs-chrome-border, #cdd3db)',\n borderRadius: 4,\n background: 'var(--cs-chrome-bg, #f3f5f8)',\n color: 'var(--cs-chrome-fg, #201f1e)',\n font: 'inherit',\n fontSize: 12,\n cursor: 'pointer',\n};\n\nconst ICON_BTN_STYLE: CSSProperties = {\n width: 26,\n height: 26,\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n border: 'none',\n borderRadius: 4,\n background: 'transparent',\n color: 'var(--cs-chrome-fg, #201f1e)',\n cursor: 'pointer',\n padding: 0,\n};\n\nexport interface FindReplaceProps {\n /** Live API, or `null` until the editor is ready. */\n api: CasualSheetsAPI | null;\n /**\n * Imperative open trigger from the dialog host. Bump this counter to open the\n * panel (e.g. when `openDialog('find-replace')` is called from a menu item).\n * The panel still self-opens on Ctrl/Cmd+F·H independently.\n */\n openSignal?: number;\n /** When the host opens it via `openSignal`, start in replace mode. */\n openInReplaceMode?: boolean;\n}\n\nexport function FindReplace({ api, openSignal, openInReplaceMode }: FindReplaceProps) {\n const [open, setOpen] = useState(false);\n const [showReplace, setShowReplace] = useState(false);\n const [query, setQuery] = useState('');\n const [replaceText, setReplaceText] = useState('');\n const [matchCase, setMatchCase] = useState(false);\n const [idx, setIdx] = useState(0);\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Open on Ctrl/Cmd+F (find) / Ctrl/Cmd+H (replace), close on Escape.\n useEffect(() => {\n const onKey = (e: globalThis.KeyboardEvent) => {\n const mod = e.metaKey || e.ctrlKey;\n if (mod && (e.key === 'f' || e.key === 'F')) {\n e.preventDefault();\n setShowReplace(false);\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n } else if (mod && (e.key === 'h' || e.key === 'H')) {\n e.preventDefault();\n setShowReplace(true);\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n }\n };\n document.addEventListener('keydown', onKey);\n return () => document.removeEventListener('keydown', onKey);\n }, []);\n\n // Host-driven open (openDialog('find-replace')). `openSignal === undefined`\n // means \"never opened by the host\"; any defined value opens (and re-opening\n // bumps the counter). Skip the initial undefined→defined? No — only react when\n // a defined signal arrives.\n const lastSignal = useRef<number | undefined>(undefined);\n useEffect(() => {\n if (openSignal === undefined) return;\n if (lastSignal.current === openSignal) return;\n lastSignal.current = openSignal;\n setShowReplace(!!openInReplaceMode);\n setOpen(true);\n requestAnimationFrame(() => inputRef.current?.focus());\n }, [openSignal, openInReplaceMode]);\n\n const matches = useMemo(\n () => (api && open && query ? findMatches(api, query, matchCase) : []),\n [api, open, query, matchCase],\n );\n\n // Keep idx in range as matches change.\n useEffect(() => {\n setIdx((i) => (matches.length === 0 ? 0 : Math.min(i, matches.length - 1)));\n }, [matches.length]);\n\n if (!open || !api) return null;\n\n const go = (delta: number) => {\n if (matches.length === 0) return;\n const next = (idx + delta + matches.length) % matches.length;\n setIdx(next);\n activate(matches[next]);\n };\n\n const activate = (m: Match) => {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (sheet?.getRange(m.row, m.col) as any)?.activate?.();\n };\n\n const replaceOne = () => {\n if (matches.length === 0) return;\n const m = matches[Math.min(idx, matches.length - 1)];\n replaceAt(m);\n // Matches recompute via the query memo on next render; advance stays put.\n };\n\n const replaceAt = (m: Match) => {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sheet) return;\n const cur = String(sheet.getRange(m.row, m.col).getValue?.() ?? '');\n const next = replaceInString(cur, query, replaceText, matchCase);\n if (next !== cur) sheet.getRange(m.row, m.col).setValue(next);\n };\n\n const replaceAll = () => {\n const sheet = api.univer.getActiveWorkbook()?.getActiveSheet();\n if (!sheet) return;\n for (const m of matches) {\n const cur = String(sheet.getRange(m.row, m.col).getValue?.() ?? '');\n const next = replaceInString(cur, query, replaceText, matchCase);\n if (next !== cur) sheet.getRange(m.row, m.col).setValue(next);\n }\n };\n\n const onInputKey = (e: KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n go(e.shiftKey ? -1 : 1);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n setOpen(false);\n }\n };\n\n const count = matches.length;\n const position = count === 0 ? 0 : Math.min(idx, count - 1) + 1;\n\n return (\n <div\n style={WRAP_STYLE}\n data-testid=\"cs-find-replace\"\n role=\"dialog\"\n aria-label=\"Find and replace\"\n >\n <div style={ROW_STYLE}>\n <input\n ref={inputRef}\n type=\"text\"\n aria-label=\"Find\"\n placeholder=\"Find\"\n data-testid=\"cs-find-input\"\n style={INPUT_STYLE}\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n onKeyDown={onInputKey}\n />\n <span\n style={{ minWidth: 54, textAlign: 'center', color: 'var(--cs-chrome-muted, #6b7280)' }}\n data-testid=\"cs-find-count\"\n >\n {position}/{count}\n </span>\n <button\n type=\"button\"\n style={ICON_BTN_STYLE}\n aria-label=\"Previous match\"\n data-testid=\"cs-find-prev\"\n onMouseDown={(e) => {\n e.preventDefault();\n go(-1);\n }}\n >\n <Icon name=\"keyboard_arrow_up\" size={18} />\n </button>\n <button\n type=\"button\"\n style={ICON_BTN_STYLE}\n aria-label=\"Next match\"\n data-testid=\"cs-find-next\"\n onMouseDown={(e) => {\n e.preventDefault();\n go(1);\n }}\n >\n <Icon name=\"keyboard_arrow_down\" size={18} />\n </button>\n <button\n type=\"button\"\n style={ICON_BTN_STYLE}\n aria-label=\"Close\"\n data-testid=\"cs-find-close\"\n onMouseDown={(e) => {\n e.preventDefault();\n setOpen(false);\n }}\n >\n <Icon name=\"close\" size={18} />\n </button>\n </div>\n\n {showReplace && (\n <div style={ROW_STYLE}>\n <input\n type=\"text\"\n aria-label=\"Replace with\"\n placeholder=\"Replace with\"\n data-testid=\"cs-replace-input\"\n style={INPUT_STYLE}\n value={replaceText}\n onChange={(e) => setReplaceText(e.target.value)}\n />\n <button\n type=\"button\"\n style={BTN_STYLE}\n data-testid=\"cs-replace-one\"\n onMouseDown={(e) => {\n e.preventDefault();\n replaceOne();\n }}\n >\n Replace\n </button>\n <button\n type=\"button\"\n style={BTN_STYLE}\n data-testid=\"cs-replace-all\"\n onMouseDown={(e) => {\n e.preventDefault();\n replaceAll();\n }}\n >\n All\n </button>\n </div>\n )}\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>\n <label style={{ display: 'inline-flex', alignItems: 'center', gap: 4, cursor: 'pointer' }}>\n <input\n type=\"checkbox\"\n data-testid=\"cs-find-match-case\"\n checked={matchCase}\n onChange={(e) => setMatchCase(e.target.checked)}\n />\n Match case\n </label>\n {!showReplace && (\n <button\n type=\"button\"\n style={{\n ...BTN_STYLE,\n marginLeft: 'auto',\n border: 'none',\n background: 'transparent',\n color: 'var(--cs-chrome-active-fg, #0e7490)',\n }}\n data-testid=\"cs-find-toggle-replace\"\n onMouseDown={(e) => {\n e.preventDefault();\n setShowReplace(true);\n }}\n >\n Replace…\n </button>\n )}\n </div>\n </div>\n );\n}\n\n/** Replace all occurrences of `query` in `text` (case-(in)sensitive). */\nfunction replaceInString(\n text: string,\n query: string,\n replacement: string,\n matchCase: boolean,\n): string {\n if (!query) return text;\n if (matchCase) return text.split(query).join(replacement);\n // Case-insensitive: walk and rebuild preserving non-matched casing.\n const lower = text.toLowerCase();\n const needle = query.toLowerCase();\n let out = '';\n let i = 0;\n while (i < text.length) {\n if (lower.startsWith(needle, i)) {\n out += replacement;\n i += needle.length;\n } else {\n out += text[i];\n i += 1;\n }\n }\n return out;\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * ChromeTop — the chrome ABOVE the grid (menu bar + toolbar + formula bar).\n * Lives in the `@casualoffice/sheets/chrome` entry, lazy-imported by\n * `<CasualSheets>` only when `chrome !== 'none'` so bare-grid consumers (the\n * default; the apps/web host renders chrome=\"none\" + its own shell) never bundle\n * the chrome JS.\n *\n * Owns the dialog host: wraps MenuBar/Toolbar in `<DialogProvider>` so their\n * controls call `openDialog(kind)` and the SDK's built-in dialogs (Format Cells,\n * …) open by default — a host overrides them via `extensions.dialogs`. The\n * self-managing FindReplace panel is mounted here and bridged to\n * `openDialog('find-replace')` via an open signal.\n */\nimport { useCallback, useState } from 'react';\nimport { MenuBar } from './MenuBar';\nimport { Toolbar } from './Toolbar';\nimport { FormulaBar } from './FormulaBar';\nimport { FindReplace } from './FindReplace';\nimport { DialogProvider, type DialogKind } from './dialog-context';\nimport type { ChromeExtensions } from './extensions';\nimport type { CasualSheetsAPI } from '../sheets/api';\n\nexport interface ChromeTopProps {\n api: CasualSheetsAPI | null;\n /** Hide a control/group + block its command when its key is false. */\n features?: Record<string, boolean>;\n /**\n * Legacy host hook — route dialog-backed controls to the host instead of the\n * SDK built-in. Kept for back-compat; prefer `extensions.dialogs`.\n */\n onDialogRequest?: (kind: DialogKind, context?: unknown) => void;\n /** Kinds the host owns via `onDialogRequest` despite an SDK built-in. */\n hostOwnedDialogs?: DialogKind[];\n /** Host chrome extensions: custom toolbar/menu items, dialogs, panels. */\n extensions?: ChromeExtensions;\n}\n\nexport function ChromeTop({\n api,\n features,\n onDialogRequest,\n hostOwnedDialogs,\n extensions,\n}: ChromeTopProps) {\n // FindReplace is a self-managing panel; the dialog host opens it by bumping\n // this signal. (Ctrl/Cmd+F·H still open it directly.)\n const [findSignal, setFindSignal] = useState(0);\n const [findReplaceMode, setFindReplaceMode] = useState(false);\n const openFindReplace = useCallback((replaceMode: boolean) => {\n setFindReplaceMode(replaceMode);\n setFindSignal((n) => n + 1);\n }, []);\n\n return (\n <DialogProvider\n api={api}\n extensions={extensions}\n onDialogRequest={onDialogRequest}\n hostOwnedDialogs={hostOwnedDialogs}\n onOpenFindReplace={openFindReplace}\n >\n <MenuBar api={api} features={features} extensions={extensions} />\n <Toolbar api={api} features={features} extensions={extensions} />\n <FormulaBar api={api} />\n <FindReplace\n api={api}\n openSignal={findSignal || undefined}\n openInReplaceMode={findReplaceMode}\n />\n </DialogProvider>\n );\n}\n","/**\n * Copyright 2026 Casual Office\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\n/**\n * ChromeBottom — the chrome BELOW the grid (sheet tabs + status bar).\n * Lazy-imported with ChromeTop (see ChromeTop).\n *\n * NOTE: Find & Replace is mounted in ChromeTop (inside the DialogProvider, so\n * the dialog host can open it via `openDialog('find-replace')`). It is NOT\n * mounted here — two `<FindReplace>` instances both bound Ctrl+F and rendered\n * two `cs-find-replace` dialogs (strict-mode violation in the chrome e2e).\n */\nimport { SheetTabs } from './SheetTabs';\nimport { StatusBar } from './StatusBar';\nimport type { CasualSheetsAPI } from '../sheets/api';\n\nexport function ChromeBottom({ api }: { api: CasualSheetsAPI | null }) {\n return (\n <>\n <SheetTabs api={api} />\n <StatusBar api={api} />\n </>\n );\n}\n"],"mappings":"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","names":["import_react","import_core","import_jsx_runtime","import_react","import_jsx_runtime","ROW_STYLE","BTN_STYLE","POPOVER_STYLE","import_react","import_jsx_runtime","ROW_STYLE","BTN_STYLE","POPOVER_STYLE","ITEM_STYLE","import_react","import_react","import_react","import_jsx_runtime","first","import_jsx_runtime","import_react","import_jsx_runtime","activeRange","CHECK_STYLE","import_react","import_facade","import_jsx_runtime","RULE_TYPE_OPTIONS","OPERATOR_OPTIONS","isRangeOperator","INITIAL_STATE","activeRange","RANGE_NOTE_STYLE","CHECK_STYLE","COLOR_INPUT_STYLE","TWO_COL_STYLE","import_react","import_facade","import_jsx_runtime","activeRange","RANGE_NOTE_STYLE","CHECK_STYLE","import_react","import_facade","import_jsx_runtime","activeRange","RANGE_NOTE_STYLE","import_react","import_jsx_runtime","activeRange","RANGE_NOTE_STYLE","import_react","import_jsx_runtime","ROW_STYLE","LIST_STYLE","TWO_COL_STYLE","import_react","import_core","import_jsx_runtime","activeRange","RANGE_NOTE_STYLE","import_react","import_core","import_jsx_runtime","SHIFT_OPTIONS","activeRange","start","count","RANGE_NOTE_STYLE","import_react","import_facade","import_jsx_runtime","INITIAL_STATE","import_react","import_facade","import_jsx_runtime","activeRange","activeSheet","bh","bw","RANGE_NOTE_STYLE","import_react","import_jsx_runtime","activeRange","RANGE_NOTE_STYLE","ERROR_STYLE","import_react","import_jsx_runtime","activeRange","toNumber","RANGE_NOTE_STYLE","CHECK_STYLE","RADIO_ROW_STYLE","import_jsx_runtime","import_jsx_runtime","readActiveStyle","FONT_FAMILIES","NUMBER_FORMAT_PATTERNS","NUMBER_FORMAT_OPTIONS","detectFormatKey","BTN_STYLE","import_react","import_core","import_react","import_core","import_jsx_runtime","onKeyDown","import_jsx_runtime","FUNCTIONS","colToLetters","BAR_STYLE","import_react","import_core","import_jsx_runtime","BAR_STYLE","import_react","import_core","import_jsx_runtime","activeRange","activeSheet","NUMBER_FORMAT_PATTERNS","BAR_STYLE","ITEM_STYLE","import_react","import_react_dom","import_jsx_runtime","BAR_STYLE","ADD_BTN_STYLE","MENU_STYLE","MENU_ITEM_STYLE","import_react","import_jsx_runtime","ROW_STYLE","INPUT_STYLE","BTN_STYLE","import_react","import_jsx_runtime","import_jsx_runtime"]}