@underverse-ui/underverse 1.0.201 → 1.0.203

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.
package/dist/index.js CHANGED
@@ -801,6 +801,8 @@ var en_default = {
801
801
  alignCenter: "Align Center",
802
802
  alignRight: "Align Right",
803
803
  justify: "Justify",
804
+ decreaseIndent: "Decrease Indent",
805
+ increaseIndent: "Increase Indent",
804
806
  bulletList: "Bullet List",
805
807
  orderedList: "Numbered List",
806
808
  taskList: "Task List",
@@ -938,11 +940,14 @@ var en_default = {
938
940
  mergeCells: "Merge Cells",
939
941
  splitCell: "Split Cell",
940
942
  openControls: "Open Table Controls",
943
+ cellFormatting: "Cell Formatting",
941
944
  quickAddColumnAfter: "Quick Add Column After",
942
945
  quickAddRowAfter: "Quick Add Row After",
943
946
  expandTable: "Expand Table",
944
947
  dragRow: "Drag Row",
945
948
  dragColumn: "Drag Column",
949
+ resizeBoth: "Resize Table",
950
+ resizeCtrlHint: "Drag freely. Hold Ctrl to lock to one axis; hold Ctrl+Shift to preserve proportions",
946
951
  alignLeft: "Align Table Left",
947
952
  alignCenter: "Align Table Center",
948
953
  alignRight: "Align Table Right",
@@ -1247,6 +1252,8 @@ var vi_default = {
1247
1252
  alignCenter: "C\u0103n gi\u1EEFa",
1248
1253
  alignRight: "C\u0103n ph\u1EA3i",
1249
1254
  justify: "C\u0103n \u0111\u1EC1u",
1255
+ decreaseIndent: "Gi\u1EA3m l\u1EC1",
1256
+ increaseIndent: "T\u0103ng l\u1EC1",
1250
1257
  bulletList: "Danh s\xE1ch d\u1EA5u ch\u1EA5m",
1251
1258
  orderedList: "Danh s\xE1ch s\u1ED1",
1252
1259
  taskList: "Danh s\xE1ch c\xF4ng vi\u1EC7c",
@@ -1384,11 +1391,14 @@ var vi_default = {
1384
1391
  mergeCells: "G\u1ED9p \xF4",
1385
1392
  splitCell: "T\xE1ch \xF4",
1386
1393
  openControls: "M\u1EDF \u0111i\u1EC1u khi\u1EC3n b\u1EA3ng",
1394
+ cellFormatting: "\u0110\u1ECBnh d\u1EA1ng \xF4",
1387
1395
  quickAddColumnAfter: "Th\xEAm nhanh c\u1ED9t sau",
1388
1396
  quickAddRowAfter: "Th\xEAm nhanh h\xE0ng sau",
1389
1397
  expandTable: "M\u1EDF r\u1ED9ng b\u1EA3ng",
1390
1398
  dragRow: "K\xE9o h\xE0ng",
1391
1399
  dragColumn: "K\xE9o c\u1ED9t",
1400
+ resizeBoth: "\u0110\u1ED5i k\xEDch th\u01B0\u1EDBc b\u1EA3ng",
1401
+ resizeCtrlHint: "K\xE9o t\u1EF1 do; gi\u1EEF Ctrl \u0111\u1EC3 kh\xF3a m\u1ED9t chi\u1EC1u, ho\u1EB7c Ctrl+Shift \u0111\u1EC3 gi\u1EEF nguy\xEAn t\u1EF7 l\u1EC7",
1392
1402
  alignLeft: "C\u0103n b\u1EA3ng tr\xE1i",
1393
1403
  alignCenter: "C\u0103n b\u1EA3ng gi\u1EEFa",
1394
1404
  alignRight: "C\u0103n b\u1EA3ng ph\u1EA3i",
@@ -1693,6 +1703,8 @@ var ko_default = {
1693
1703
  alignCenter: "\uAC00\uC6B4\uB370 \uC815\uB82C",
1694
1704
  alignRight: "\uC624\uB978\uCABD \uC815\uB82C",
1695
1705
  justify: "\uC591\uCABD \uB9DE\uCDA4",
1706
+ decreaseIndent: "\uB0B4\uC5B4\uC4F0\uAE30",
1707
+ increaseIndent: "\uB4E4\uC5EC\uC4F0\uAE30",
1696
1708
  bulletList: "\uAE00\uBA38\uB9AC \uAE30\uD638 \uBAA9\uB85D",
1697
1709
  orderedList: "\uBC88\uD638 \uB9E4\uAE30\uAE30 \uBAA9\uB85D",
1698
1710
  taskList: "\uD560 \uC77C \uBAA9\uB85D",
@@ -1830,11 +1842,14 @@ var ko_default = {
1830
1842
  mergeCells: "\uC140 \uBCD1\uD569",
1831
1843
  splitCell: "\uC140 \uBD84\uD560",
1832
1844
  openControls: "\uD45C \uCEE8\uD2B8\uB864 \uC5F4\uAE30",
1845
+ cellFormatting: "\uC140 \uC11C\uC2DD",
1833
1846
  quickAddColumnAfter: "\uC624\uB978\uCABD \uC5F4 \uBE60\uB974\uAC8C \uCD94\uAC00",
1834
1847
  quickAddRowAfter: "\uC544\uB798 \uD589 \uBE60\uB974\uAC8C \uCD94\uAC00",
1835
1848
  expandTable: "\uD45C \uD655\uC7A5",
1836
1849
  dragRow: "\uD589 \uB4DC\uB798\uADF8",
1837
1850
  dragColumn: "\uC5F4 \uB4DC\uB798\uADF8",
1851
+ resizeBoth: "\uD45C \uD06C\uAE30 \uC870\uC808",
1852
+ resizeCtrlHint: "\uC790\uC720\uB86D\uAC8C \uB4DC\uB798\uADF8\uD569\uB2C8\uB2E4. Ctrl \uD0A4\uB97C \uB204\uB974\uBA74 \uD55C \uCD95\uC73C\uB85C \uACE0\uC815\uB418\uACE0, Ctrl+Shift \uD0A4\uB97C \uB204\uB974\uBA74 \uBE44\uC728\uC774 \uC720\uC9C0\uB429\uB2C8\uB2E4",
1838
1853
  alignLeft: "\uD45C \uC67C\uCABD \uC815\uB82C",
1839
1854
  alignCenter: "\uD45C \uAC00\uC6B4\uB370 \uC815\uB82C",
1840
1855
  alignRight: "\uD45C \uC624\uB978\uCABD \uC815\uB82C",
@@ -2139,6 +2154,8 @@ var ja_default = {
2139
2154
  alignCenter: "\u4E2D\u592E\u63C3\u3048",
2140
2155
  alignRight: "\u53F3\u63C3\u3048",
2141
2156
  justify: "\u4E21\u7AEF\u63C3\u3048",
2157
+ decreaseIndent: "\u30A4\u30F3\u30C7\u30F3\u30C8\u3092\u6E1B\u3089\u3059",
2158
+ increaseIndent: "\u30A4\u30F3\u30C7\u30F3\u30C8\u3092\u5897\u3084\u3059",
2142
2159
  bulletList: "\u7B87\u6761\u66F8\u304D",
2143
2160
  orderedList: "\u756A\u53F7\u4ED8\u304D\u30EA\u30B9\u30C8",
2144
2161
  taskList: "\u30BF\u30B9\u30AF\u30EA\u30B9\u30C8",
@@ -2276,11 +2293,14 @@ var ja_default = {
2276
2293
  mergeCells: "\u30BB\u30EB\u3092\u7D50\u5408",
2277
2294
  splitCell: "\u30BB\u30EB\u3092\u5206\u5272",
2278
2295
  openControls: "\u8868\u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\u3092\u958B\u304F",
2296
+ cellFormatting: "\u30BB\u30EB\u306E\u66F8\u5F0F\u8A2D\u5B9A",
2279
2297
  quickAddColumnAfter: "\u53F3\u5074\u306B\u5217\u3092\u3059\u3070\u3084\u304F\u8FFD\u52A0",
2280
2298
  quickAddRowAfter: "\u4E0B\u306B\u884C\u3092\u3059\u3070\u3084\u304F\u8FFD\u52A0",
2281
2299
  expandTable: "\u8868\u3092\u62E1\u5F35",
2282
2300
  dragRow: "\u884C\u3092\u30C9\u30E9\u30C3\u30B0",
2283
2301
  dragColumn: "\u5217\u3092\u30C9\u30E9\u30C3\u30B0",
2302
+ resizeBoth: "\u8868\u306E\u30B5\u30A4\u30BA\u3092\u5909\u66F4",
2303
+ resizeCtrlHint: "\u81EA\u7531\u306B\u30C9\u30E9\u30C3\u30B0\u3067\u304D\u307E\u3059\u3002Ctrl\u30AD\u30FC\u30671\u65B9\u5411\u306B\u56FA\u5B9A\u3057\u3001Ctrl+Shift\u30AD\u30FC\u3067\u7E26\u6A2A\u6BD4\u3092\u7DAD\u6301\u3057\u307E\u3059",
2284
2304
  alignLeft: "\u8868\u3092\u5DE6\u5BC4\u305B",
2285
2305
  alignCenter: "\u8868\u3092\u4E2D\u592E\u63C3\u3048",
2286
2306
  alignRight: "\u8868\u3092\u53F3\u5BC4\u305B",
@@ -8679,6 +8699,8 @@ var DropdownMenu = ({
8679
8699
  disabled = false,
8680
8700
  isOpen,
8681
8701
  onOpenChange,
8702
+ openOnHover = false,
8703
+ hoverCloseDelay = 120,
8682
8704
  items,
8683
8705
  borderMode
8684
8706
  }) => {
@@ -8698,10 +8720,26 @@ var DropdownMenu = ({
8698
8720
  const itemsRef = React29.useRef([]);
8699
8721
  const [activeIndex, setActiveIndex] = useResettingIndex(open);
8700
8722
  const parentMenu = React29.useContext(DropdownMenuContext);
8723
+ const hoverCloseTimeoutRef = React29.useRef(null);
8724
+ const cancelHoverClose = React29.useCallback(() => {
8725
+ if (hoverCloseTimeoutRef.current === null) return;
8726
+ clearTimeout(hoverCloseTimeoutRef.current);
8727
+ hoverCloseTimeoutRef.current = null;
8728
+ }, []);
8729
+ const scheduleHoverClose = React29.useCallback(() => {
8730
+ if (!openOnHover) return;
8731
+ cancelHoverClose();
8732
+ hoverCloseTimeoutRef.current = setTimeout(() => {
8733
+ hoverCloseTimeoutRef.current = null;
8734
+ setOpen(false);
8735
+ }, hoverCloseDelay);
8736
+ }, [cancelHoverClose, hoverCloseDelay, openOnHover, setOpen]);
8737
+ React29.useEffect(() => () => cancelHoverClose(), [cancelHoverClose]);
8701
8738
  const closeMenu = React29.useCallback(() => {
8739
+ cancelHoverClose();
8702
8740
  setOpen(false);
8703
8741
  parentMenu?.closeMenu();
8704
- }, [parentMenu, setOpen]);
8742
+ }, [cancelHoverClose, parentMenu, setOpen]);
8705
8743
  const getEnabledMenuItems = React29.useCallback(() => {
8706
8744
  const menuEl = menuRef.current;
8707
8745
  if (!menuEl) return [];
@@ -8758,9 +8796,11 @@ var DropdownMenu = ({
8758
8796
  const menuContext = React29.useMemo(
8759
8797
  () => ({
8760
8798
  closeMenu,
8761
- closeOnSelect
8799
+ closeOnSelect,
8800
+ cancelHoverClose,
8801
+ scheduleHoverClose
8762
8802
  }),
8763
- [closeMenu, closeOnSelect]
8803
+ [cancelHoverClose, closeMenu, closeOnSelect, scheduleHoverClose]
8764
8804
  );
8765
8805
  const handleItemClick = (itemOnClick) => {
8766
8806
  itemOnClick();
@@ -8768,71 +8808,117 @@ var DropdownMenu = ({
8768
8808
  closeMenu();
8769
8809
  }
8770
8810
  };
8771
- const menuBody = /* @__PURE__ */ jsx32(DropdownMenuContext.Provider, { value: menuContext, children: /* @__PURE__ */ jsx32("div", { ref: menuRef, "data-dropdown-menu": true, "data-state": open ? "open" : "closed", role: "menu", className: cn("min-w-40", className), children: items ? items.map((item, index) => {
8772
- const IconComponent = item.icon;
8773
- return /* @__PURE__ */ jsxs22(
8774
- "button",
8775
- {
8776
- ref: (el) => {
8777
- if (el) itemsRef.current[index] = el;
8778
- },
8779
- onClick: () => handleItemClick(item.onClick),
8780
- disabled: item.disabled,
8781
- role: "menuitem",
8782
- "data-dropdown-menu-item": "",
8783
- tabIndex: -1,
8784
- style: {
8785
- animationDelay: open ? `${Math.min(index * 20, 200)}ms` : "0ms"
8786
- },
8787
- className: cn(
8788
- "dropdown-item flex w-full items-center gap-2 px-2.5 py-1.5 text-sm",
8789
- resolvedBorderMode ? getBorderRadiusClass(resolvedBorderMode) : "rounded-lg",
8790
- "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
8791
- "hover:bg-accent hover:text-accent-foreground",
8792
- "focus:bg-accent focus:text-accent-foreground",
8793
- "disabled:opacity-50 disabled:cursor-not-allowed",
8794
- item.destructive && "text-destructive hover:bg-destructive/10 focus:bg-destructive/10"
8795
- ),
8796
- children: [
8797
- IconComponent && /* @__PURE__ */ jsx32(IconComponent, { className: "h-4 w-4" }),
8798
- item.label
8799
- ]
8800
- },
8801
- index
8802
- );
8803
- }) : children }) });
8811
+ const menuBody = /* @__PURE__ */ jsx32(DropdownMenuContext.Provider, { value: menuContext, children: /* @__PURE__ */ jsx32(
8812
+ "div",
8813
+ {
8814
+ ref: menuRef,
8815
+ "data-dropdown-menu": true,
8816
+ "data-state": open ? "open" : "closed",
8817
+ role: "menu",
8818
+ className: cn("min-w-40", className),
8819
+ onMouseEnter: openOnHover ? () => {
8820
+ cancelHoverClose();
8821
+ parentMenu?.cancelHoverClose();
8822
+ } : void 0,
8823
+ onMouseLeave: openOnHover ? () => {
8824
+ scheduleHoverClose();
8825
+ parentMenu?.scheduleHoverClose();
8826
+ } : void 0,
8827
+ children: items ? items.map((item, index) => {
8828
+ const IconComponent = item.icon;
8829
+ return /* @__PURE__ */ jsxs22(
8830
+ "button",
8831
+ {
8832
+ ref: (el) => {
8833
+ if (el) itemsRef.current[index] = el;
8834
+ },
8835
+ onClick: () => handleItemClick(item.onClick),
8836
+ disabled: item.disabled,
8837
+ role: "menuitem",
8838
+ "data-dropdown-menu-item": "",
8839
+ tabIndex: -1,
8840
+ style: {
8841
+ animationDelay: open ? `${Math.min(index * 20, 200)}ms` : "0ms"
8842
+ },
8843
+ className: cn(
8844
+ "dropdown-item flex w-full items-center gap-2 px-2.5 py-1.5 text-sm",
8845
+ resolvedBorderMode ? getBorderRadiusClass(resolvedBorderMode) : "rounded-lg",
8846
+ "outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
8847
+ "hover:bg-accent hover:text-accent-foreground",
8848
+ "focus:bg-accent focus:text-accent-foreground",
8849
+ "disabled:opacity-50 disabled:cursor-not-allowed",
8850
+ item.destructive && "text-destructive hover:bg-destructive/10 focus:bg-destructive/10"
8851
+ ),
8852
+ children: [
8853
+ IconComponent && /* @__PURE__ */ jsx32(IconComponent, { className: "h-4 w-4" }),
8854
+ item.label
8855
+ ]
8856
+ },
8857
+ index
8858
+ );
8859
+ }) : children
8860
+ }
8861
+ ) });
8804
8862
  const triggerProps = trigger.props;
8805
- const childRef = triggerProps.ref;
8863
+ const {
8864
+ ref: childRef,
8865
+ onKeyDown: triggerOnKeyDown,
8866
+ onClick: triggerOnClick,
8867
+ onMouseEnter: triggerOnMouseEnter,
8868
+ onMouseLeave: triggerOnMouseLeave
8869
+ } = triggerProps;
8870
+ const setTriggerNode = React29.useCallback((node) => {
8871
+ setRefValue(childRef, node);
8872
+ triggerRef.current = node;
8873
+ }, [childRef]);
8874
+ const handleTriggerKeyDown = React29.useCallback((event) => {
8875
+ if (!disabled) {
8876
+ if (event.key === "ArrowDown") {
8877
+ event.preventDefault();
8878
+ setOpen(true);
8879
+ requestAnimationFrame(() => focusMenuItem(0));
8880
+ } else if (event.key === "ArrowUp") {
8881
+ event.preventDefault();
8882
+ setOpen(true);
8883
+ requestAnimationFrame(() => {
8884
+ const enabled = getEnabledMenuItems();
8885
+ focusMenuItem(enabled.length - 1);
8886
+ });
8887
+ } else if (event.key === "Escape") {
8888
+ event.preventDefault();
8889
+ setOpen(false);
8890
+ }
8891
+ }
8892
+ triggerOnKeyDown?.(event);
8893
+ }, [disabled, focusMenuItem, getEnabledMenuItems, setOpen, triggerOnKeyDown]);
8894
+ const handleTriggerClick = React29.useCallback((event) => {
8895
+ if (openOnHover && !disabled) {
8896
+ cancelHoverClose();
8897
+ setOpen(true);
8898
+ }
8899
+ triggerOnClick?.(event);
8900
+ }, [cancelHoverClose, disabled, openOnHover, setOpen, triggerOnClick]);
8901
+ const handleTriggerMouseEnter = React29.useCallback((event) => {
8902
+ if (openOnHover && !disabled) {
8903
+ cancelHoverClose();
8904
+ parentMenu?.cancelHoverClose();
8905
+ setOpen(true);
8906
+ }
8907
+ triggerOnMouseEnter?.(event);
8908
+ }, [cancelHoverClose, disabled, openOnHover, parentMenu, setOpen, triggerOnMouseEnter]);
8909
+ const handleTriggerMouseLeave = React29.useCallback((event) => {
8910
+ scheduleHoverClose();
8911
+ triggerOnMouseLeave?.(event);
8912
+ }, [scheduleHoverClose, triggerOnMouseLeave]);
8806
8913
  const enhancedTrigger = React29.cloneElement(trigger, {
8807
8914
  ...triggerProps,
8808
- ref: mergeRefs(childRef, (node) => {
8809
- triggerRef.current = node;
8810
- }),
8915
+ ref: setTriggerNode,
8811
8916
  "aria-haspopup": "menu",
8812
8917
  "aria-expanded": open,
8813
- onKeyDown: chainEventHandlers((e) => {
8814
- triggerRef.current = e.currentTarget;
8815
- if (!disabled) {
8816
- if (e.key === "ArrowDown") {
8817
- e.preventDefault();
8818
- setOpen(true);
8819
- requestAnimationFrame(() => focusMenuItem(0));
8820
- } else if (e.key === "ArrowUp") {
8821
- e.preventDefault();
8822
- setOpen(true);
8823
- requestAnimationFrame(() => {
8824
- const enabled = getEnabledMenuItems();
8825
- focusMenuItem(enabled.length - 1);
8826
- });
8827
- } else if (e.key === "Escape") {
8828
- e.preventDefault();
8829
- setOpen(false);
8830
- }
8831
- }
8832
- }, triggerProps.onKeyDown),
8833
- onFocus: chainEventHandlers((e) => {
8834
- triggerRef.current = e.currentTarget;
8835
- }, triggerProps.onFocus)
8918
+ onKeyDown: handleTriggerKeyDown,
8919
+ onClick: handleTriggerClick,
8920
+ onMouseEnter: handleTriggerMouseEnter,
8921
+ onMouseLeave: handleTriggerMouseLeave
8836
8922
  });
8837
8923
  return /* @__PURE__ */ jsx32(
8838
8924
  Popover,
@@ -8930,6 +9016,7 @@ var DropdownMenuSub = ({ label, icon: Icon, disabled, borderMode, children }) =>
8930
9016
  }
8931
9017
  ),
8932
9018
  placement: "right",
9019
+ openOnHover: true,
8933
9020
  children
8934
9021
  }
8935
9022
  );
@@ -31418,6 +31505,199 @@ var LetterSpacing = Extension9.create({
31418
31505
  });
31419
31506
  var letter_spacing_default = LetterSpacing;
31420
31507
 
31508
+ // src/components/UEditor/indent.ts
31509
+ import { Extension as Extension10 } from "@tiptap/core";
31510
+ import { isInTable } from "@tiptap/pm/tables";
31511
+ var DEFAULT_MAX_LEVEL = 6;
31512
+ var DEFAULT_MIN_LEVEL = 0;
31513
+ var DEFAULT_STEP_REM = 2;
31514
+ var INLINE_TAB_SPACES = "\xA0".repeat(4);
31515
+ var LIST_ITEM_TYPES = /* @__PURE__ */ new Set(["listItem", "taskItem"]);
31516
+ var TABLE_CELL_TYPES = /* @__PURE__ */ new Set(["tableCell", "tableHeader"]);
31517
+ function clampIndentLevel(value, minLevel, maxLevel) {
31518
+ const numericValue = typeof value === "number" ? value : Number.parseInt(String(value ?? ""), 10);
31519
+ if (!Number.isFinite(numericValue)) return minLevel;
31520
+ return Math.min(maxLevel, Math.max(minLevel, Math.round(numericValue)));
31521
+ }
31522
+ function parseIndentLevel(element, options) {
31523
+ const dataIndent = element.getAttribute("data-indent");
31524
+ if (dataIndent !== null) {
31525
+ return clampIndentLevel(dataIndent, options.minLevel, options.maxLevel);
31526
+ }
31527
+ const marginLeft = element.style.marginLeft.trim();
31528
+ const match = marginLeft.match(/^(-?\d+(?:\.\d+)?)(rem|em|px)$/i);
31529
+ if (!match) return options.minLevel;
31530
+ const value = Number.parseFloat(match[1] ?? "0");
31531
+ const unit = match[2]?.toLowerCase();
31532
+ const remValue = unit === "px" ? value / 16 : value;
31533
+ return clampIndentLevel(remValue / options.stepRem, options.minLevel, options.maxLevel);
31534
+ }
31535
+ function getNodePos($pos, depth) {
31536
+ return depth > 0 ? $pos.before(depth) : 0;
31537
+ }
31538
+ function getIndentTargetAt($pos, indentTypes) {
31539
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
31540
+ const nodeName = $pos.node(depth).type.name;
31541
+ if (LIST_ITEM_TYPES.has(nodeName) || TABLE_CELL_TYPES.has(nodeName)) return null;
31542
+ }
31543
+ if (indentTypes.has("blockquote")) {
31544
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
31545
+ const node = $pos.node(depth);
31546
+ if (node.type.name === "blockquote") {
31547
+ return { node, pos: getNodePos($pos, depth) };
31548
+ }
31549
+ }
31550
+ }
31551
+ for (let depth = $pos.depth; depth > 0; depth -= 1) {
31552
+ const node = $pos.node(depth);
31553
+ if (indentTypes.has(node.type.name)) {
31554
+ return { node, pos: getNodePos($pos, depth) };
31555
+ }
31556
+ }
31557
+ return null;
31558
+ }
31559
+ function getIndentTargets(state, types) {
31560
+ if (isInTable(state)) return [];
31561
+ const indentTypes = new Set(types);
31562
+ const targets = /* @__PURE__ */ new Map();
31563
+ const addTarget = (target) => {
31564
+ if (target) targets.set(target.pos, target);
31565
+ };
31566
+ addTarget(getIndentTargetAt(state.selection.$from, indentTypes));
31567
+ addTarget(getIndentTargetAt(state.selection.$to, indentTypes));
31568
+ if (!state.selection.empty) {
31569
+ state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos) => {
31570
+ if (!indentTypes.has(node.type.name)) return true;
31571
+ const resolvedPos = state.doc.resolve(Math.min(pos + 1, state.doc.content.size));
31572
+ addTarget(getIndentTargetAt(resolvedPos, indentTypes));
31573
+ return node.type.name !== "blockquote";
31574
+ });
31575
+ }
31576
+ return Array.from(targets.values()).sort((a, b) => a.pos - b.pos);
31577
+ }
31578
+ function updateBlockIndent({
31579
+ state,
31580
+ dispatch,
31581
+ options,
31582
+ delta
31583
+ }) {
31584
+ const targets = getIndentTargets(state, options.types);
31585
+ let transaction = state.tr;
31586
+ let changed = false;
31587
+ for (const target of targets) {
31588
+ const currentLevel = clampIndentLevel(target.node.attrs.indent, options.minLevel, options.maxLevel);
31589
+ const nextLevel = clampIndentLevel(currentLevel + delta, options.minLevel, options.maxLevel);
31590
+ if (nextLevel === currentLevel) continue;
31591
+ transaction = transaction.setNodeMarkup(target.pos, void 0, {
31592
+ ...target.node.attrs,
31593
+ indent: nextLevel
31594
+ });
31595
+ changed = true;
31596
+ }
31597
+ if (changed && dispatch) dispatch(transaction.scrollIntoView());
31598
+ return changed;
31599
+ }
31600
+ function insertTabAtCursor(state, dispatch) {
31601
+ if (!state.selection.empty) return false;
31602
+ if (dispatch) {
31603
+ dispatch(state.tr.insertText(INLINE_TAB_SPACES, state.selection.from).scrollIntoView());
31604
+ }
31605
+ return true;
31606
+ }
31607
+ function removeTabBeforeCursor(state, dispatch) {
31608
+ if (!state.selection.empty || state.selection.$from.parentOffset <= 0) return false;
31609
+ const cursorPos = state.selection.from;
31610
+ const tabStartPos = cursorPos - INLINE_TAB_SPACES.length;
31611
+ if (tabStartPos < 0 || state.doc.textBetween(tabStartPos, cursorPos) !== INLINE_TAB_SPACES) return false;
31612
+ if (dispatch) {
31613
+ dispatch(state.tr.delete(tabStartPos, cursorPos).scrollIntoView());
31614
+ }
31615
+ return true;
31616
+ }
31617
+ var Indent = Extension10.create({
31618
+ name: "indent",
31619
+ addOptions() {
31620
+ return {
31621
+ maxLevel: DEFAULT_MAX_LEVEL,
31622
+ minLevel: DEFAULT_MIN_LEVEL,
31623
+ stepRem: DEFAULT_STEP_REM,
31624
+ types: ["paragraph", "blockquote"]
31625
+ };
31626
+ },
31627
+ addGlobalAttributes() {
31628
+ return [
31629
+ {
31630
+ types: this.options.types,
31631
+ attributes: {
31632
+ indent: {
31633
+ default: this.options.minLevel,
31634
+ parseHTML: (element) => parseIndentLevel(element, this.options),
31635
+ renderHTML: (attributes) => {
31636
+ const level = clampIndentLevel(attributes.indent, this.options.minLevel, this.options.maxLevel);
31637
+ if (level <= this.options.minLevel) return {};
31638
+ return {
31639
+ "data-indent": String(level),
31640
+ style: `margin-left: ${level * this.options.stepRem}rem`
31641
+ };
31642
+ }
31643
+ }
31644
+ }
31645
+ }
31646
+ ];
31647
+ },
31648
+ addCommands() {
31649
+ return {
31650
+ increaseIndent: () => ({ editor, commands, state, dispatch }) => {
31651
+ if (editor.isActive("taskItem")) return commands.sinkListItem("taskItem");
31652
+ if (editor.isActive("listItem")) return commands.sinkListItem("listItem");
31653
+ return updateBlockIndent({
31654
+ state,
31655
+ dispatch,
31656
+ options: this.options,
31657
+ delta: 1
31658
+ });
31659
+ },
31660
+ decreaseIndent: () => ({ editor, commands, state, dispatch }) => {
31661
+ if (editor.isActive("taskItem")) return commands.liftListItem("taskItem");
31662
+ if (editor.isActive("listItem")) return commands.liftListItem("listItem");
31663
+ return updateBlockIndent({
31664
+ state,
31665
+ dispatch,
31666
+ options: this.options,
31667
+ delta: -1
31668
+ });
31669
+ }
31670
+ };
31671
+ },
31672
+ addKeyboardShortcuts() {
31673
+ const handleBlockIndent = (delta) => {
31674
+ const { state } = this.editor;
31675
+ const hasBlockTarget = getIndentTargets(state, this.options.types).length > 0;
31676
+ if (!hasBlockTarget) {
31677
+ return delta > 0 ? this.editor.commands.increaseIndent() : this.editor.commands.decreaseIndent();
31678
+ }
31679
+ if (state.selection.empty && state.selection.$from.parentOffset > 0) {
31680
+ if (delta > 0) {
31681
+ return insertTabAtCursor(state, (transaction) => this.editor.view.dispatch(transaction));
31682
+ }
31683
+ removeTabBeforeCursor(state, (transaction) => this.editor.view.dispatch(transaction));
31684
+ return true;
31685
+ }
31686
+ if (delta > 0) {
31687
+ this.editor.commands.increaseIndent();
31688
+ } else {
31689
+ this.editor.commands.decreaseIndent();
31690
+ }
31691
+ return true;
31692
+ };
31693
+ return {
31694
+ Tab: () => handleBlockIndent(1),
31695
+ "Shift-Tab": () => handleBlockIndent(-1)
31696
+ };
31697
+ }
31698
+ });
31699
+ var indent_default = Indent;
31700
+
31421
31701
  // src/components/UEditor/table-align.ts
31422
31702
  import { Table as Table3 } from "@tiptap/extension-table";
31423
31703
  import { Plugin as Plugin5 } from "@tiptap/pm/state";
@@ -32438,6 +32718,7 @@ function buildUEditorExtensions({
32438
32718
  font_size_default,
32439
32719
  line_height_default,
32440
32720
  letter_spacing_default,
32721
+ indent_default,
32441
32722
  Color,
32442
32723
  Highlight.configure({
32443
32724
  multicolor: true
@@ -32513,12 +32794,13 @@ import {
32513
32794
  ArrowLeft,
32514
32795
  ArrowRight,
32515
32796
  ArrowUp,
32516
- ChevronDown as ChevronDown8,
32517
32797
  CircleCheckBig as CircleCheckBig2,
32518
32798
  FileCode as FileCode3,
32519
32799
  Heading1 as Heading1Icon,
32520
32800
  Heading2 as Heading2Icon,
32521
32801
  Heading3 as Heading3Icon,
32802
+ IndentDecrease,
32803
+ IndentIncrease,
32522
32804
  Link as LinkIcon,
32523
32805
  List as ListIcon,
32524
32806
  ListOrdered as ListOrderedIcon,
@@ -32526,7 +32808,6 @@ import {
32526
32808
  Quote as QuoteIcon,
32527
32809
  RotateCcw as RotateCcw2,
32528
32810
  SquareCheckBig,
32529
- Table as TableIcon,
32530
32811
  TableCellsMerge,
32531
32812
  Trash2 as Trash22,
32532
32813
  Type as Type2,
@@ -33572,6 +33853,77 @@ function getTableAnchorPos(editor) {
33572
33853
  const firstCell = tables[0]?.querySelector("th,td");
33573
33854
  return firstCell instanceof HTMLTableCellElement ? editor.view.posAtDOM(firstCell, 0) + 1 : null;
33574
33855
  }
33856
+ var EDITOR_UI_ACTIVE_MARKS = [
33857
+ "blockquote",
33858
+ "bold",
33859
+ "bulletList",
33860
+ "code",
33861
+ "codeBlock",
33862
+ "formCheckbox",
33863
+ "highlight",
33864
+ "image",
33865
+ "italic",
33866
+ "link",
33867
+ "orderedList",
33868
+ "paragraph",
33869
+ "strike",
33870
+ "subscript",
33871
+ "superscript",
33872
+ "taskList",
33873
+ "underline"
33874
+ ];
33875
+ function getEditorUiRenderState(editor) {
33876
+ const textStyle = editor.getAttributes("textStyle");
33877
+ const highlight = editor.getAttributes("highlight");
33878
+ const image = editor.getAttributes("image");
33879
+ const link = editor.getAttributes("link");
33880
+ const tableCell = editor.getAttributes("tableCell");
33881
+ const tableHeader = editor.getAttributes("tableHeader");
33882
+ const hasTableContext = getTableAnchorPos(editor) !== null;
33883
+ const can = editor.can();
33884
+ return {
33885
+ active: EDITOR_UI_ACTIVE_MARKS.map((name) => editor.isActive(name)),
33886
+ alignment: ["left", "center", "right", "justify"].map((textAlign) => editor.isActive({ textAlign })),
33887
+ heading: [1, 2, 3].map((level) => editor.isActive("heading", { level })),
33888
+ textStyle: {
33889
+ color: textStyle.color ?? null,
33890
+ fontFamily: textStyle.fontFamily ?? null,
33891
+ fontSize: textStyle.fontSize ?? null,
33892
+ letterSpacing: textStyle.letterSpacing ?? null,
33893
+ lineHeight: textStyle.lineHeight ?? null
33894
+ },
33895
+ highlightColor: highlight.color ?? null,
33896
+ image: {
33897
+ imageLayout: image.imageLayout ?? null,
33898
+ imageWidthPreset: image.imageWidthPreset ?? null
33899
+ },
33900
+ linkHref: link.href ?? null,
33901
+ tableCell: {
33902
+ backgroundColor: tableCell.backgroundColor ?? tableHeader.backgroundColor ?? null,
33903
+ borderColor: tableCell.borderColor ?? tableHeader.borderColor ?? null,
33904
+ borderStyle: tableCell.borderStyle ?? tableHeader.borderStyle ?? null,
33905
+ borderWidth: tableCell.borderWidth ?? tableHeader.borderWidth ?? null,
33906
+ formula: tableCell.formula ?? tableHeader.formula ?? null,
33907
+ numberFormat: tableCell.numberFormat ?? tableHeader.numberFormat ?? null,
33908
+ textDirection: tableCell.textDirection ?? tableHeader.textDirection ?? null,
33909
+ verticalAlign: tableCell.verticalAlign ?? tableHeader.verticalAlign ?? null
33910
+ },
33911
+ can: {
33912
+ addColumnAfter: hasTableContext && can.addColumnAfter(),
33913
+ addColumnBefore: hasTableContext && can.addColumnBefore(),
33914
+ addRowAfter: hasTableContext && can.addRowAfter(),
33915
+ addRowBefore: hasTableContext && can.addRowBefore(),
33916
+ decreaseIndent: can.decreaseIndent(),
33917
+ increaseIndent: can.increaseIndent(),
33918
+ mergeCells: hasTableContext && can.mergeCells(),
33919
+ redo: can.redo(),
33920
+ splitCell: hasTableContext && can.splitCell(),
33921
+ undo: can.undo()
33922
+ },
33923
+ hasTableContext,
33924
+ isEmpty: editor.isEmpty
33925
+ };
33926
+ }
33575
33927
  function fileToDataUrl2(file) {
33576
33928
  return new Promise((resolve, reject) => {
33577
33929
  const reader = new FileReader();
@@ -33597,10 +33949,10 @@ var ToolbarButton = React84.forwardRef(({ onClick, onMouseDown, active, disabled
33597
33949
  onClick,
33598
33950
  disabled,
33599
33951
  className: cn(
33600
- "flex h-8 w-8 shrink-0 items-center justify-center rounded-md transition-colors duration-150 cursor-pointer",
33601
- "gap-0.5 [&_svg+svg]:-ml-1",
33952
+ "flex h-7 w-7 shrink-0 cursor-pointer items-center justify-center rounded-md transition-colors duration-150",
33953
+ "gap-0.5 [&>svg]:h-3.5 [&>svg]:w-3.5 [&>svg]:shrink-0",
33602
33954
  "hover:bg-accent",
33603
- "focus:outline-none focus:ring-2 focus:ring-primary/20",
33955
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/20",
33604
33956
  "disabled:opacity-40 disabled:cursor-not-allowed",
33605
33957
  active ? "bg-primary/10 text-primary shadow-sm" : "text-[#7B8184] hover:text-foreground dark:text-muted-foreground",
33606
33958
  className
@@ -33614,7 +33966,7 @@ var ToolbarButton = React84.forwardRef(({ onClick, onMouseDown, active, disabled
33614
33966
  return button;
33615
33967
  });
33616
33968
  ToolbarButton.displayName = "ToolbarButton";
33617
- var ToolbarDivider = () => /* @__PURE__ */ jsx93("div", { "aria-hidden": "true", className: "mx-2 h-9 w-px shrink-0 bg-[rgba(123,129,132,0.24)]" });
33969
+ var ToolbarDivider = () => /* @__PURE__ */ jsx93("div", { "aria-hidden": "true", className: "mx-1.5 h-7 w-px shrink-0 bg-[rgba(123,129,132,0.24)]" });
33618
33970
  var TableInsertGrid = ({
33619
33971
  insertLabel,
33620
33972
  previewTemplate,
@@ -33625,7 +33977,7 @@ var TableInsertGrid = ({
33625
33977
  const maxCols = 8;
33626
33978
  return /* @__PURE__ */ jsxs75("div", { className: "mb-2 rounded-xl border border-border/60 bg-muted/20 p-2", children: [
33627
33979
  /* @__PURE__ */ jsx93("div", { className: "mb-2 text-sm font-medium text-foreground", children: formatTableInsertLabel(previewTemplate, selection.rows, selection.cols) }),
33628
- /* @__PURE__ */ jsx93("div", { className: "grid grid-cols-8 gap-1", onMouseLeave: () => setSelection((prev) => prev), children: Array.from({ length: maxRows }).map(
33980
+ /* @__PURE__ */ jsx93("div", { className: "grid grid-cols-8 gap-1", children: Array.from({ length: maxRows }).map(
33629
33981
  (_, rowIndex) => Array.from({ length: maxCols }).map((__, colIndex) => {
33630
33982
  const rows = rowIndex + 1;
33631
33983
  const cols = colIndex + 1;
@@ -33673,15 +34025,14 @@ var EditorToolbar = ({
33673
34025
  letterSpacings
33674
34026
  }) => {
33675
34027
  const t = useSmartTranslations("UEditor");
33676
- useEditorState({
34028
+ const editorUiState = useEditorState({
33677
34029
  editor,
33678
- selector: ({ transactionNumber }) => transactionNumber
34030
+ selector: ({ editor: currentEditor }) => getEditorUiRenderState(currentEditor)
33679
34031
  });
33680
34032
  const { textColors, highlightColors } = useEditorColors();
33681
34033
  const [showImageInput, setShowImageInput] = useState50(false);
33682
34034
  const [showLinkInput, setShowLinkInput] = useState50(false);
33683
34035
  const [isTableMenuOpen, setIsTableMenuOpen] = useState50(false);
33684
- const [preservedTableAnchorPos, setPreservedTableAnchorPos] = useState50(null);
33685
34036
  const fileInputRef = useRef34(null);
33686
34037
  const [isUploadingImage, setIsUploadingImage] = useState50(false);
33687
34038
  const [imageUploadError, setImageUploadError] = useState50(null);
@@ -33689,14 +34040,11 @@ var EditorToolbar = ({
33689
34040
  const imageAttrs = editor.getAttributes("image");
33690
34041
  const tableAnchorPos = getTableAnchorPos(editor);
33691
34042
  const tableInfo = tableAnchorPos == null ? null : findTableNodeInfoFromState(editor.state, tableAnchorPos);
33692
- const tableAttrs = tableInfo?.node.attrs ?? editor.getAttributes("table");
33693
34043
  const textStyleAttrs = editor.getAttributes("textStyle");
33694
34044
  const imageLayout = imageAttrs.imageLayout === "left" || imageAttrs.imageLayout === "right" ? imageAttrs.imageLayout : "block";
33695
34045
  const imageWidthPreset = imageAttrs.imageWidthPreset === "sm" || imageAttrs.imageWidthPreset === "md" || imageAttrs.imageWidthPreset === "lg" ? imageAttrs.imageWidthPreset : null;
33696
- const tableAlignAttr = tableAttrs.tableAlign ?? tableAttrs.textAlign;
33697
- const currentTableAlign = tableAlignAttr === "center" || tableAlignAttr === "right" ? tableAlignAttr : "left";
33698
34046
  const isTableSelected = tableInfo !== null;
33699
- const hasTableContext = isTableSelected || preservedTableAnchorPos !== null;
34047
+ const hasTableContext = isTableSelected;
33700
34048
  const canMergeCells = hasTableContext && editor.can().mergeCells();
33701
34049
  const canSplitCell = hasTableContext && editor.can().splitCell();
33702
34050
  const currentCellVerticalAlign = normalizeStyleValue(editor.getAttributes("tableCell").verticalAlign || editor.getAttributes("tableHeader").verticalAlign) || "";
@@ -33722,7 +34070,6 @@ var EditorToolbar = ({
33722
34070
  const displayedFontFamilyValue = currentFontFamily || defaultFontFamilyValue;
33723
34071
  const displayedFontSizeLabel = currentFontSize ? currentFontSizeLabel : "13";
33724
34072
  const activeFontSize = currentFontSize || "13px";
33725
- const tableCommandAnchorPos = preservedTableAnchorPos ?? tableAnchorPos ?? void 0;
33726
34073
  const isMedium = variant === "medium";
33727
34074
  const isMediumFull = variant === "medium-full";
33728
34075
  const isFull = variant === "default" || variant === "full" || variant === "notion" || !variant;
@@ -33762,14 +34109,29 @@ var EditorToolbar = ({
33762
34109
  children: /* @__PURE__ */ jsx93(FigmaListIcon, { className: "h-4 w-4" })
33763
34110
  }
33764
34111
  ),
34112
+ /* @__PURE__ */ jsx93(
34113
+ ToolbarButton,
34114
+ {
34115
+ onClick: () => editor.chain().focus().decreaseIndent().run(),
34116
+ disabled: !editorUiState.can.decreaseIndent,
34117
+ title: t("toolbar.decreaseIndent"),
34118
+ children: /* @__PURE__ */ jsx93(IndentDecrease, { className: "h-4 w-4" })
34119
+ }
34120
+ ),
34121
+ /* @__PURE__ */ jsx93(
34122
+ ToolbarButton,
34123
+ {
34124
+ onClick: () => editor.chain().focus().increaseIndent().run(),
34125
+ disabled: !editorUiState.can.increaseIndent,
34126
+ title: t("toolbar.increaseIndent"),
34127
+ children: /* @__PURE__ */ jsx93(IndentIncrease, { className: "h-4 w-4" })
34128
+ }
34129
+ ),
33765
34130
  /* @__PURE__ */ jsxs75(
33766
34131
  DropdownMenu,
33767
34132
  {
33768
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
33769
- }, active: editor.isActive("formCheckbox"), title: t("slashCommand.formCheckbox"), children: [
33770
- /* @__PURE__ */ jsx93(SquareCheckBig, { className: "w-4 h-4" }),
33771
- /* @__PURE__ */ jsx93(ChevronDown8, { className: "w-3 h-3" })
33772
- ] }),
34133
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34134
+ }, active: editor.isActive("formCheckbox"), title: t("slashCommand.formCheckbox"), children: /* @__PURE__ */ jsx93(SquareCheckBig, { className: "w-4 h-4" }) }),
33773
34135
  children: [
33774
34136
  /* @__PURE__ */ jsx93(
33775
34137
  DropdownMenuItem,
@@ -33836,7 +34198,7 @@ var EditorToolbar = ({
33836
34198
  "div",
33837
34199
  {
33838
34200
  role: "toolbar",
33839
- className: "flex min-h-15 flex-nowrap items-center gap-1 overflow-x-auto border-b border-[rgba(196,197,213,0.6)] bg-[#F4F4F4] px-3 py-3 dark:bg-muted/60",
34201
+ className: "flex min-h-12 flex-nowrap items-center gap-0.5 overflow-x-auto border-b border-[rgba(196,197,213,0.6)] bg-[#F4F4F4] px-2 py-2 dark:bg-muted/60",
33840
34202
  children: [
33841
34203
  isFull && /* @__PURE__ */ jsx93(
33842
34204
  DropdownMenu,
@@ -33847,7 +34209,7 @@ var EditorToolbar = ({
33847
34209
  onClick: () => {
33848
34210
  },
33849
34211
  title: t("toolbar.fontFamily"),
33850
- className: "h-9 w-50 max-w-50 justify-between gap-3 rounded-lg border border-[rgba(196,197,213,0.6)] bg-white px-3 text-[#404040] shadow-[0_1px_2px_rgba(0,0,0,0.07)] hover:bg-white hover:text-[#404040] dark:bg-background dark:text-foreground",
34212
+ className: "h-8 w-44 max-w-44 justify-between gap-2 border border-[rgba(196,197,213,0.6)] bg-white px-2.5 text-[#404040] shadow-[0_1px_2px_rgba(0,0,0,0.07)] hover:bg-white hover:text-[#404040] dark:bg-background dark:text-foreground",
33851
34213
  children: [
33852
34214
  /* @__PURE__ */ jsx93("span", { className: "min-w-0 flex-1 truncate text-left text-sm font-normal", style: { fontFamily: displayedFontFamilyValue || void 0 }, children: displayedFontFamilyLabel }),
33853
34215
  /* @__PURE__ */ jsx93(FigmaChevronDownIcon, { className: "h-3 w-3 shrink-0 text-[#7B8184]" })
@@ -33876,7 +34238,7 @@ var EditorToolbar = ({
33876
34238
  onClick: () => {
33877
34239
  },
33878
34240
  title: t("toolbar.fontSize"),
33879
- className: "h-9 w-20 justify-between gap-3 rounded-lg border border-[rgba(196,197,213,0.6)] bg-white px-3 text-[#404040] shadow-[0_1px_2px_rgba(0,0,0,0.07)] hover:bg-white hover:text-[#404040] dark:bg-background dark:text-foreground",
34241
+ className: "h-8 w-16 justify-between gap-2 border border-[rgba(196,197,213,0.6)] bg-white px-2.5 text-[#404040] shadow-[0_1px_2px_rgba(0,0,0,0.07)] hover:bg-white hover:text-[#404040] dark:bg-background dark:text-foreground",
33880
34242
  children: [
33881
34243
  /* @__PURE__ */ jsx93("span", { className: "text-sm font-normal leading-none", children: displayedFontSizeLabel }),
33882
34244
  /* @__PURE__ */ jsx93(FigmaChevronDownIcon, { className: "h-3 w-3 shrink-0 text-[#7B8184]" })
@@ -33899,11 +34261,8 @@ var EditorToolbar = ({
33899
34261
  DropdownMenu,
33900
34262
  {
33901
34263
  contentClassName: "p-1",
33902
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
33903
- }, title: t("toolbar.textStyle"), className: "px-1.5 w-auto gap-0.5", children: [
33904
- /* @__PURE__ */ jsx93(FigmaTextStyleIcon, { className: "h-4 w-4" }),
33905
- /* @__PURE__ */ jsx93(FigmaChevronDownIcon, { className: "h-2.5 w-2.5" })
33906
- ] }),
34264
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34265
+ }, title: t("toolbar.textStyle"), className: "px-1.5 w-auto gap-0.5", children: /* @__PURE__ */ jsx93(FigmaTextStyleIcon, { className: "h-4 w-4" }) }),
33907
34266
  children: [
33908
34267
  /* @__PURE__ */ jsx93(
33909
34268
  DropdownMenuItem,
@@ -34082,11 +34441,8 @@ var EditorToolbar = ({
34082
34441
  /* @__PURE__ */ jsx93(
34083
34442
  DropdownMenu,
34084
34443
  {
34085
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
34086
- }, title: t("colors.textColor"), children: [
34087
- /* @__PURE__ */ jsx93(TextColorIcon, { color: currentTextColor }),
34088
- /* @__PURE__ */ jsx93(FigmaChevronDownIcon, { className: "h-2.5 w-2.5" })
34089
- ] }),
34444
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34445
+ }, title: t("colors.textColor"), children: /* @__PURE__ */ jsx93(TextColorIcon, { color: currentTextColor }) }),
34090
34446
  children: /* @__PURE__ */ jsx93(
34091
34447
  EditorColorPalette,
34092
34448
  {
@@ -34107,11 +34463,8 @@ var EditorToolbar = ({
34107
34463
  /* @__PURE__ */ jsx93(
34108
34464
  DropdownMenu,
34109
34465
  {
34110
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
34111
- }, active: editor.isActive("highlight"), title: t("colors.highlight"), children: [
34112
- /* @__PURE__ */ jsx93(HighlightColorIcon, { color: currentHighlightColor }),
34113
- /* @__PURE__ */ jsx93(FigmaChevronDownIcon, { className: "h-2.5 w-2.5" })
34114
- ] }),
34466
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34467
+ }, active: editor.isActive("highlight"), title: t("colors.highlight"), children: /* @__PURE__ */ jsx93(HighlightColorIcon, { color: currentHighlightColor }) }),
34115
34468
  children: /* @__PURE__ */ jsx93(
34116
34469
  EditorColorPalette,
34117
34470
  {
@@ -34129,35 +34482,13 @@ var EditorToolbar = ({
34129
34482
  )
34130
34483
  }
34131
34484
  ),
34132
- (isMediumFull || isFull) && /* @__PURE__ */ jsxs75(Fragment29, { children: [
34133
- /* @__PURE__ */ jsx93(ToolbarDivider, {}),
34134
- /* @__PURE__ */ jsx93(
34135
- DropdownMenu,
34136
- {
34137
- contentClassName: "p-0 overflow-hidden",
34138
- trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34139
- }, title: t("toolbar.emoji"), children: /* @__PURE__ */ jsx93(FigmaSmileIcon, { className: "h-4 w-4" }) }),
34140
- children: /* @__PURE__ */ jsx93(
34141
- EmojiPicker2,
34142
- {
34143
- onSelect: (emoji) => {
34144
- editor.chain().focus().insertContent(emoji).run();
34145
- }
34146
- }
34147
- )
34148
- }
34149
- )
34150
- ] }),
34151
34485
  (isMediumFull || isFull) && /* @__PURE__ */ jsxs75(Fragment29, { children: [
34152
34486
  /* @__PURE__ */ jsx93(ToolbarDivider, {}),
34153
34487
  /* @__PURE__ */ jsxs75(
34154
34488
  DropdownMenu,
34155
34489
  {
34156
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
34157
- }, title: t("toolbar.alignment"), children: [
34158
- /* @__PURE__ */ jsx93(FigmaAlignLeftIcon, { className: "h-4 w-4" }),
34159
- /* @__PURE__ */ jsx93(FigmaChevronDownIcon, { className: "h-2.5 w-2.5" })
34160
- ] }),
34490
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34491
+ }, title: t("toolbar.alignment"), children: /* @__PURE__ */ jsx93(FigmaAlignLeftIcon, { className: "h-4 w-4" }) }),
34161
34492
  children: [
34162
34493
  /* @__PURE__ */ jsx93(
34163
34494
  DropdownMenuItem,
@@ -34231,11 +34562,8 @@ var EditorToolbar = ({
34231
34562
  hasTableContext && /* @__PURE__ */ jsxs75(
34232
34563
  DropdownMenu,
34233
34564
  {
34234
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
34235
- }, title: t("tableMenu.textDirection"), children: [
34236
- currentCellTextDirection === "vertical" ? /* @__PURE__ */ jsx93(ArrowDown, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx93(ArrowRight, { className: "w-4 h-4" }),
34237
- /* @__PURE__ */ jsx93(ChevronDown8, { className: "w-3 h-3" })
34238
- ] }),
34565
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34566
+ }, title: t("tableMenu.textDirection"), children: currentCellTextDirection === "vertical" ? /* @__PURE__ */ jsx93(ArrowDown, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx93(ArrowRight, { className: "w-4 h-4" }) }),
34239
34567
  children: [
34240
34568
  /* @__PURE__ */ jsx93(
34241
34569
  DropdownMenuItem,
@@ -34263,11 +34591,8 @@ var EditorToolbar = ({
34263
34591
  /* @__PURE__ */ jsxs75(
34264
34592
  DropdownMenu,
34265
34593
  {
34266
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
34267
- }, title: t("toolbar.bulletList"), children: [
34268
- /* @__PURE__ */ jsx93(FigmaListIcon, { className: "h-4 w-4" }),
34269
- /* @__PURE__ */ jsx93(FigmaChevronDownIcon, { className: "h-2.5 w-2.5" })
34270
- ] }),
34594
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34595
+ }, title: t("toolbar.bulletList"), children: /* @__PURE__ */ jsx93(FigmaListIcon, { className: "h-4 w-4" }) }),
34271
34596
  children: [
34272
34597
  /* @__PURE__ */ jsx93(
34273
34598
  DropdownMenuItem,
@@ -34302,14 +34627,29 @@ var EditorToolbar = ({
34302
34627
  ]
34303
34628
  }
34304
34629
  ),
34630
+ /* @__PURE__ */ jsx93(
34631
+ ToolbarButton,
34632
+ {
34633
+ onClick: () => editor.chain().focus().decreaseIndent().run(),
34634
+ disabled: !editorUiState.can.decreaseIndent,
34635
+ title: t("toolbar.decreaseIndent"),
34636
+ children: /* @__PURE__ */ jsx93(IndentDecrease, { className: "h-4 w-4" })
34637
+ }
34638
+ ),
34639
+ /* @__PURE__ */ jsx93(
34640
+ ToolbarButton,
34641
+ {
34642
+ onClick: () => editor.chain().focus().increaseIndent().run(),
34643
+ disabled: !editorUiState.can.increaseIndent,
34644
+ title: t("toolbar.increaseIndent"),
34645
+ children: /* @__PURE__ */ jsx93(IndentIncrease, { className: "h-4 w-4" })
34646
+ }
34647
+ ),
34305
34648
  /* @__PURE__ */ jsxs75(
34306
34649
  DropdownMenu,
34307
34650
  {
34308
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
34309
- }, active: editor.isActive("formCheckbox"), title: t("slashCommand.formCheckbox"), children: [
34310
- /* @__PURE__ */ jsx93(SquareCheckBig, { className: "w-4 h-4" }),
34311
- /* @__PURE__ */ jsx93(ChevronDown8, { className: "w-3 h-3" })
34312
- ] }),
34651
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34652
+ }, active: editor.isActive("formCheckbox"), title: t("slashCommand.formCheckbox"), children: /* @__PURE__ */ jsx93(SquareCheckBig, { className: "w-4 h-4" }) }),
34313
34653
  children: [
34314
34654
  /* @__PURE__ */ jsx93(
34315
34655
  DropdownMenuItem,
@@ -34334,11 +34674,8 @@ var EditorToolbar = ({
34334
34674
  isFull && /* @__PURE__ */ jsxs75(
34335
34675
  DropdownMenu,
34336
34676
  {
34337
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
34338
- }, title: t("toolbar.quote"), children: [
34339
- /* @__PURE__ */ jsx93(FigmaQuoteIcon, { className: "h-4 w-4" }),
34340
- /* @__PURE__ */ jsx93(FigmaChevronDownIcon, { className: "h-2.5 w-2.5" })
34341
- ] }),
34677
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34678
+ }, title: t("toolbar.quote"), children: /* @__PURE__ */ jsx93(FigmaQuoteIcon, { className: "h-4 w-4" }) }),
34342
34679
  children: [
34343
34680
  /* @__PURE__ */ jsx93(
34344
34681
  DropdownMenuItem,
@@ -34366,11 +34703,8 @@ var EditorToolbar = ({
34366
34703
  (isMediumFull || isFull) && /* @__PURE__ */ jsx93(
34367
34704
  DropdownMenu,
34368
34705
  {
34369
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
34370
- }, title: t("toolbar.image"), children: [
34371
- /* @__PURE__ */ jsx93(FigmaImageIcon, { className: "h-4 w-4" }),
34372
- /* @__PURE__ */ jsx93(FigmaChevronDownIcon, { className: "h-2.5 w-2.5" })
34373
- ] }),
34706
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34707
+ }, title: t("toolbar.image"), children: /* @__PURE__ */ jsx93(FigmaImageIcon, { className: "h-4 w-4" }) }),
34374
34708
  children: showImageInput ? /* @__PURE__ */ jsx93(
34375
34709
  ImageInput,
34376
34710
  {
@@ -34490,149 +34824,25 @@ var EditorToolbar = ({
34490
34824
  ] })
34491
34825
  }
34492
34826
  ),
34493
- (isMediumFull || isFull) && /* @__PURE__ */ jsxs75(
34827
+ (isMediumFull || isFull) && /* @__PURE__ */ jsx93(
34494
34828
  DropdownMenu,
34495
34829
  {
34496
34830
  isOpen: isTableMenuOpen,
34497
- onOpenChange: (open) => {
34498
- setIsTableMenuOpen(open);
34499
- setPreservedTableAnchorPos(open ? getTableAnchorPos(editor) : null);
34500
- },
34501
- trigger: /* @__PURE__ */ jsxs75(ToolbarButton, { onClick: () => {
34502
- }, title: t("toolbar.table"), children: [
34503
- /* @__PURE__ */ jsx93(FigmaTableIcon, { className: "h-4 w-4" }),
34504
- /* @__PURE__ */ jsx93(FigmaChevronDownIcon, { className: "h-2.5 w-2.5" })
34505
- ] }),
34831
+ onOpenChange: setIsTableMenuOpen,
34832
+ trigger: /* @__PURE__ */ jsx93(ToolbarButton, { onClick: () => {
34833
+ }, title: t("toolbar.table"), children: /* @__PURE__ */ jsx93(FigmaTableIcon, { className: "h-4 w-4" }) }),
34506
34834
  contentClassName: "p-2 min-w-56",
34507
- children: [
34508
- /* @__PURE__ */ jsx93(
34509
- TableInsertGrid,
34510
- {
34511
- insertLabel: t("tableMenu.insertTable"),
34512
- previewTemplate: t("tableMenu.gridPreview"),
34513
- onInsert: (rows, cols) => {
34514
- editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
34515
- setIsTableMenuOpen(false);
34516
- setPreservedTableAnchorPos(null);
34517
- }
34518
- }
34519
- ),
34520
- /* @__PURE__ */ jsx93("div", { className: "my-1 border-t" }),
34521
- /* @__PURE__ */ jsx93(
34522
- DropdownMenuItem,
34523
- {
34524
- icon: AlignLeft,
34525
- label: t("tableMenu.alignLeft"),
34526
- onClick: () => applyTableAlignment(editor, "left", tableCommandAnchorPos),
34527
- active: hasTableContext && currentTableAlign === "left",
34528
- disabled: !hasTableContext
34529
- }
34530
- ),
34531
- /* @__PURE__ */ jsx93(
34532
- DropdownMenuItem,
34533
- {
34534
- icon: AlignCenter,
34535
- label: t("tableMenu.alignCenter"),
34536
- onClick: () => applyTableAlignment(editor, "center", tableCommandAnchorPos),
34537
- active: hasTableContext && currentTableAlign === "center",
34538
- disabled: !hasTableContext
34539
- }
34540
- ),
34541
- /* @__PURE__ */ jsx93(
34542
- DropdownMenuItem,
34543
- {
34544
- icon: AlignRight,
34545
- label: t("tableMenu.alignRight"),
34546
- onClick: () => applyTableAlignment(editor, "right", tableCommandAnchorPos),
34547
- active: hasTableContext && currentTableAlign === "right",
34548
- disabled: !hasTableContext
34549
- }
34550
- ),
34551
- /* @__PURE__ */ jsx93("div", { className: "my-1 border-t" }),
34552
- /* @__PURE__ */ jsx93(
34553
- DropdownMenuItem,
34554
- {
34555
- icon: ArrowLeft,
34556
- label: t("tableMenu.addColumnBefore"),
34557
- onClick: () => editor.chain().focus().addColumnBefore().run(),
34558
- disabled: !hasTableContext || !editor.can().addColumnBefore()
34559
- }
34560
- ),
34561
- /* @__PURE__ */ jsx93(
34562
- DropdownMenuItem,
34563
- {
34564
- icon: ArrowDown,
34565
- label: t("tableMenu.addColumnAfter"),
34566
- onClick: () => editor.chain().focus().addColumnAfter().run(),
34567
- disabled: !hasTableContext || !editor.can().addColumnAfter()
34568
- }
34569
- ),
34570
- /* @__PURE__ */ jsx93(
34571
- DropdownMenuItem,
34572
- {
34573
- icon: ArrowUp,
34574
- label: t("tableMenu.addRowBefore"),
34575
- onClick: () => editor.chain().focus().addRowBefore().run(),
34576
- disabled: !hasTableContext || !editor.can().addRowBefore()
34577
- }
34578
- ),
34579
- /* @__PURE__ */ jsx93(
34580
- DropdownMenuItem,
34581
- {
34582
- icon: ArrowRight,
34583
- label: t("tableMenu.addRowAfter"),
34584
- onClick: () => editor.chain().focus().addRowAfter().run(),
34585
- disabled: !hasTableContext || !editor.can().addRowAfter()
34586
- }
34587
- ),
34588
- /* @__PURE__ */ jsx93("div", { className: "my-1 border-t" }),
34589
- /* @__PURE__ */ jsx93(
34590
- DropdownMenuItem,
34591
- {
34592
- icon: TableIcon,
34593
- label: t("tableMenu.toggleHeaderRow"),
34594
- onClick: () => editor.chain().focus().toggleHeaderRow().run(),
34595
- disabled: !hasTableContext || !editor.can().toggleHeaderRow()
34596
- }
34597
- ),
34598
- /* @__PURE__ */ jsx93(
34599
- DropdownMenuItem,
34600
- {
34601
- icon: TableIcon,
34602
- label: t("tableMenu.toggleHeaderColumn"),
34603
- onClick: () => editor.chain().focus().toggleHeaderColumn().run(),
34604
- disabled: !hasTableContext || !editor.can().toggleHeaderColumn()
34605
- }
34606
- ),
34607
- /* @__PURE__ */ jsx93("div", { className: "my-1 border-t" }),
34608
- /* @__PURE__ */ jsx93(
34609
- DropdownMenuItem,
34610
- {
34611
- icon: Trash22,
34612
- label: t("tableMenu.deleteColumn"),
34613
- onClick: () => editor.chain().focus().deleteColumn().run(),
34614
- disabled: !hasTableContext || !editor.can().deleteColumn()
34615
- }
34616
- ),
34617
- /* @__PURE__ */ jsx93(
34618
- DropdownMenuItem,
34619
- {
34620
- icon: Trash22,
34621
- label: t("tableMenu.deleteRow"),
34622
- onClick: () => editor.chain().focus().deleteRow().run(),
34623
- disabled: !hasTableContext || !editor.can().deleteRow()
34624
- }
34625
- ),
34626
- /* @__PURE__ */ jsx93(
34627
- DropdownMenuItem,
34628
- {
34629
- icon: Trash22,
34630
- label: t("tableMenu.deleteTable"),
34631
- onClick: () => editor.chain().focus().deleteTable().run(),
34632
- disabled: !hasTableContext || !editor.can().deleteTable()
34835
+ children: /* @__PURE__ */ jsx93(
34836
+ TableInsertGrid,
34837
+ {
34838
+ insertLabel: t("tableMenu.insertTable"),
34839
+ previewTemplate: t("tableMenu.gridPreview"),
34840
+ onInsert: (rows, cols) => {
34841
+ editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
34842
+ setIsTableMenuOpen(false);
34633
34843
  }
34634
- )
34635
- ]
34844
+ }
34845
+ )
34636
34846
  }
34637
34847
  ),
34638
34848
  /* @__PURE__ */ jsx93(ToolbarDivider, {}),
@@ -34701,14 +34911,14 @@ var EditorToolbar = ({
34701
34911
  // src/components/UEditor/menus.tsx
34702
34912
  import { useCallback as useCallback23, useEffect as useEffect38, useMemo as useMemo25, useRef as useRef35, useState as useState51 } from "react";
34703
34913
  import { useEditorState as useEditorState2 } from "@tiptap/react";
34704
- import { isInTable as isSelectionInTable, setCellAttr as setCellAttr3 } from "@tiptap/pm/tables";
34914
+ import { CellSelection, isInTable as isSelectionInTable, setCellAttr as setCellAttr3 } from "@tiptap/pm/tables";
34705
34915
  import { createPortal as createPortal8 } from "react-dom";
34706
34916
  import {
34707
34917
  AlignCenter as AlignCenter2,
34708
34918
  AlignLeft as AlignLeft2,
34709
34919
  AlignRight as AlignRight2,
34710
34920
  Bold as BoldIcon,
34711
- ChevronDown as ChevronDown9,
34921
+ ChevronDown as ChevronDown8,
34712
34922
  Code as CodeIcon,
34713
34923
  Italic as ItalicIcon,
34714
34924
  Link as LinkIcon2,
@@ -35803,7 +36013,7 @@ function recalculateAllTableFormulas(editor) {
35803
36013
  }
35804
36014
 
35805
36015
  // src/components/UEditor/menus.tsx
35806
- import { Fragment as Fragment30, jsx as jsx94, jsxs as jsxs76 } from "react/jsx-runtime";
36016
+ import { jsx as jsx94, jsxs as jsxs76 } from "react/jsx-runtime";
35807
36017
  var FloatingSlashCommandMenu = ({ editor, onClose }) => {
35808
36018
  const t = useSmartTranslations("UEditor");
35809
36019
  const messages = useMemo25(() => buildSlashCommandMessages(t), [t]);
@@ -35848,7 +36058,7 @@ var FloatingMenuContent = ({ editor }) => {
35848
36058
  {
35849
36059
  type: "button",
35850
36060
  onClick: () => setShowCommands(true),
35851
- className: "flex items-center gap-1 px-2 py-1.5 rounded-lg hover:bg-accent transition-all group",
36061
+ className: "group flex items-center gap-1 rounded-lg px-2 py-1.5 transition-colors hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/30",
35852
36062
  children: [
35853
36063
  /* @__PURE__ */ jsx94(Plus3, { className: "w-4 h-4 text-muted-foreground group-hover:text-foreground" }),
35854
36064
  /* @__PURE__ */ jsx94("span", { className: "text-sm text-muted-foreground group-hover:text-foreground", children: t("floatingMenu.addBlock") })
@@ -35922,20 +36132,28 @@ function BorderPositionPreviewIcon({ position }) {
35922
36132
  showVertical && /* @__PURE__ */ jsx94("path", { d: "M10 2V18", strokeWidth: "2" })
35923
36133
  ] });
35924
36134
  }
36135
+ function getBubbleMenuContext(editor) {
36136
+ const { selection } = editor.state;
36137
+ if (editor.isActive("image")) return "image";
36138
+ if (selection instanceof CellSelection) return "table-cell";
36139
+ if (editor.isActive("link")) return "link";
36140
+ if (!selection.empty) return "text";
36141
+ return "none";
36142
+ }
35925
36143
  var BubbleMenuContent = ({
35926
36144
  editor,
36145
+ context,
35927
36146
  onKeepOpenChange,
35928
36147
  onLinkInputOpenChange,
35929
36148
  onRequestClose,
35930
36149
  fontSizes,
35931
36150
  lineHeights,
35932
- initialShowLinkInput = false,
35933
- cellBorderOpenRequest = 0
36151
+ initialShowLinkInput = false
35934
36152
  }) => {
35935
36153
  const t = useSmartTranslations("UEditor");
35936
36154
  useEditorState2({
35937
36155
  editor,
35938
- selector: ({ transactionNumber }) => transactionNumber
36156
+ selector: ({ editor: currentEditor }) => getEditorUiRenderState(currentEditor)
35939
36157
  });
35940
36158
  const { textColors, highlightColors } = useEditorColors();
35941
36159
  const [showLinkInput, setShowLinkInput] = useState51(initialShowLinkInput);
@@ -35943,17 +36161,13 @@ var BubbleMenuContent = ({
35943
36161
  useEffect38(() => {
35944
36162
  setShowLinkInput(initialShowLinkInput);
35945
36163
  }, [initialShowLinkInput]);
35946
- useEffect38(() => {
35947
- if (!cellBorderOpenRequest) return;
35948
- setActiveColorPalette("cell-border");
35949
- onKeepOpenChange?.(true);
35950
- }, [cellBorderOpenRequest, onKeepOpenChange]);
35951
36164
  const [showTypographyPanel, setShowTypographyPanel] = useState51(false);
35952
36165
  const [showFormulaPanel, setShowFormulaPanel] = useState51(false);
35953
36166
  const [formulaDraft, setFormulaDraft] = useState51("");
35954
36167
  const [showFontSizeOptions, setShowFontSizeOptions] = useState51(false);
35955
36168
  const [fontSizeDraft, setFontSizeDraft] = useState51("");
35956
- const isImageSelected = editor.isActive("image");
36169
+ const isImageSelected = context === "image";
36170
+ const isTableCellSelection = context === "table-cell";
35957
36171
  const imageAttrs = editor.getAttributes("image");
35958
36172
  const imageLayout = imageAttrs.imageLayout === "left" || imageAttrs.imageLayout === "right" ? imageAttrs.imageLayout : "block";
35959
36173
  const imageWidthPreset = imageAttrs.imageWidthPreset === "sm" || imageAttrs.imageWidthPreset === "md" || imageAttrs.imageWidthPreset === "lg" ? imageAttrs.imageWidthPreset : null;
@@ -35975,9 +36189,9 @@ var BubbleMenuContent = ({
35975
36189
  const [activeBorderPosition, setActiveBorderPosition] = useState51("all");
35976
36190
  const currentCellVerticalAlign = normalizeStyleValue(editor.getAttributes("tableCell").verticalAlign || editor.getAttributes("tableHeader").verticalAlign) || "";
35977
36191
  const currentCellTextDirection = normalizeStyleValue(editor.getAttributes("tableCell").textDirection || editor.getAttributes("tableHeader").textDirection) || "horizontal";
35978
- const isInTable2 = isSelectionInTable(editor.state);
35979
- const canMergeCells = isInTable2 && editor.can().mergeCells();
35980
- const canSplitCell = isInTable2 && editor.can().splitCell();
36192
+ const isInTable3 = isSelectionInTable(editor.state);
36193
+ const canMergeCells = isInTable3 && editor.can().mergeCells();
36194
+ const canSplitCell = isInTable3 && editor.can().splitCell();
35981
36195
  const currentFontSize = normalizeStyleValue(textStyleAttrs.fontSize);
35982
36196
  const currentLineHeight = normalizeStyleValue(textStyleAttrs.lineHeight);
35983
36197
  const quickFontSizes = useMemo25(
@@ -36016,12 +36230,10 @@ var BubbleMenuContent = ({
36016
36230
  setFontSizeDraft(String(clamped));
36017
36231
  };
36018
36232
  useEffect38(() => {
36019
- onKeepOpenChange?.(showLinkInput);
36233
+ const shouldKeepOpen = showLinkInput || Boolean(activeColorPalette) || showFormulaPanel || showTypographyPanel;
36234
+ onKeepOpenChange?.(shouldKeepOpen);
36020
36235
  onLinkInputOpenChange?.(showLinkInput);
36021
- }, [onKeepOpenChange, onLinkInputOpenChange, showLinkInput]);
36022
- useEffect38(() => {
36023
- onKeepOpenChange?.(Boolean(activeColorPalette));
36024
- }, [activeColorPalette, onKeepOpenChange]);
36236
+ }, [activeColorPalette, onKeepOpenChange, onLinkInputOpenChange, showFormulaPanel, showLinkInput, showTypographyPanel]);
36025
36237
  const closeTransientPanels = useCallback23(() => {
36026
36238
  setActiveColorPalette(null);
36027
36239
  setShowLinkInput(false);
@@ -36325,7 +36537,7 @@ var BubbleMenuContent = ({
36325
36537
  )
36326
36538
  ] });
36327
36539
  }
36328
- if (showFormulaPanel && isInTable2) {
36540
+ if (showFormulaPanel && isInTable3) {
36329
36541
  return /* @__PURE__ */ jsxs76("div", { className: "w-72 p-2", children: [
36330
36542
  /* @__PURE__ */ jsxs76("div", { className: "mb-2 flex items-center justify-between gap-2", children: [
36331
36543
  /* @__PURE__ */ jsx94("span", { className: "px-1 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: t("tableMenu.formula") || "Formula" }),
@@ -36476,7 +36688,7 @@ var BubbleMenuContent = ({
36476
36688
  "flex h-full w-9 items-center justify-center border-l border-border/50 transition-colors hover:bg-muted",
36477
36689
  showFontSizeOptions && "bg-primary/10 text-primary"
36478
36690
  ),
36479
- children: /* @__PURE__ */ jsx94(ChevronDown9, { className: "h-4 w-4" })
36691
+ children: /* @__PURE__ */ jsx94(ChevronDown8, { className: "h-4 w-4" })
36480
36692
  }
36481
36693
  )
36482
36694
  ] }),
@@ -36580,38 +36792,8 @@ var BubbleMenuContent = ({
36580
36792
  ] });
36581
36793
  }
36582
36794
  const VerticalAlignActiveIcon = currentCellVerticalAlign === "middle" ? AlignCenterVertical2 : currentCellVerticalAlign === "bottom" ? AlignEndVertical2 : AlignStartVertical2;
36583
- return /* @__PURE__ */ jsxs76("div", { className: "flex items-center gap-0.5 p-1", children: [
36584
- /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ jsx94(BoldIcon, { className: "w-4 h-4" }) }),
36585
- /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ jsx94(ItalicIcon, { className: "w-4 h-4" }) }),
36586
- /* @__PURE__ */ jsx94(
36587
- ToolbarButton,
36588
- {
36589
- onClick: () => editor.chain().focus().toggleUnderline().run(),
36590
- active: editor.isActive("underline"),
36591
- title: t("toolbar.underline"),
36592
- children: /* @__PURE__ */ jsx94(UnderlineIcon, { className: "w-4 h-4" })
36593
- }
36594
- ),
36595
- /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ jsx94(StrikethroughIcon, { className: "w-4 h-4" }) }),
36596
- /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ jsx94(CodeIcon, { className: "w-4 h-4" }) }),
36597
- /* @__PURE__ */ jsx94("div", { className: "w-px h-6 bg-border/50 mx-1" }),
36598
- /* @__PURE__ */ jsx94(
36599
- ToolbarButton,
36600
- {
36601
- onMouseDown: () => {
36602
- onKeepOpenChange?.(true);
36603
- },
36604
- onClick: () => {
36605
- setShowLinkInput(true);
36606
- },
36607
- active: editor.isActive("link"),
36608
- title: t("toolbar.link"),
36609
- children: /* @__PURE__ */ jsx94(LinkIcon2, { className: "w-4 h-4" })
36610
- }
36611
- ),
36612
- /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => setActiveColorPalette("text"), title: t("colors.textColor"), children: /* @__PURE__ */ jsx94(TextColorIcon, { color: currentTextColor }) }),
36613
- /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => setActiveColorPalette("highlight"), active: editor.isActive("highlight"), title: t("colors.highlight"), children: /* @__PURE__ */ jsx94(HighlightColorIcon, { color: currentHighlightColor }) }),
36614
- isInTable2 && /* @__PURE__ */ jsxs76(Fragment30, { children: [
36795
+ if (isTableCellSelection) {
36796
+ return /* @__PURE__ */ jsxs76("div", { className: "flex items-center gap-0.5 p-1", "data-ueditor-cell-inspector": "", children: [
36615
36797
  /* @__PURE__ */ jsx94(
36616
36798
  ToolbarButton,
36617
36799
  {
@@ -36624,9 +36806,7 @@ var BubbleMenuContent = ({
36624
36806
  /* @__PURE__ */ jsx94(
36625
36807
  ToolbarButton,
36626
36808
  {
36627
- onMouseDown: () => {
36628
- onKeepOpenChange?.(true);
36629
- },
36809
+ onMouseDown: () => onKeepOpenChange?.(true),
36630
36810
  onClick: () => setActiveColorPalette("cell-border"),
36631
36811
  active: Boolean(
36632
36812
  editor.getAttributes("tableCell").borderColor || editor.getAttributes("tableHeader").borderColor || editor.getAttributes("tableCell").borderStyle || editor.getAttributes("tableHeader").borderStyle || editor.getAttributes("tableCell").borderWidth || editor.getAttributes("tableHeader").borderWidth
@@ -36643,9 +36823,7 @@ var BubbleMenuContent = ({
36643
36823
  /* @__PURE__ */ jsx94(
36644
36824
  ToolbarButton,
36645
36825
  {
36646
- onMouseDown: () => {
36647
- onKeepOpenChange?.(true);
36648
- },
36826
+ onMouseDown: () => onKeepOpenChange?.(true),
36649
36827
  onClick: () => {
36650
36828
  setFormulaDraft(currentCellFormula);
36651
36829
  setShowFormulaPanel(true);
@@ -36674,21 +36852,17 @@ var BubbleMenuContent = ({
36674
36852
  /* @__PURE__ */ jsxs76(
36675
36853
  DropdownMenu,
36676
36854
  {
36677
- onOpenChange: (open) => {
36678
- onKeepOpenChange?.(open);
36679
- },
36855
+ onOpenChange: onKeepOpenChange,
36680
36856
  trigger: /* @__PURE__ */ jsxs76(
36681
36857
  ToolbarButton,
36682
36858
  {
36683
- onMouseDown: () => {
36684
- onKeepOpenChange?.(true);
36685
- },
36859
+ onMouseDown: () => onKeepOpenChange?.(true),
36686
36860
  onClick: () => {
36687
36861
  },
36688
36862
  title: t("tableMenu.alignVertical") || "Vertical alignment",
36689
36863
  children: [
36690
36864
  /* @__PURE__ */ jsx94(VerticalAlignActiveIcon, { className: "w-4 h-4" }),
36691
- /* @__PURE__ */ jsx94(ChevronDown9, { className: "w-3 h-3" })
36865
+ /* @__PURE__ */ jsx94(ChevronDown8, { className: "w-3 h-3" })
36692
36866
  ]
36693
36867
  }
36694
36868
  ),
@@ -36726,21 +36900,17 @@ var BubbleMenuContent = ({
36726
36900
  /* @__PURE__ */ jsxs76(
36727
36901
  DropdownMenu,
36728
36902
  {
36729
- onOpenChange: (open) => {
36730
- onKeepOpenChange?.(open);
36731
- },
36903
+ onOpenChange: onKeepOpenChange,
36732
36904
  trigger: /* @__PURE__ */ jsxs76(
36733
36905
  ToolbarButton,
36734
36906
  {
36735
- onMouseDown: () => {
36736
- onKeepOpenChange?.(true);
36737
- },
36907
+ onMouseDown: () => onKeepOpenChange?.(true),
36738
36908
  onClick: () => {
36739
36909
  },
36740
36910
  title: t("tableMenu.textDirection"),
36741
36911
  children: [
36742
36912
  currentCellTextDirection === "vertical" ? /* @__PURE__ */ jsx94(ArrowDown2, { className: "w-4 h-4" }) : /* @__PURE__ */ jsx94(ArrowRight2, { className: "w-4 h-4" }),
36743
- /* @__PURE__ */ jsx94(ChevronDown9, { className: "w-3 h-3" })
36913
+ /* @__PURE__ */ jsx94(ChevronDown8, { className: "w-3 h-3" })
36744
36914
  ]
36745
36915
  }
36746
36916
  ),
@@ -36766,7 +36936,39 @@ var BubbleMenuContent = ({
36766
36936
  ]
36767
36937
  }
36768
36938
  )
36769
- ] }),
36939
+ ] });
36940
+ }
36941
+ return /* @__PURE__ */ jsxs76("div", { className: "flex items-center gap-0.5 p-1", children: [
36942
+ /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => editor.chain().focus().toggleBold().run(), active: editor.isActive("bold"), title: t("toolbar.bold"), children: /* @__PURE__ */ jsx94(BoldIcon, { className: "w-4 h-4" }) }),
36943
+ /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => editor.chain().focus().toggleItalic().run(), active: editor.isActive("italic"), title: t("toolbar.italic"), children: /* @__PURE__ */ jsx94(ItalicIcon, { className: "w-4 h-4" }) }),
36944
+ /* @__PURE__ */ jsx94(
36945
+ ToolbarButton,
36946
+ {
36947
+ onClick: () => editor.chain().focus().toggleUnderline().run(),
36948
+ active: editor.isActive("underline"),
36949
+ title: t("toolbar.underline"),
36950
+ children: /* @__PURE__ */ jsx94(UnderlineIcon, { className: "w-4 h-4" })
36951
+ }
36952
+ ),
36953
+ /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => editor.chain().focus().toggleStrike().run(), active: editor.isActive("strike"), title: t("toolbar.strike"), children: /* @__PURE__ */ jsx94(StrikethroughIcon, { className: "w-4 h-4" }) }),
36954
+ /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => editor.chain().focus().toggleCode().run(), active: editor.isActive("code"), title: t("toolbar.code"), children: /* @__PURE__ */ jsx94(CodeIcon, { className: "w-4 h-4" }) }),
36955
+ /* @__PURE__ */ jsx94("div", { className: "w-px h-6 bg-border/50 mx-1" }),
36956
+ /* @__PURE__ */ jsx94(
36957
+ ToolbarButton,
36958
+ {
36959
+ onMouseDown: () => {
36960
+ onKeepOpenChange?.(true);
36961
+ },
36962
+ onClick: () => {
36963
+ setShowLinkInput(true);
36964
+ },
36965
+ active: editor.isActive("link"),
36966
+ title: t("toolbar.link"),
36967
+ children: /* @__PURE__ */ jsx94(LinkIcon2, { className: "w-4 h-4" })
36968
+ }
36969
+ ),
36970
+ /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => setActiveColorPalette("text"), title: t("colors.textColor"), children: /* @__PURE__ */ jsx94(TextColorIcon, { color: currentTextColor }) }),
36971
+ /* @__PURE__ */ jsx94(ToolbarButton, { onClick: () => setActiveColorPalette("highlight"), active: editor.isActive("highlight"), title: t("colors.highlight"), children: /* @__PURE__ */ jsx94(HighlightColorIcon, { color: currentHighlightColor }) }),
36770
36972
  /* @__PURE__ */ jsx94(
36771
36973
  ToolbarButton,
36772
36974
  {
@@ -36806,7 +37008,6 @@ var CustomBubbleMenu = ({
36806
37008
  const BUBBLE_MENU_ESTIMATED_HEIGHT = 44;
36807
37009
  const [isVisible, setIsVisible] = useState51(false);
36808
37010
  const [linkInputOpen, setLinkInputOpen] = useState51(false);
36809
- const [cellBorderOpenRequest, setCellBorderOpenRequest] = useState51(0);
36810
37011
  const [position, setPosition2] = useState51({
36811
37012
  top: 0,
36812
37013
  left: 0,
@@ -36843,14 +37044,14 @@ var CustomBubbleMenu = ({
36843
37044
  };
36844
37045
  const updatePosition = () => {
36845
37046
  const { state, view } = editor;
36846
- const { from, to, empty } = state.selection;
36847
- const isLinkActive = editor.isActive("link");
37047
+ const { from, to } = state.selection;
37048
+ const context2 = getBubbleMenuContext(editor);
36848
37049
  if (Date.now() < suppressShowUntilRef.current) {
36849
37050
  clearShowTimeout();
36850
37051
  setIsVisible(false);
36851
37052
  return;
36852
37053
  }
36853
- if (!keepOpenRef.current && (empty && !isLinkActive || !view.hasFocus())) {
37054
+ if (!keepOpenRef.current && (context2 === "none" || !view.hasFocus())) {
36854
37055
  clearShowTimeout();
36855
37056
  setIsVisible(false);
36856
37057
  return;
@@ -36900,20 +37101,24 @@ var CustomBubbleMenu = ({
36900
37101
  setIsVisible(false);
36901
37102
  }
36902
37103
  };
36903
- editor.on("selectionUpdate", updatePosition);
36904
- editor.on("focus", updatePosition);
37104
+ let animationFrameId = null;
37105
+ const schedulePositionUpdate = () => {
37106
+ if (animationFrameId !== null) return;
37107
+ animationFrameId = requestAnimationFrame(() => {
37108
+ animationFrameId = null;
37109
+ updatePosition();
37110
+ });
37111
+ };
37112
+ editor.on("transaction", schedulePositionUpdate);
37113
+ editor.on("focus", schedulePositionUpdate);
36905
37114
  editor.on("blur", handleBlur);
36906
- editor.on("transaction", updatePosition);
36907
- editor.on("update", updatePosition);
36908
- const animationFrameId = requestAnimationFrame(updatePosition);
37115
+ schedulePositionUpdate();
36909
37116
  return () => {
36910
- cancelAnimationFrame(animationFrameId);
37117
+ if (animationFrameId !== null) cancelAnimationFrame(animationFrameId);
36911
37118
  clearShowTimeout();
36912
- editor.off("selectionUpdate", updatePosition);
36913
- editor.off("focus", updatePosition);
37119
+ editor.off("transaction", schedulePositionUpdate);
37120
+ editor.off("focus", schedulePositionUpdate);
36914
37121
  editor.off("blur", handleBlur);
36915
- editor.off("transaction", updatePosition);
36916
- editor.off("update", updatePosition);
36917
37122
  };
36918
37123
  }, [editor]);
36919
37124
  useEffect38(() => {
@@ -36921,8 +37126,6 @@ var CustomBubbleMenu = ({
36921
37126
  const handlePointerDown = (event) => {
36922
37127
  const target = event.target;
36923
37128
  if (target && (menuRef.current?.contains(target) || target.closest("[data-ueditor-keep-open]"))) return;
36924
- const table = target?.closest("table");
36925
- if (table && editor.view.dom.contains(table)) return;
36926
37129
  closeBubbleMenu(false);
36927
37130
  };
36928
37131
  const handleKeyDown2 = (event) => {
@@ -36935,23 +37138,9 @@ var CustomBubbleMenu = ({
36935
37138
  document.removeEventListener("keydown", handleKeyDown2);
36936
37139
  };
36937
37140
  }, [closeBubbleMenu, editor, isVisible]);
36938
- useEffect38(() => {
36939
- const handleTableDoubleClick = (event) => {
36940
- const target = event.target;
36941
- const cell = target?.closest("td,th");
36942
- if (!cell || !editor.view.dom.contains(cell)) return;
36943
- suppressShowUntilRef.current = 0;
36944
- keepOpenRef.current = true;
36945
- setKeepOpenState(true);
36946
- setLinkInputOpen(false);
36947
- setCellBorderOpenRequest((request) => request + 1);
36948
- setIsVisible(true);
36949
- requestAnimationFrame(() => editor.view.focus());
36950
- };
36951
- editor.view.dom.addEventListener("dblclick", handleTableDoubleClick);
36952
- return () => editor.view.dom.removeEventListener("dblclick", handleTableDoubleClick);
36953
- }, [editor]);
36954
37141
  if (!isVisible) return null;
37142
+ const context = getBubbleMenuContext(editor);
37143
+ if (context === "none") return null;
36955
37144
  return createPortal8(
36956
37145
  /* @__PURE__ */ jsx94(
36957
37146
  "div",
@@ -36973,7 +37162,7 @@ var CustomBubbleMenu = ({
36973
37162
  }
36974
37163
  e.preventDefault();
36975
37164
  },
36976
- children: editor.isActive("link") && !keepOpen && !linkInputOpen ? /* @__PURE__ */ jsx94(
37165
+ children: context === "link" && !keepOpen && !linkInputOpen ? /* @__PURE__ */ jsx94(
36977
37166
  LinkPreviewContent,
36978
37167
  {
36979
37168
  editor,
@@ -36986,14 +37175,15 @@ var CustomBubbleMenu = ({
36986
37175
  BubbleMenuContent,
36987
37176
  {
36988
37177
  editor,
37178
+ context,
36989
37179
  onKeepOpenChange: setKeepOpen,
36990
37180
  onLinkInputOpenChange: setLinkInputOpen,
36991
37181
  onRequestClose: closeBubbleMenu,
36992
37182
  fontSizes,
36993
37183
  lineHeights,
36994
- initialShowLinkInput: linkInputOpen,
36995
- cellBorderOpenRequest
36996
- }
37184
+ initialShowLinkInput: linkInputOpen
37185
+ },
37186
+ context
36997
37187
  )
36998
37188
  }
36999
37189
  ),
@@ -37018,15 +37208,23 @@ var CustomFloatingMenu = ({ editor }) => {
37018
37208
  setIsVisible(true);
37019
37209
  };
37020
37210
  const handleBlur = () => setIsVisible(false);
37021
- editor.on("selectionUpdate", updatePosition);
37022
- editor.on("focus", updatePosition);
37211
+ let animationFrameId = null;
37212
+ const schedulePositionUpdate = () => {
37213
+ if (animationFrameId !== null) return;
37214
+ animationFrameId = requestAnimationFrame(() => {
37215
+ animationFrameId = null;
37216
+ updatePosition();
37217
+ });
37218
+ };
37219
+ editor.on("transaction", schedulePositionUpdate);
37220
+ editor.on("focus", schedulePositionUpdate);
37023
37221
  editor.on("blur", handleBlur);
37024
- editor.on("update", updatePosition);
37222
+ schedulePositionUpdate();
37025
37223
  return () => {
37026
- editor.off("selectionUpdate", updatePosition);
37027
- editor.off("focus", updatePosition);
37224
+ if (animationFrameId !== null) cancelAnimationFrame(animationFrameId);
37225
+ editor.off("transaction", schedulePositionUpdate);
37226
+ editor.off("focus", schedulePositionUpdate);
37028
37227
  editor.off("blur", handleBlur);
37029
- editor.off("update", updatePosition);
37030
37228
  };
37031
37229
  }, [editor]);
37032
37230
  if (!isVisible) return null;
@@ -37050,12 +37248,20 @@ var CustomFloatingMenu = ({ editor }) => {
37050
37248
  };
37051
37249
 
37052
37250
  // src/components/UEditor/CharacterCount.tsx
37251
+ import { useEditorState as useEditorState3 } from "@tiptap/react";
37053
37252
  import { jsxs as jsxs77 } from "react/jsx-runtime";
37054
37253
  var CharacterCountDisplay = ({ editor, maxCharacters }) => {
37055
37254
  const t = useSmartTranslations("UEditor");
37056
- const storage = editor.storage;
37057
- const characterCount = storage.characterCount?.characters?.() ?? 0;
37058
- const wordCount = storage.characterCount?.words?.() ?? 0;
37255
+ const { characterCount, wordCount } = useEditorState3({
37256
+ editor,
37257
+ selector: ({ editor: currentEditor }) => {
37258
+ const storage = currentEditor.storage;
37259
+ return {
37260
+ characterCount: storage.characterCount?.characters?.() ?? 0,
37261
+ wordCount: storage.characterCount?.words?.() ?? 0
37262
+ };
37263
+ }
37264
+ });
37059
37265
  const percentage = maxCharacters ? Math.round(characterCount / maxCharacters * 100) : 0;
37060
37266
  return /* @__PURE__ */ jsxs77("div", { className: "flex items-center gap-3 px-3 py-2 text-xs text-muted-foreground border-t border-border/30 bg-muted/20", children: [
37061
37267
  /* @__PURE__ */ jsxs77("span", { children: [
@@ -37546,7 +37752,7 @@ function findDiffEnd(a, b, posA, posB) {
37546
37752
  posB -= size;
37547
37753
  }
37548
37754
  }
37549
- var Fragment31 = class _Fragment {
37755
+ var Fragment30 = class _Fragment {
37550
37756
  /**
37551
37757
  @internal
37552
37758
  */
@@ -37838,7 +38044,7 @@ var Fragment31 = class _Fragment {
37838
38044
  throw new RangeError("Can not convert " + nodes + " to a Fragment" + (nodes.nodesBetween ? " (looks like multiple versions of prosemirror-model were loaded)" : ""));
37839
38045
  }
37840
38046
  };
37841
- Fragment31.empty = new Fragment31([], 0);
38047
+ Fragment30.empty = new Fragment30([], 0);
37842
38048
  var found = { index: 0, offset: 0 };
37843
38049
  function retIndex(index, offset) {
37844
38050
  found.index = index;
@@ -38063,7 +38269,7 @@ var Slice = class _Slice {
38063
38269
  let openStart = json.openStart || 0, openEnd = json.openEnd || 0;
38064
38270
  if (typeof openStart != "number" || typeof openEnd != "number")
38065
38271
  throw new RangeError("Invalid input for Slice.fromJSON");
38066
- return new _Slice(Fragment31.fromJSON(schema, json.content), openStart, openEnd);
38272
+ return new _Slice(Fragment30.fromJSON(schema, json.content), openStart, openEnd);
38067
38273
  }
38068
38274
  /**
38069
38275
  Create a slice from a fragment by taking the maximum possible
@@ -38078,7 +38284,7 @@ var Slice = class _Slice {
38078
38284
  return new _Slice(fragment, openStart, openEnd);
38079
38285
  }
38080
38286
  };
38081
- Slice.empty = new Slice(Fragment31.empty, 0, 0);
38287
+ Slice.empty = new Slice(Fragment30.empty, 0, 0);
38082
38288
  function removeRange(content, from, to) {
38083
38289
  let { index, offset } = content.findIndex(from), child = content.maybeChild(index);
38084
38290
  let { index: indexTo, offset: offsetTo } = content.findIndex(to);
@@ -38176,7 +38382,7 @@ function replaceThreeWay($from, $start, $end, $to, depth) {
38176
38382
  addNode(close(openEnd, replaceTwoWay($end, $to, depth + 1)), content);
38177
38383
  }
38178
38384
  addRange($to, null, depth, content);
38179
- return new Fragment31(content);
38385
+ return new Fragment30(content);
38180
38386
  }
38181
38387
  function replaceTwoWay($from, $to, depth) {
38182
38388
  let content = [];
@@ -38186,13 +38392,13 @@ function replaceTwoWay($from, $to, depth) {
38186
38392
  addNode(close(type, replaceTwoWay($from, $to, depth + 1)), content);
38187
38393
  }
38188
38394
  addRange($to, null, depth, content);
38189
- return new Fragment31(content);
38395
+ return new Fragment30(content);
38190
38396
  }
38191
38397
  function prepareSliceForReplace(slice, $along) {
38192
38398
  let extra = $along.depth - slice.openStart, parent = $along.node(extra);
38193
38399
  let node = parent.copy(slice.content);
38194
38400
  for (let i = extra - 1; i >= 0; i--)
38195
- node = $along.node(i).copy(Fragment31.from(node));
38401
+ node = $along.node(i).copy(Fragment30.from(node));
38196
38402
  return {
38197
38403
  start: node.resolveNoCache(slice.openStart + extra),
38198
38404
  end: node.resolveNoCache(node.content.size - slice.openEnd - extra)
@@ -38531,7 +38737,7 @@ var Node7 = class _Node {
38531
38737
  this.type = type;
38532
38738
  this.attrs = attrs;
38533
38739
  this.marks = marks;
38534
- this.content = content || Fragment31.empty;
38740
+ this.content = content || Fragment30.empty;
38535
38741
  }
38536
38742
  /**
38537
38743
  The array of this node's child nodes.
@@ -38836,7 +39042,7 @@ var Node7 = class _Node {
38836
39042
  can optionally pass `start` and `end` indices into the
38837
39043
  replacement fragment.
38838
39044
  */
38839
- canReplace(from, to, replacement = Fragment31.empty, start = 0, end = replacement.childCount) {
39045
+ canReplace(from, to, replacement = Fragment30.empty, start = 0, end = replacement.childCount) {
38840
39046
  let one = this.contentMatchAt(from).matchFragment(replacement, start, end);
38841
39047
  let two = one && one.matchFragment(this.content, to);
38842
39048
  if (!two || !two.validEnd)
@@ -38918,7 +39124,7 @@ var Node7 = class _Node {
38918
39124
  throw new RangeError("Invalid text node in JSON");
38919
39125
  return schema.text(json.text, marks);
38920
39126
  }
38921
- let content = Fragment31.fromJSON(schema, json.content);
39127
+ let content = Fragment30.fromJSON(schema, json.content);
38922
39128
  let node = schema.nodeType(json.type).create(json.attrs, content, marks);
38923
39129
  node.type.checkAttrs(node.attrs);
38924
39130
  return node;
@@ -39014,7 +39220,7 @@ var ContentMatch = class _ContentMatch {
39014
39220
  function search(match, types) {
39015
39221
  let finished = match.matchFragment(after, startIndex);
39016
39222
  if (finished && (!toEnd || finished.validEnd))
39017
- return Fragment31.from(types.map((tp) => tp.createAndFill()));
39223
+ return Fragment30.from(types.map((tp) => tp.createAndFill()));
39018
39224
  for (let i = 0; i < match.next.length; i++) {
39019
39225
  let { type, next } = match.next[i];
39020
39226
  if (!(type.isText || type.hasRequiredAttrs()) && seen.indexOf(next) == -1) {
@@ -39582,7 +39788,7 @@ function mapFragment(fragment, f, parent) {
39582
39788
  child = f(child, parent, i);
39583
39789
  mapped.push(child);
39584
39790
  }
39585
- return Fragment31.fromArray(mapped);
39791
+ return Fragment30.fromArray(mapped);
39586
39792
  }
39587
39793
  var AddMarkStep = class _AddMarkStep extends Step {
39588
39794
  /**
@@ -39699,7 +39905,7 @@ var AddNodeMarkStep = class _AddNodeMarkStep extends Step {
39699
39905
  if (!node)
39700
39906
  return StepResult.fail("No node at mark step's position");
39701
39907
  let updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks));
39702
- return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment31.from(updated), 0, node.isLeaf ? 0 : 1));
39908
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment30.from(updated), 0, node.isLeaf ? 0 : 1));
39703
39909
  }
39704
39910
  invert(doc) {
39705
39911
  let node = doc.nodeAt(this.pos);
@@ -39745,7 +39951,7 @@ var RemoveNodeMarkStep = class _RemoveNodeMarkStep extends Step {
39745
39951
  if (!node)
39746
39952
  return StepResult.fail("No node at mark step's position");
39747
39953
  let updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks));
39748
- return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment31.from(updated), 0, node.isLeaf ? 0 : 1));
39954
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment30.from(updated), 0, node.isLeaf ? 0 : 1));
39749
39955
  }
39750
39956
  invert(doc) {
39751
39957
  let node = doc.nodeAt(this.pos);
@@ -39946,7 +40152,7 @@ var AttrStep = class _AttrStep extends Step {
39946
40152
  attrs[name] = node.attrs[name];
39947
40153
  attrs[this.attr] = this.value;
39948
40154
  let updated = node.type.create(attrs, null, node.marks);
39949
- return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment31.from(updated), 0, node.isLeaf ? 0 : 1));
40155
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, new Slice(Fragment30.from(updated), 0, node.isLeaf ? 0 : 1));
39950
40156
  }
39951
40157
  getMap() {
39952
40158
  return StepMap.empty;
@@ -40330,7 +40536,7 @@ var NodeSelection2 = class _NodeSelection extends Selection {
40330
40536
  return new _NodeSelection($pos);
40331
40537
  }
40332
40538
  content() {
40333
- return new Slice(Fragment31.from(this.node), 0, 0);
40539
+ return new Slice(Fragment30.from(this.node), 0, 0);
40334
40540
  }
40335
40541
  eq(other) {
40336
40542
  return other instanceof _NodeSelection && other.anchor == this.anchor;
@@ -40943,7 +41149,7 @@ function cellAround2($pos) {
40943
41149
  for (let d = $pos.depth - 1; d > 0; d--) if ($pos.node(d).type.spec.tableRole == "row") return $pos.node(0).resolve($pos.before(d + 1));
40944
41150
  return null;
40945
41151
  }
40946
- function isInTable(state) {
41152
+ function isInTable2(state) {
40947
41153
  const $head = state.selection.$head;
40948
41154
  for (let d = $head.depth; d > 0; d--) if ($head.node(d).type.spec.tableRole == "row") return true;
40949
41155
  return false;
@@ -40991,7 +41197,7 @@ function removeColSpan(attrs, pos, n = 1) {
40991
41197
  }
40992
41198
  return result;
40993
41199
  }
40994
- var CellSelection = class CellSelection2 extends Selection {
41200
+ var CellSelection2 = class CellSelection3 extends Selection {
40995
41201
  constructor($anchorCell, $headCell = $anchorCell) {
40996
41202
  const table = $anchorCell.node(-1);
40997
41203
  const map = TableMap4.get(table);
@@ -41015,9 +41221,9 @@ var CellSelection = class CellSelection2 extends Selection {
41015
41221
  const $headCell = doc.resolve(mapping.map(this.$headCell.pos));
41016
41222
  if (pointsAtCell2($anchorCell) && pointsAtCell2($headCell) && inSameTable($anchorCell, $headCell)) {
41017
41223
  const tableChanged = this.$anchorCell.node(-1) != $anchorCell.node(-1);
41018
- if (tableChanged && this.isRowSelection()) return CellSelection2.rowSelection($anchorCell, $headCell);
41019
- else if (tableChanged && this.isColSelection()) return CellSelection2.colSelection($anchorCell, $headCell);
41020
- else return new CellSelection2($anchorCell, $headCell);
41224
+ if (tableChanged && this.isRowSelection()) return CellSelection3.rowSelection($anchorCell, $headCell);
41225
+ else if (tableChanged && this.isColSelection()) return CellSelection3.colSelection($anchorCell, $headCell);
41226
+ else return new CellSelection3($anchorCell, $headCell);
41021
41227
  }
41022
41228
  return TextSelection5.between($anchorCell, $headCell);
41023
41229
  }
@@ -41058,10 +41264,10 @@ var CellSelection = class CellSelection2 extends Selection {
41058
41264
  }
41059
41265
  rowContent.push(cell);
41060
41266
  }
41061
- rows.push(table.child(row).copy(Fragment31.from(rowContent)));
41267
+ rows.push(table.child(row).copy(Fragment30.from(rowContent)));
41062
41268
  }
41063
41269
  const fragment = this.isColSelection() && this.isRowSelection() ? table : rows;
41064
- return new Slice(Fragment31.from(fragment), 1, 1);
41270
+ return new Slice(Fragment30.from(fragment), 1, 1);
41065
41271
  }
41066
41272
  replace(tr, content = Slice.empty) {
41067
41273
  const mapFrom = tr.steps.length, ranges = this.ranges;
@@ -41073,7 +41279,7 @@ var CellSelection = class CellSelection2 extends Selection {
41073
41279
  if (sel) tr.setSelection(sel);
41074
41280
  }
41075
41281
  replaceWith(tr, node) {
41076
- this.replace(tr, new Slice(Fragment31.from(node), 0, 0));
41282
+ this.replace(tr, new Slice(Fragment30.from(node), 0, 0));
41077
41283
  }
41078
41284
  forEachCell(f) {
41079
41285
  const table = this.$anchorCell.node(-1);
@@ -41104,7 +41310,7 @@ var CellSelection = class CellSelection2 extends Selection {
41104
41310
  if (headRect.top > 0) $headCell = doc.resolve(tableStart + map.map[headRect.left]);
41105
41311
  if (anchorRect.bottom < map.height) $anchorCell = doc.resolve(tableStart + map.map[map.width * (map.height - 1) + anchorRect.right - 1]);
41106
41312
  }
41107
- return new CellSelection2($anchorCell, $headCell);
41313
+ return new CellSelection3($anchorCell, $headCell);
41108
41314
  }
41109
41315
  isRowSelection() {
41110
41316
  const table = this.$anchorCell.node(-1);
@@ -41118,7 +41324,7 @@ var CellSelection = class CellSelection2 extends Selection {
41118
41324
  return Math.max(anchorRight, headRight) == map.width;
41119
41325
  }
41120
41326
  eq(other) {
41121
- return other instanceof CellSelection2 && other.$anchorCell.pos == this.$anchorCell.pos && other.$headCell.pos == this.$headCell.pos;
41327
+ return other instanceof CellSelection3 && other.$anchorCell.pos == this.$anchorCell.pos && other.$headCell.pos == this.$headCell.pos;
41122
41328
  }
41123
41329
  static rowSelection($anchorCell, $headCell = $anchorCell) {
41124
41330
  const table = $anchorCell.node(-1);
@@ -41134,7 +41340,7 @@ var CellSelection = class CellSelection2 extends Selection {
41134
41340
  if (headRect.left > 0) $headCell = doc.resolve(tableStart + map.map[headRect.top * map.width]);
41135
41341
  if (anchorRect.right < map.width) $anchorCell = doc.resolve(tableStart + map.map[map.width * (anchorRect.top + 1) - 1]);
41136
41342
  }
41137
- return new CellSelection2($anchorCell, $headCell);
41343
+ return new CellSelection3($anchorCell, $headCell);
41138
41344
  }
41139
41345
  toJSON() {
41140
41346
  return {
@@ -41144,17 +41350,17 @@ var CellSelection = class CellSelection2 extends Selection {
41144
41350
  };
41145
41351
  }
41146
41352
  static fromJSON(doc, json) {
41147
- return new CellSelection2(doc.resolve(json.anchor), doc.resolve(json.head));
41353
+ return new CellSelection3(doc.resolve(json.anchor), doc.resolve(json.head));
41148
41354
  }
41149
41355
  static create(doc, anchorCell, headCell = anchorCell) {
41150
- return new CellSelection2(doc.resolve(anchorCell), doc.resolve(headCell));
41356
+ return new CellSelection3(doc.resolve(anchorCell), doc.resolve(headCell));
41151
41357
  }
41152
41358
  getBookmark() {
41153
41359
  return new CellBookmark(this.$anchorCell.pos, this.$headCell.pos);
41154
41360
  }
41155
41361
  };
41156
- CellSelection.prototype.visible = false;
41157
- Selection.jsonID("cell", CellSelection);
41362
+ CellSelection2.prototype.visible = false;
41363
+ Selection.jsonID("cell", CellSelection2);
41158
41364
  var CellBookmark = class CellBookmark2 {
41159
41365
  constructor(anchor, head) {
41160
41366
  this.anchor = anchor;
@@ -41165,7 +41371,7 @@ var CellBookmark = class CellBookmark2 {
41165
41371
  }
41166
41372
  resolve(doc) {
41167
41373
  const $anchorCell = doc.resolve(this.anchor), $headCell = doc.resolve(this.head);
41168
- if ($anchorCell.parent.type.spec.tableRole == "row" && $headCell.parent.type.spec.tableRole == "row" && $anchorCell.index() < $anchorCell.parent.childCount && $headCell.index() < $headCell.parent.childCount && inSameTable($anchorCell, $headCell)) return new CellSelection($anchorCell, $headCell);
41374
+ if ($anchorCell.parent.type.spec.tableRole == "row" && $headCell.parent.type.spec.tableRole == "row" && $anchorCell.index() < $anchorCell.parent.childCount && $headCell.index() < $headCell.parent.childCount && inSameTable($anchorCell, $headCell)) return new CellSelection2($anchorCell, $headCell);
41169
41375
  else return Selection.near($headCell, 1);
41170
41376
  }
41171
41377
  };
@@ -41408,7 +41614,7 @@ function moveColumn(moveColParams) {
41408
41614
  const $lastCell = tr.doc.resolve(start + lastCell);
41409
41615
  const firstCell = map.positionAt(0, index, newTable);
41410
41616
  const $firstCell = tr.doc.resolve(start + firstCell);
41411
- tr.setSelection(CellSelection.colSelection($lastCell, $firstCell));
41617
+ tr.setSelection(CellSelection2.colSelection($lastCell, $firstCell));
41412
41618
  return true;
41413
41619
  }
41414
41620
  function moveTableColumn$1(table, indexesOrigin, indexesTarget, direction) {
@@ -41436,7 +41642,7 @@ function moveRow(moveRowParams) {
41436
41642
  const $lastCell = tr.doc.resolve(start + lastCell);
41437
41643
  const firstCell = map.positionAt(index, 0, newTable);
41438
41644
  const $firstCell = tr.doc.resolve(start + firstCell);
41439
- tr.setSelection(CellSelection.rowSelection($lastCell, $firstCell));
41645
+ tr.setSelection(CellSelection2.rowSelection($lastCell, $firstCell));
41440
41646
  return true;
41441
41647
  }
41442
41648
  function moveTableRow$1(table, indexesOrigin, indexesTarget, direction) {
@@ -41451,7 +41657,7 @@ function selectedRect4(state) {
41451
41657
  const tableStart = $pos.start(-1);
41452
41658
  const map = TableMap4.get(table);
41453
41659
  return {
41454
- ...sel instanceof CellSelection ? map.rectBetween(sel.$anchorCell.pos - tableStart, sel.$headCell.pos - tableStart) : map.findCell($pos.pos - tableStart),
41660
+ ...sel instanceof CellSelection2 ? map.rectBetween(sel.$anchorCell.pos - tableStart, sel.$headCell.pos - tableStart) : map.findCell($pos.pos - tableStart),
41455
41661
  tableStart,
41456
41662
  map,
41457
41663
  table
@@ -41459,7 +41665,7 @@ function selectedRect4(state) {
41459
41665
  }
41460
41666
  function deprecated_toggleHeader(type) {
41461
41667
  return function(state, dispatch) {
41462
- if (!isInTable(state)) return false;
41668
+ if (!isInTable2(state)) return false;
41463
41669
  if (dispatch) {
41464
41670
  const types = tableNodeTypes2(state.schema);
41465
41671
  const rect = selectedRect4(state), tr = state.tr;
@@ -41499,7 +41705,7 @@ function toggleHeader(type, options) {
41499
41705
  options = options || { useDeprecatedLogic: false };
41500
41706
  if (options.useDeprecatedLogic) return deprecated_toggleHeader(type);
41501
41707
  return function(state, dispatch) {
41502
- if (!isInTable(state)) return false;
41708
+ if (!isInTable2(state)) return false;
41503
41709
  if (dispatch) {
41504
41710
  const types = tableNodeTypes2(state.schema);
41505
41711
  const rect = selectedRect4(state), tr = state.tr;
@@ -41533,7 +41739,7 @@ var toggleHeaderColumn = toggleHeader("column", { useDeprecatedLogic: true });
41533
41739
  var toggleHeaderCell = toggleHeader("cell", { useDeprecatedLogic: true });
41534
41740
  function deleteCellSelection(state, dispatch) {
41535
41741
  const sel = state.selection;
41536
- if (!(sel instanceof CellSelection)) return false;
41742
+ if (!(sel instanceof CellSelection2)) return false;
41537
41743
  if (dispatch) {
41538
41744
  const tr = state.tr;
41539
41745
  const baseContent = tableNodeTypes2(state.schema).cell.createAndFill().content;
@@ -41601,7 +41807,7 @@ function arrow(axis, dir) {
41601
41807
  return (state, dispatch, view) => {
41602
41808
  if (!view) return false;
41603
41809
  const sel = state.selection;
41604
- if (sel instanceof CellSelection) return maybeSetSelection(state, dispatch, Selection.near(sel.$headCell, dir));
41810
+ if (sel instanceof CellSelection2) return maybeSetSelection(state, dispatch, Selection.near(sel.$headCell, dir));
41605
41811
  if (axis != "horiz" && !sel.empty) return false;
41606
41812
  const end = atEndOfCell(view, axis, dir);
41607
41813
  if (end == null) return false;
@@ -41622,15 +41828,15 @@ function shiftArrow(axis, dir) {
41622
41828
  if (!view) return false;
41623
41829
  const sel = state.selection;
41624
41830
  let cellSel;
41625
- if (sel instanceof CellSelection) cellSel = sel;
41831
+ if (sel instanceof CellSelection2) cellSel = sel;
41626
41832
  else {
41627
41833
  const end = atEndOfCell(view, axis, dir);
41628
41834
  if (end == null) return false;
41629
- cellSel = new CellSelection(state.doc.resolve(end));
41835
+ cellSel = new CellSelection2(state.doc.resolve(end));
41630
41836
  }
41631
41837
  const $head = nextCell(cellSel.$headCell, axis, dir);
41632
41838
  if (!$head) return false;
41633
- return maybeSetSelection(state, dispatch, new CellSelection(cellSel.$anchorCell, $head));
41839
+ return maybeSetSelection(state, dispatch, new CellSelection2(cellSel.$anchorCell, $head));
41634
41840
  };
41635
41841
  }
41636
41842
  function atEndOfCell(view, axis, dir) {
@@ -41659,7 +41865,8 @@ import {
41659
41865
  ArrowRight as ArrowRight3,
41660
41866
  ArrowUp as ArrowUp2,
41661
41867
  Copy as Copy3,
41662
- Table as TableIcon2,
41868
+ Paintbrush as Paintbrush2,
41869
+ Table as TableIcon,
41663
41870
  Trash2 as Trash24
41664
41871
  } from "lucide-react";
41665
41872
 
@@ -41856,15 +42063,19 @@ function buildTableControlLayout(editor, surface, cell) {
41856
42063
  const map = TableMap4.get(tableInfo.node);
41857
42064
  const surfaceRect = surface.getBoundingClientRect();
41858
42065
  const tableRect = table.getBoundingClientRect();
42066
+ const explicitColumnWidths = Array.from(table.querySelectorAll("colgroup > col")).slice(0, map.width).map((column) => parsePixelMetric(column.style.width));
42067
+ const explicitTableWidth = parsePixelMetric(table.style.width) ?? (explicitColumnWidths.length === map.width && explicitColumnWidths.every((width) => width !== null) ? explicitColumnWidths.reduce((sum, width) => sum + width, 0) : null);
42068
+ const explicitRowHeights = rows.map((tableRow) => parsePixelMetric(tableRow.getAttribute("data-row-height")) ?? parsePixelMetric(tableRow.style.height));
42069
+ const explicitTableHeight = explicitRowHeights.every((height) => height !== null) ? explicitRowHeights.reduce((sum, height) => sum + height, 0) : null;
41859
42070
  const wrapperElement = table.closest(".tableWrapper");
41860
42071
  const wrapper = wrapperElement instanceof HTMLElement ? wrapperElement : null;
41861
42072
  const wrapperRect = wrapper?.getBoundingClientRect() ?? tableRect;
41862
42073
  const tableLeft = tableRect.left - surfaceRect.left + surface.scrollLeft;
41863
42074
  const tableTop = tableRect.top - surfaceRect.top + surface.scrollTop;
41864
- const avgRowHeight = metricOrFallback(tableRect.height / rows.length, FALLBACK_TABLE_ROW_HEIGHT);
41865
- const avgColumnWidth = metricOrFallback(tableRect.width / map.width, FALLBACK_TABLE_COLUMN_WIDTH);
41866
- const tableWidth = metricOrFallback(tableRect.width, avgColumnWidth * map.width);
41867
- const tableHeight = metricOrFallback(tableRect.height, avgRowHeight * rows.length);
42075
+ const tableWidth = metricOrFallback(tableRect.width, explicitTableWidth ?? FALLBACK_TABLE_COLUMN_WIDTH * map.width);
42076
+ const tableHeight = metricOrFallback(tableRect.height, explicitTableHeight ?? FALLBACK_TABLE_ROW_HEIGHT * rows.length);
42077
+ const avgRowHeight = metricOrFallback(tableHeight / rows.length, FALLBACK_TABLE_ROW_HEIGHT);
42078
+ const avgColumnWidth = metricOrFallback(tableWidth / map.width, FALLBACK_TABLE_COLUMN_WIDTH);
41868
42079
  const wrapperLeft = wrapperRect.left - surfaceRect.left + surface.scrollLeft;
41869
42080
  const wrapperTop = wrapperRect.top - surfaceRect.top + surface.scrollTop;
41870
42081
  const wrapperWidth = metricOrFallback(wrapperRect.width, tableWidth);
@@ -41974,7 +42185,7 @@ function buildTableHoverState({
41974
42185
  }
41975
42186
 
41976
42187
  // src/components/UEditor/table-drag-preview.tsx
41977
- import { Fragment as Fragment32, jsx as jsx95, jsxs as jsxs78 } from "react/jsx-runtime";
42188
+ import { Fragment as Fragment31, jsx as jsx95, jsxs as jsxs78 } from "react/jsx-runtime";
41978
42189
  function TableDragPreview({
41979
42190
  columnDragLabel,
41980
42191
  dragPreview,
@@ -41985,8 +42196,8 @@ function TableDragPreview({
41985
42196
  const expandPreviewWidth = dragPreview.kind === "add-column" ? layout.tableWidth + dragPreview.previewCols * layout.avgColumnWidth : layout.tableWidth;
41986
42197
  const expandPreviewHeight = dragPreview.kind === "add-row" ? layout.tableHeight + dragPreview.previewRows * layout.avgRowHeight : layout.tableHeight;
41987
42198
  const dragStatusText = dragPreview.kind === "row" ? `${rowDragLabel} ${dragPreview.originIndex + 1} -> ${dragPreview.targetIndex + 1}` : dragPreview.kind === "column" ? `${columnDragLabel} ${dragPreview.originIndex + 1} -> ${dragPreview.targetIndex + 1}` : dragPreview.kind === "add-row" ? `+${dragPreview.previewRows}R` : `+${dragPreview.previewCols}C`;
41988
- return /* @__PURE__ */ jsxs78(Fragment32, { children: [
41989
- dragPreview.kind === "row" && /* @__PURE__ */ jsxs78(Fragment32, { children: [
42199
+ return /* @__PURE__ */ jsxs78(Fragment31, { children: [
42200
+ dragPreview.kind === "row" && /* @__PURE__ */ jsxs78(Fragment31, { children: [
41990
42201
  /* @__PURE__ */ jsx95(
41991
42202
  "div",
41992
42203
  {
@@ -42014,7 +42225,7 @@ function TableDragPreview({
42014
42225
  }
42015
42226
  )
42016
42227
  ] }),
42017
- dragPreview.kind === "column" && /* @__PURE__ */ jsxs78(Fragment32, { children: [
42228
+ dragPreview.kind === "column" && /* @__PURE__ */ jsxs78(Fragment31, { children: [
42018
42229
  /* @__PURE__ */ jsx95(
42019
42230
  "div",
42020
42231
  {
@@ -42071,7 +42282,7 @@ function TableDragPreview({
42071
42282
  }
42072
42283
 
42073
42284
  // src/components/UEditor/table-add-rails.tsx
42074
- import { Fragment as Fragment33, jsx as jsx96, jsxs as jsxs79 } from "react/jsx-runtime";
42285
+ import { Fragment as Fragment32, jsx as jsx96, jsxs as jsxs79 } from "react/jsx-runtime";
42075
42286
  var ADD_COLUMN_RAIL_GAP = 4;
42076
42287
  var ADD_ROW_RAIL_GAP = 4;
42077
42288
  function TableAddRails({
@@ -42092,7 +42303,7 @@ function TableAddRails({
42092
42303
  const rowRailLeft = visibleBounds.left;
42093
42304
  const showColumnRail = controlsVisible || addColumnVisible;
42094
42305
  const showRowRail = controlsVisible || addRowVisible;
42095
- return /* @__PURE__ */ jsxs79(Fragment33, { children: [
42306
+ return /* @__PURE__ */ jsxs79(Fragment32, { children: [
42096
42307
  /* @__PURE__ */ jsx96(
42097
42308
  Tooltip,
42098
42309
  {
@@ -42223,7 +42434,7 @@ function TableControlMenu({
42223
42434
  transform: shown ? "scale(1)" : "scale(0.82)",
42224
42435
  pointerEvents: shown ? "auto" : "none"
42225
42436
  },
42226
- children: /* @__PURE__ */ jsx97(MoreHorizontal2, { className: "h-4 w-4" })
42437
+ children: /* @__PURE__ */ jsx97(MoreHorizontal2, { "aria-hidden": "true", className: "h-4 w-4" })
42227
42438
  }
42228
42439
  )
42229
42440
  }
@@ -42236,7 +42447,7 @@ function TableControlMenu({
42236
42447
 
42237
42448
  // src/components/UEditor/table-axis-handles.tsx
42238
42449
  import { GripHorizontal, GripVertical as GripVertical3 } from "lucide-react";
42239
- import { Fragment as Fragment34, jsx as jsx98 } from "react/jsx-runtime";
42450
+ import { Fragment as Fragment33, jsx as jsx98 } from "react/jsx-runtime";
42240
42451
  var IDLE_HANDLE_SCALE = "0.78";
42241
42452
  function TableRowHandles({
42242
42453
  activeRowIndex,
@@ -42250,7 +42461,7 @@ function TableRowHandles({
42250
42461
  rowHandleLeft,
42251
42462
  rowHandles
42252
42463
  }) {
42253
- return /* @__PURE__ */ jsx98(Fragment34, { children: rowHandles.map((rowHandle) => {
42464
+ return /* @__PURE__ */ jsx98(Fragment33, { children: rowHandles.map((rowHandle) => {
42254
42465
  const menuKey = `row:${rowHandle.index}`;
42255
42466
  const isActive = rowHandle.index === activeRowIndex;
42256
42467
  const visible = controlsVisible || hoverRowHandleIndex === rowHandle.index || openMenuKey === menuKey;
@@ -42321,7 +42532,7 @@ function TableColumnHandles({
42321
42532
  onStartDrag,
42322
42533
  openMenuKey
42323
42534
  }) {
42324
- return /* @__PURE__ */ jsx98(Fragment34, { children: columnHandles.map((columnHandle) => {
42535
+ return /* @__PURE__ */ jsx98(Fragment33, { children: columnHandles.map((columnHandle) => {
42325
42536
  const menuKey = `column:${columnHandle.index}`;
42326
42537
  const isActive = columnHandle.index === activeColumnIndex;
42327
42538
  const visible = controlsVisible || hoverColumnHandleIndex === columnHandle.index || openMenuKey === menuKey;
@@ -42381,8 +42592,236 @@ function TableColumnHandles({
42381
42592
  }) });
42382
42593
  }
42383
42594
 
42595
+ // src/components/UEditor/table-resize-handles.tsx
42596
+ import { MoveDiagonal2 } from "lucide-react";
42597
+ import { jsx as jsx99, jsxs as jsxs80 } from "react/jsx-runtime";
42598
+ var HANDLE_BASE_CLASS = cn(
42599
+ "pointer-events-auto absolute z-10 inline-flex touch-none items-center justify-center rounded-md",
42600
+ "bg-background/95 text-primary shadow-sm backdrop-blur-sm",
42601
+ "transition-[color,background-color,box-shadow,transform] duration-150",
42602
+ "hover:bg-primary hover:text-primary-foreground hover:shadow-md active:scale-95",
42603
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2"
42604
+ );
42605
+ function TableResizeHandles({
42606
+ active,
42607
+ ctrlHint,
42608
+ frameRef,
42609
+ layout,
42610
+ onStartResize,
42611
+ resizeBothLabel
42612
+ }) {
42613
+ return /* @__PURE__ */ jsxs80(
42614
+ "div",
42615
+ {
42616
+ ref: frameRef,
42617
+ "data-table-resize-frame": "",
42618
+ "data-resizing": active ? "true" : "false",
42619
+ className: cn(
42620
+ "pointer-events-none absolute z-[38] box-border border border-primary/55",
42621
+ active && "border-primary bg-primary/[0.03]"
42622
+ ),
42623
+ style: {
42624
+ left: layout.tableLeft,
42625
+ top: layout.tableTop,
42626
+ width: layout.tableWidth,
42627
+ height: layout.tableHeight
42628
+ },
42629
+ children: [
42630
+ /* @__PURE__ */ jsx99(
42631
+ "button",
42632
+ {
42633
+ type: "button",
42634
+ "aria-label": resizeBothLabel,
42635
+ title: `${resizeBothLabel}. ${ctrlHint}`,
42636
+ "data-table-resize-handle": "both",
42637
+ className: cn(
42638
+ HANDLE_BASE_CLASS,
42639
+ "bottom-[-28px] right-[-30px] h-6 w-6 cursor-nwse-resize",
42640
+ active && "bg-primary text-primary-foreground shadow-md"
42641
+ ),
42642
+ onPointerDown: onStartResize,
42643
+ children: /* @__PURE__ */ jsx99(MoveDiagonal2, { "aria-hidden": "true", className: "h-3.5 w-3.5", strokeWidth: 2.25 })
42644
+ }
42645
+ ),
42646
+ active ? /* @__PURE__ */ jsx99(
42647
+ "span",
42648
+ {
42649
+ role: "status",
42650
+ "aria-live": "polite",
42651
+ "data-table-resize-dimensions": "",
42652
+ className: "absolute bottom-2 right-2 rounded bg-foreground/85 px-1.5 py-0.5 text-[10px] font-medium text-background shadow-sm",
42653
+ children: `${Math.round(layout.tableWidth)} \xD7 ${Math.round(layout.tableHeight)}`
42654
+ }
42655
+ ) : null
42656
+ ]
42657
+ }
42658
+ );
42659
+ }
42660
+
42661
+ // src/components/UEditor/table-size-utils.ts
42662
+ var MAX_TABLE_DIMENSION = 8192;
42663
+ function positiveMetric(value, fallback) {
42664
+ return typeof value === "number" && Number.isFinite(value) && value > 0 ? value : fallback;
42665
+ }
42666
+ function normalizeWeightsToTotal(values, total, minimum) {
42667
+ if (values.length === 0) return [];
42668
+ const safeTotal = Math.max(values.length * minimum, Math.round(total));
42669
+ const positiveValues = values.map((value) => positiveMetric(value, 1));
42670
+ const weightSum = positiveValues.reduce((sum, value) => sum + value, 0);
42671
+ const raw = positiveValues.map((value) => value / weightSum * safeTotal);
42672
+ const normalized = raw.map((value) => Math.max(minimum, Math.round(value)));
42673
+ let difference = safeTotal - normalized.reduce((sum, value) => sum + value, 0);
42674
+ while (difference !== 0) {
42675
+ let changed = false;
42676
+ for (let index = normalized.length - 1; index >= 0 && difference !== 0; index -= 1) {
42677
+ if (difference < 0 && normalized[index] <= minimum) continue;
42678
+ normalized[index] += difference > 0 ? 1 : -1;
42679
+ difference += difference > 0 ? -1 : 1;
42680
+ changed = true;
42681
+ }
42682
+ if (!changed) break;
42683
+ }
42684
+ return normalized;
42685
+ }
42686
+ function getLogicalColumnWidths(table, tableMap, fallback) {
42687
+ return Array.from({ length: tableMap.width }, (_, columnIndex) => {
42688
+ const relativeCellPos = tableMap.positionAt(0, columnIndex, table);
42689
+ const cell = table.nodeAt(relativeCellPos);
42690
+ if (!cell) return fallback;
42691
+ const cellStartColumn = tableMap.colCount(relativeCellPos);
42692
+ const widthIndex = columnIndex - cellStartColumn;
42693
+ const colwidth = cell.attrs.colwidth;
42694
+ return positiveMetric(colwidth?.[widthIndex], fallback);
42695
+ });
42696
+ }
42697
+ function getLogicalRowHeights(table, fallback) {
42698
+ const heights = [];
42699
+ table.forEach((row) => {
42700
+ heights.push(positiveMetric(row.attrs.rowHeight, fallback));
42701
+ });
42702
+ return heights;
42703
+ }
42704
+ function createTableSizeSnapshot(editor, anchorPos, startWidth, startHeight) {
42705
+ const tableInfo = findTableInfo(editor, anchorPos);
42706
+ if (!tableInfo) return null;
42707
+ const tableMap = TableMap4.get(tableInfo.node);
42708
+ if (tableMap.width === 0 || tableMap.height === 0) return null;
42709
+ const safeWidth = Math.max(tableMap.width * MIN_RESIZED_TABLE_COLUMN_WIDTH, Math.round(startWidth));
42710
+ const safeHeight = Math.max(tableMap.height * MIN_TABLE_ROW_HEIGHT, Math.round(startHeight));
42711
+ const fallbackColumnWidth = safeWidth / tableMap.width;
42712
+ const fallbackRowHeight = safeHeight / tableMap.height;
42713
+ return {
42714
+ anchorPos,
42715
+ tablePos: tableInfo.pos,
42716
+ startWidth: safeWidth,
42717
+ startHeight: safeHeight,
42718
+ columnWidths: normalizeWeightsToTotal(
42719
+ getLogicalColumnWidths(tableInfo.node, tableMap, fallbackColumnWidth),
42720
+ safeWidth,
42721
+ MIN_RESIZED_TABLE_COLUMN_WIDTH
42722
+ ),
42723
+ rowHeights: normalizeWeightsToTotal(
42724
+ getLogicalRowHeights(tableInfo.node, fallbackRowHeight),
42725
+ safeHeight,
42726
+ MIN_TABLE_ROW_HEIGHT
42727
+ ),
42728
+ minWidth: tableMap.width * MIN_RESIZED_TABLE_COLUMN_WIDTH,
42729
+ minHeight: tableMap.height * MIN_TABLE_ROW_HEIGHT
42730
+ };
42731
+ }
42732
+ function resolveTableResizeDimensions({
42733
+ deltaX,
42734
+ deltaY,
42735
+ lockAxis,
42736
+ preserveRatio,
42737
+ snapshot
42738
+ }) {
42739
+ let width = snapshot.startWidth + deltaX;
42740
+ let height = snapshot.startHeight + deltaY;
42741
+ if (preserveRatio) {
42742
+ const horizontalDrag = Math.abs(deltaX) >= Math.abs(deltaY);
42743
+ const scale = horizontalDrag ? width / snapshot.startWidth : height / snapshot.startHeight;
42744
+ const minScale = Math.max(
42745
+ snapshot.minWidth / snapshot.startWidth,
42746
+ snapshot.minHeight / snapshot.startHeight
42747
+ );
42748
+ const maxScale = Math.min(
42749
+ MAX_TABLE_DIMENSION / snapshot.startWidth,
42750
+ MAX_TABLE_DIMENSION / snapshot.startHeight
42751
+ );
42752
+ const safeScale = Math.min(Math.max(scale, minScale), maxScale);
42753
+ width = snapshot.startWidth * safeScale;
42754
+ height = snapshot.startHeight * safeScale;
42755
+ } else if (lockAxis) {
42756
+ if (Math.abs(deltaX) >= Math.abs(deltaY)) {
42757
+ height = snapshot.startHeight;
42758
+ } else {
42759
+ width = snapshot.startWidth;
42760
+ }
42761
+ }
42762
+ return {
42763
+ width: Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minWidth, Math.round(width))),
42764
+ height: Math.min(MAX_TABLE_DIMENSION, Math.max(snapshot.minHeight, Math.round(height)))
42765
+ };
42766
+ }
42767
+ function arraysEqual(left, right) {
42768
+ return Array.isArray(left) && left.length === right.length && left.every((value, index) => value === right[index]);
42769
+ }
42770
+ function applyTableSize(editor, snapshot, dimensions) {
42771
+ const table = editor.state.doc.nodeAt(snapshot.tablePos);
42772
+ if (!table || table.type.name !== "table") return false;
42773
+ const tableMap = TableMap4.get(table);
42774
+ if (tableMap.width !== snapshot.columnWidths.length || tableMap.height !== snapshot.rowHeights.length) {
42775
+ return false;
42776
+ }
42777
+ const resizeWidth = dimensions.width !== snapshot.startWidth;
42778
+ const resizeHeight = dimensions.height !== snapshot.startHeight;
42779
+ if (!resizeWidth && !resizeHeight) return false;
42780
+ const tableStart = snapshot.tablePos + 1;
42781
+ const transaction = editor.state.tr;
42782
+ if (resizeWidth) {
42783
+ const nextColumnWidths = normalizeWeightsToTotal(
42784
+ snapshot.columnWidths,
42785
+ dimensions.width,
42786
+ MIN_RESIZED_TABLE_COLUMN_WIDTH
42787
+ );
42788
+ const seenCellPositions = /* @__PURE__ */ new Set();
42789
+ for (const relativeCellPos of tableMap.map) {
42790
+ if (seenCellPositions.has(relativeCellPos)) continue;
42791
+ seenCellPositions.add(relativeCellPos);
42792
+ const cell = table.nodeAt(relativeCellPos);
42793
+ if (!cell) continue;
42794
+ const cellRect = tableMap.findCell(relativeCellPos);
42795
+ const colwidth = nextColumnWidths.slice(cellRect.left, cellRect.right);
42796
+ if (arraysEqual(cell.attrs.colwidth, colwidth)) continue;
42797
+ transaction.setNodeMarkup(tableStart + relativeCellPos, void 0, {
42798
+ ...cell.attrs,
42799
+ colwidth
42800
+ });
42801
+ }
42802
+ }
42803
+ if (resizeHeight) {
42804
+ const nextRowHeights = normalizeWeightsToTotal(
42805
+ snapshot.rowHeights,
42806
+ dimensions.height,
42807
+ MIN_TABLE_ROW_HEIGHT
42808
+ );
42809
+ table.forEach((row, offset, rowIndex) => {
42810
+ const rowHeight = nextRowHeights[rowIndex];
42811
+ if (row.attrs.rowHeight === rowHeight) return;
42812
+ transaction.setNodeMarkup(tableStart + offset, void 0, {
42813
+ ...row.attrs,
42814
+ rowHeight
42815
+ });
42816
+ });
42817
+ }
42818
+ if (!transaction.docChanged) return false;
42819
+ editor.view.dispatch(transaction);
42820
+ return true;
42821
+ }
42822
+
42384
42823
  // src/components/UEditor/table-controls.tsx
42385
- import { Fragment as Fragment35, jsx as jsx99, jsxs as jsxs80 } from "react/jsx-runtime";
42824
+ import { Fragment as Fragment34, jsx as jsx100, jsxs as jsxs81 } from "react/jsx-runtime";
42386
42825
  var TABLE_MENU_TOP_OFFSET = 10;
42387
42826
  function nearestIndex(centers, position) {
42388
42827
  let bestIndex = 0;
@@ -42406,15 +42845,18 @@ function getSelectedCell(editor) {
42406
42845
  const domAtPos = editor.view.domAtPos(editor.state.selection.from);
42407
42846
  return getCellFromTarget(domAtPos.node);
42408
42847
  }
42409
- function TableControls({ editor, containerRef }) {
42848
+ function TableControls({ editor, containerRef, showCellInspector = true }) {
42410
42849
  const t = useSmartTranslations("UEditor");
42411
42850
  const [layout, setLayout] = React86.useState(null);
42412
42851
  const [dragPreview, setDragPreview] = React86.useState(null);
42852
+ const [tableResizeActive, setTableResizeActive] = React86.useState(false);
42413
42853
  const [hoverState, setHoverState] = React86.useState(DEFAULT_TABLE_HOVER_STATE);
42414
42854
  const [openMenuKey, setOpenMenuKey] = React86.useState(null);
42415
42855
  const layoutRef = React86.useRef(null);
42416
42856
  const dragStateRef = React86.useRef(null);
42417
42857
  const syncFrameRef = React86.useRef(null);
42858
+ const tableResizeFrameRef = React86.useRef(null);
42859
+ const tableResizePreviewFrameRef = React86.useRef(null);
42418
42860
  React86.useEffect(() => {
42419
42861
  layoutRef.current = layout;
42420
42862
  }, [layout]);
@@ -42452,11 +42894,44 @@ function TableControls({ editor, containerRef }) {
42452
42894
  return cell ? buildTableControlLayout(editor, surface, cell) : null;
42453
42895
  });
42454
42896
  }, [containerRef, editor]);
42897
+ const updateTableResizePreview = React86.useCallback((dimensions) => {
42898
+ const frame = tableResizeFrameRef.current;
42899
+ if (!frame) return;
42900
+ frame.style.width = `${dimensions.width}px`;
42901
+ frame.style.height = `${dimensions.height}px`;
42902
+ const dimensionsLabel = frame.querySelector("[data-table-resize-dimensions]");
42903
+ if (dimensionsLabel) {
42904
+ dimensionsLabel.textContent = `${dimensions.width} \xD7 ${dimensions.height}`;
42905
+ }
42906
+ }, []);
42907
+ const resetTableResizePreview = React86.useCallback(() => {
42908
+ const activeLayout = layoutRef.current;
42909
+ if (!activeLayout) return;
42910
+ updateTableResizePreview({
42911
+ width: Math.round(activeLayout.tableWidth),
42912
+ height: Math.round(activeLayout.tableHeight)
42913
+ });
42914
+ }, [updateTableResizePreview]);
42455
42915
  const clearDrag = React86.useCallback(() => {
42916
+ const dragState = dragStateRef.current;
42917
+ if (dragState?.kind === "resize-table") {
42918
+ try {
42919
+ if (dragState.pointerTarget.hasPointerCapture?.(dragState.pointerId)) {
42920
+ dragState.pointerTarget.releasePointerCapture(dragState.pointerId);
42921
+ }
42922
+ } catch {
42923
+ }
42924
+ }
42925
+ if (tableResizePreviewFrameRef.current !== null) {
42926
+ window.cancelAnimationFrame(tableResizePreviewFrameRef.current);
42927
+ tableResizePreviewFrameRef.current = null;
42928
+ }
42456
42929
  dragStateRef.current = null;
42457
42930
  setDragPreview(null);
42931
+ setTableResizeActive(false);
42932
+ resetTableResizePreview();
42458
42933
  document.body.style.cursor = "";
42459
- }, []);
42934
+ }, [resetTableResizePreview]);
42460
42935
  const updateHoverState = React86.useCallback((event) => {
42461
42936
  const activeLayout = layoutRef.current;
42462
42937
  const surface = containerRef.current;
@@ -42496,9 +42971,26 @@ function TableControls({ editor, containerRef }) {
42496
42971
  const cell = event ? getCellFromTarget(event.target) : null;
42497
42972
  syncFromCell(cell ?? getSelectedCell(editor));
42498
42973
  };
42974
+ const handleDoubleClick = (event) => {
42975
+ if (event.button !== 0) return;
42976
+ const cell = getCellFromTarget(event.target);
42977
+ if (!cell || cell.hasAttribute("data-formula")) return;
42978
+ const surface2 = containerRef.current;
42979
+ const nextLayout = surface2 ? buildTableControlLayout(editor, surface2, cell) : null;
42980
+ if (!nextLayout) return;
42981
+ const didSelect = editor.commands.setCellSelection({
42982
+ anchorCell: nextLayout.cellPos,
42983
+ headCell: nextLayout.cellPos
42984
+ });
42985
+ if (!didSelect) return;
42986
+ event.preventDefault();
42987
+ editor.view.focus();
42988
+ setLayout(nextLayout);
42989
+ };
42499
42990
  proseMirror.addEventListener("mouseover", handleMouseOver);
42500
42991
  proseMirror.addEventListener("mouseleave", handleMouseLeave2);
42501
42992
  proseMirror.addEventListener("click", handleFocusIn);
42993
+ proseMirror.addEventListener("dblclick", handleDoubleClick);
42502
42994
  proseMirror.addEventListener("mouseup", handleFocusIn);
42503
42995
  proseMirror.addEventListener("focusin", handleFocusIn);
42504
42996
  surface.addEventListener("mouseover", handleSurfaceMouseMove);
@@ -42513,6 +43005,7 @@ function TableControls({ editor, containerRef }) {
42513
43005
  proseMirror.removeEventListener("mouseover", handleMouseOver);
42514
43006
  proseMirror.removeEventListener("mouseleave", handleMouseLeave2);
42515
43007
  proseMirror.removeEventListener("click", handleFocusIn);
43008
+ proseMirror.removeEventListener("dblclick", handleDoubleClick);
42516
43009
  proseMirror.removeEventListener("mouseup", handleFocusIn);
42517
43010
  proseMirror.removeEventListener("focusin", handleFocusIn);
42518
43011
  surface.removeEventListener("mouseover", handleSurfaceMouseMove);
@@ -42563,6 +43056,42 @@ function TableControls({ editor, containerRef }) {
42563
43056
  const canExpandTable = Boolean(layout);
42564
43057
  const controlsVisible = dragPreview !== null;
42565
43058
  const tableMenuOpen = openMenuKey === "table";
43059
+ const startTableResize = React86.useCallback((event) => {
43060
+ if (event.button !== 0 || dragStateRef.current) return;
43061
+ const activeLayout = layoutRef.current;
43062
+ if (!activeLayout) return;
43063
+ const snapshot = createTableSizeSnapshot(
43064
+ editor,
43065
+ activeLayout.cellPos,
43066
+ activeLayout.tableWidth,
43067
+ activeLayout.tableHeight
43068
+ );
43069
+ if (!snapshot) return;
43070
+ event.preventDefault();
43071
+ event.stopPropagation();
43072
+ try {
43073
+ event.currentTarget.setPointerCapture?.(event.pointerId);
43074
+ } catch {
43075
+ }
43076
+ setOpenMenuKey(null);
43077
+ setHoverState(DEFAULT_TABLE_HOVER_STATE);
43078
+ setTableResizeActive(true);
43079
+ const pendingDimensions = {
43080
+ width: snapshot.startWidth,
43081
+ height: snapshot.startHeight
43082
+ };
43083
+ dragStateRef.current = {
43084
+ kind: "resize-table",
43085
+ pointerId: event.pointerId,
43086
+ pointerTarget: event.currentTarget,
43087
+ startX: event.clientX,
43088
+ startY: event.clientY,
43089
+ snapshot,
43090
+ pendingDimensions
43091
+ };
43092
+ updateTableResizePreview(pendingDimensions);
43093
+ document.body.style.cursor = "nwse-resize";
43094
+ }, [editor, updateTableResizePreview]);
42566
43095
  const startAddColumnDrag = React86.useCallback(() => {
42567
43096
  setOpenMenuKey(null);
42568
43097
  dragStateRef.current = { kind: "add-column", previewCols: 1 };
@@ -42618,6 +43147,9 @@ function TableControls({ editor, containerRef }) {
42618
43147
  const surfaceRect = surface.getBoundingClientRect();
42619
43148
  const relativeX = event.clientX - surfaceRect.left + surface.scrollLeft;
42620
43149
  const relativeY = event.clientY - surfaceRect.top + surface.scrollTop;
43150
+ if (dragState.kind === "resize-table") {
43151
+ return;
43152
+ }
42621
43153
  if (dragState.kind === "row") {
42622
43154
  const targetHandleIndex = nearestIndex(activeLayout.rowHandles.map((item) => item.center), relativeY);
42623
43155
  const targetRow = activeLayout.rowHandles[targetHandleIndex];
@@ -42662,7 +43194,7 @@ function TableControls({ editor, containerRef }) {
42662
43194
  };
42663
43195
  const handleMouseUp = () => {
42664
43196
  const dragState = dragStateRef.current;
42665
- if (!dragState) return;
43197
+ if (!dragState || dragState.kind === "resize-table") return;
42666
43198
  if (dragState.kind === "row" && dragState.originIndex !== dragState.targetIndex) {
42667
43199
  moveTableRow({
42668
43200
  from: dragState.originIndex,
@@ -42698,9 +43230,76 @@ function TableControls({ editor, containerRef }) {
42698
43230
  window.removeEventListener("blur", clearDrag);
42699
43231
  };
42700
43232
  }, [clearDrag, containerRef, editor, expandTableBy, scheduleSyncFromSelection]);
43233
+ React86.useEffect(() => {
43234
+ const handlePointerMove = (event) => {
43235
+ const dragState = dragStateRef.current;
43236
+ if (!dragState || dragState.kind !== "resize-table" || event.pointerId !== dragState.pointerId) return;
43237
+ dragState.pendingDimensions = resolveTableResizeDimensions({
43238
+ deltaX: event.clientX - dragState.startX,
43239
+ deltaY: event.clientY - dragState.startY,
43240
+ lockAxis: event.ctrlKey && !event.shiftKey,
43241
+ preserveRatio: event.ctrlKey && event.shiftKey,
43242
+ snapshot: dragState.snapshot
43243
+ });
43244
+ if (tableResizePreviewFrameRef.current === null) {
43245
+ tableResizePreviewFrameRef.current = window.requestAnimationFrame(() => {
43246
+ tableResizePreviewFrameRef.current = null;
43247
+ const currentDragState = dragStateRef.current;
43248
+ if (!currentDragState || currentDragState.kind !== "resize-table") return;
43249
+ updateTableResizePreview(currentDragState.pendingDimensions);
43250
+ });
43251
+ }
43252
+ document.body.style.cursor = "nwse-resize";
43253
+ if (event.cancelable) event.preventDefault();
43254
+ };
43255
+ const finishTableResize = (event, commit) => {
43256
+ const dragState = dragStateRef.current;
43257
+ if (!dragState || dragState.kind !== "resize-table" || event.pointerId !== dragState.pointerId) return;
43258
+ if (tableResizePreviewFrameRef.current !== null) {
43259
+ window.cancelAnimationFrame(tableResizePreviewFrameRef.current);
43260
+ tableResizePreviewFrameRef.current = null;
43261
+ }
43262
+ updateTableResizePreview(dragState.pendingDimensions);
43263
+ if (commit && applyTableSize(editor, dragState.snapshot, dragState.pendingDimensions)) {
43264
+ scheduleSyncFromSelection();
43265
+ }
43266
+ clearDrag();
43267
+ };
43268
+ const handlePointerUp = (event) => finishTableResize(event, true);
43269
+ const handlePointerCancel = (event) => finishTableResize(event, false);
43270
+ window.addEventListener("pointermove", handlePointerMove, { passive: false });
43271
+ window.addEventListener("pointerup", handlePointerUp);
43272
+ window.addEventListener("pointercancel", handlePointerCancel);
43273
+ return () => {
43274
+ window.removeEventListener("pointermove", handlePointerMove);
43275
+ window.removeEventListener("pointerup", handlePointerUp);
43276
+ window.removeEventListener("pointercancel", handlePointerCancel);
43277
+ if (tableResizePreviewFrameRef.current !== null) {
43278
+ window.cancelAnimationFrame(tableResizePreviewFrameRef.current);
43279
+ tableResizePreviewFrameRef.current = null;
43280
+ }
43281
+ };
43282
+ }, [clearDrag, editor, scheduleSyncFromSelection, updateTableResizePreview]);
43283
+ const openCellInspector = React86.useCallback(() => {
43284
+ const cellPos = layoutRef.current?.cellPos;
43285
+ if (!showCellInspector || cellPos == null) return;
43286
+ const didSelect = editor.commands.setCellSelection({
43287
+ anchorCell: cellPos,
43288
+ headCell: cellPos
43289
+ });
43290
+ if (!didSelect) return;
43291
+ window.requestAnimationFrame(() => {
43292
+ if (!editor.isDestroyed) editor.view.focus();
43293
+ });
43294
+ }, [editor, showCellInspector]);
42701
43295
  const menuItems = React86.useMemo(() => {
42702
43296
  if (!layout) return [];
42703
43297
  return [
43298
+ ...showCellInspector ? [{
43299
+ label: t("tableMenu.cellFormatting"),
43300
+ icon: Paintbrush2,
43301
+ onClick: openCellInspector
43302
+ }] : [],
42704
43303
  {
42705
43304
  label: t("tableMenu.alignLeft"),
42706
43305
  icon: AlignLeft3,
@@ -42738,12 +43337,12 @@ function TableControls({ editor, containerRef }) {
42738
43337
  },
42739
43338
  {
42740
43339
  label: t("tableMenu.toggleHeaderRow"),
42741
- icon: TableIcon2,
43340
+ icon: TableIcon,
42742
43341
  onClick: () => runAtActiveCell((chain) => chain.toggleHeaderRow())
42743
43342
  },
42744
43343
  {
42745
43344
  label: t("tableMenu.toggleHeaderColumn"),
42746
- icon: TableIcon2,
43345
+ icon: TableIcon,
42747
43346
  onClick: () => runAtActiveCell((chain) => chain.toggleHeaderColumn())
42748
43347
  },
42749
43348
  {
@@ -42765,7 +43364,7 @@ function TableControls({ editor, containerRef }) {
42765
43364
  destructive: true
42766
43365
  }
42767
43366
  ];
42768
- }, [editor, layout, runAtActiveCell, t]);
43367
+ }, [editor, layout, openCellInspector, runAtActiveCell, showCellInspector, t]);
42769
43368
  const getRowHandleMenuItems = React86.useCallback((rowHandle) => [
42770
43369
  {
42771
43370
  label: t("tableMenu.addRowBefore"),
@@ -42784,7 +43383,7 @@ function TableControls({ editor, containerRef }) {
42784
43383
  },
42785
43384
  {
42786
43385
  label: t("tableMenu.clearRowContents"),
42787
- icon: TableIcon2,
43386
+ icon: TableIcon,
42788
43387
  onClick: () => clearRowAt(rowHandle.index, rowHandle.cellPos)
42789
43388
  },
42790
43389
  {
@@ -42812,7 +43411,7 @@ function TableControls({ editor, containerRef }) {
42812
43411
  },
42813
43412
  {
42814
43413
  label: t("tableMenu.clearColumnContents"),
42815
- icon: TableIcon2,
43414
+ icon: TableIcon,
42816
43415
  onClick: () => clearColumnAt(columnHandle.index, columnHandle.cellPos)
42817
43416
  },
42818
43417
  {
@@ -42829,8 +43428,8 @@ function TableControls({ editor, containerRef }) {
42829
43428
  const menuLeft = Math.max(8, layout.tableLeft);
42830
43429
  const rowHandleLeft = layout.tableLeft - 12;
42831
43430
  const columnHandleTop = layout.tableTop - 12;
42832
- return /* @__PURE__ */ jsxs80(Fragment35, { children: [
42833
- /* @__PURE__ */ jsx99(
43431
+ return /* @__PURE__ */ jsxs81(Fragment34, { children: [
43432
+ /* @__PURE__ */ jsx100(
42834
43433
  TableRowHandles,
42835
43434
  {
42836
43435
  activeRowIndex: layout.activeRowIndex,
@@ -42847,7 +43446,7 @@ function TableControls({ editor, containerRef }) {
42847
43446
  rowHandles: layout.rowHandles
42848
43447
  }
42849
43448
  ),
42850
- /* @__PURE__ */ jsx99(
43449
+ /* @__PURE__ */ jsx100(
42851
43450
  TableColumnHandles,
42852
43451
  {
42853
43452
  activeColumnIndex: layout.activeColumnIndex,
@@ -42864,7 +43463,7 @@ function TableControls({ editor, containerRef }) {
42864
43463
  openMenuKey
42865
43464
  }
42866
43465
  ),
42867
- /* @__PURE__ */ jsx99(
43466
+ /* @__PURE__ */ jsx100(
42868
43467
  TableControlMenu,
42869
43468
  {
42870
43469
  controlsVisible,
@@ -42879,7 +43478,18 @@ function TableControls({ editor, containerRef }) {
42879
43478
  top: menuTop
42880
43479
  }
42881
43480
  ),
42882
- /* @__PURE__ */ jsx99(
43481
+ dragPreview === null && /* @__PURE__ */ jsx100(
43482
+ TableResizeHandles,
43483
+ {
43484
+ active: tableResizeActive,
43485
+ ctrlHint: t("tableMenu.resizeCtrlHint"),
43486
+ frameRef: tableResizeFrameRef,
43487
+ layout,
43488
+ onStartResize: startTableResize,
43489
+ resizeBothLabel: t("tableMenu.resizeBoth")
43490
+ }
43491
+ ),
43492
+ /* @__PURE__ */ jsx100(
42883
43493
  TableAddRails,
42884
43494
  {
42885
43495
  addColumnVisible: hoverState.addColumnVisible,
@@ -42893,7 +43503,7 @@ function TableControls({ editor, containerRef }) {
42893
43503
  quickAddRowLabel: t("tableMenu.quickAddRowAfter")
42894
43504
  }
42895
43505
  ),
42896
- /* @__PURE__ */ jsx99(
43506
+ /* @__PURE__ */ jsx100(
42897
43507
  TableDragPreview,
42898
43508
  {
42899
43509
  columnDragLabel: t("tableMenu.dragColumn"),
@@ -44011,7 +44621,7 @@ function useFormulaCoordinateOverlay(editor, containerRef, labels) {
44011
44621
 
44012
44622
  // src/components/UEditor/menu-bar.tsx
44013
44623
  import React89, { useMemo as useMemo26, useRef as useRef39, useState as useState52 } from "react";
44014
- import { useEditorState as useEditorState3 } from "@tiptap/react";
44624
+ import { useEditorState as useEditorState4 } from "@tiptap/react";
44015
44625
  import {
44016
44626
  AlignCenter as AlignCenter4,
44017
44627
  AlignJustify as AlignJustify2,
@@ -44035,7 +44645,7 @@ import {
44035
44645
  Strikethrough as StrikethroughIcon2,
44036
44646
  Subscript as SubscriptIcon2,
44037
44647
  Superscript as SuperscriptIcon2,
44038
- Table as TableIcon3,
44648
+ Table as TableIcon2,
44039
44649
  Trash2 as Trash25,
44040
44650
  Underline as UnderlineIcon2,
44041
44651
  Undo as UndoIcon,
@@ -44182,14 +44792,14 @@ function prepareUEditorPreviewHtml(html) {
44182
44792
  }
44183
44793
 
44184
44794
  // src/components/UEditor/menu-bar.tsx
44185
- import { Fragment as Fragment36, jsx as jsx100, jsxs as jsxs81 } from "react/jsx-runtime";
44795
+ import { Fragment as Fragment35, jsx as jsx101, jsxs as jsxs82 } from "react/jsx-runtime";
44186
44796
  function MenuTableInsertGrid({
44187
44797
  insertLabel,
44188
44798
  previewTemplate,
44189
44799
  onInsert
44190
44800
  }) {
44191
44801
  const closeMenu = useDropdownMenuClose();
44192
- return /* @__PURE__ */ jsx100(
44802
+ return /* @__PURE__ */ jsx101(
44193
44803
  TableInsertGrid,
44194
44804
  {
44195
44805
  insertLabel,
@@ -44205,9 +44815,9 @@ function renderMenuItems(items) {
44205
44815
  return items.map((item, i) => {
44206
44816
  switch (item.type) {
44207
44817
  case "separator":
44208
- return /* @__PURE__ */ jsx100(DropdownMenuSeparator, {}, i);
44818
+ return /* @__PURE__ */ jsx101(DropdownMenuSeparator, {}, i);
44209
44819
  case "action":
44210
- return /* @__PURE__ */ jsx100(
44820
+ return /* @__PURE__ */ jsx101(
44211
44821
  DropdownMenuItem,
44212
44822
  {
44213
44823
  label: item.label,
@@ -44221,9 +44831,9 @@ function renderMenuItems(items) {
44221
44831
  i
44222
44832
  );
44223
44833
  case "sub":
44224
- return /* @__PURE__ */ jsx100(DropdownMenuSub, { label: item.label, icon: item.icon, disabled: item.disabled, children: renderMenuItems(item.items) }, i);
44834
+ return /* @__PURE__ */ jsx101(DropdownMenuSub, { label: item.label, icon: item.icon, disabled: item.disabled, children: renderMenuItems(item.items) }, i);
44225
44835
  case "custom":
44226
- return /* @__PURE__ */ jsx100(React89.Fragment, { children: item.render() }, item.key);
44836
+ return /* @__PURE__ */ jsx101(React89.Fragment, { children: item.render() }, item.key);
44227
44837
  }
44228
44838
  });
44229
44839
  }
@@ -44520,12 +45130,12 @@ function buildTableMenuItems(t, editor, onInsertTable) {
44520
45130
  {
44521
45131
  type: "sub",
44522
45132
  label: t("menubar.insertTable"),
44523
- icon: TableIcon3,
45133
+ icon: TableIcon2,
44524
45134
  items: [
44525
45135
  {
44526
45136
  type: "custom",
44527
45137
  key: "table-insert-grid",
44528
- render: () => /* @__PURE__ */ jsx100(
45138
+ render: () => /* @__PURE__ */ jsx101(
44529
45139
  MenuTableInsertGrid,
44530
45140
  {
44531
45141
  insertLabel: t("tableMenu.insertTable"),
@@ -44600,7 +45210,7 @@ function buildTableMenuItems(t, editor, onInsertTable) {
44600
45210
  ];
44601
45211
  }
44602
45212
  var MenuBarTrigger = React89.forwardRef(
44603
- ({ children, className, ...props }, ref) => /* @__PURE__ */ jsx100(
45213
+ ({ children, className, ...props }, ref) => /* @__PURE__ */ jsx101(
44604
45214
  "button",
44605
45215
  {
44606
45216
  ref,
@@ -44631,14 +45241,14 @@ var MenuBar = ({
44631
45241
  onPreview
44632
45242
  }) => {
44633
45243
  const t = useSmartTranslations("UEditor");
44634
- useEditorState3({
45244
+ useEditorState4({
44635
45245
  editor,
44636
- selector: ({ transactionNumber }) => transactionNumber
45246
+ selector: ({ editor: currentEditor }) => getEditorUiRenderState(currentEditor)
44637
45247
  });
44638
45248
  const fileInputRef = useRef39(null);
44639
45249
  const [showImageInput, setShowImageInput] = useState52(false);
44640
45250
  const [showLinkInput, setShowLinkInput] = useState52(false);
44641
- const [isInsertMenuOpen, setIsInsertMenuOpen] = useState52(false);
45251
+ const [openMenuKey, setOpenMenuKey] = useState52(null);
44642
45252
  const [showSourceDialog, setShowSourceDialog] = useState52(false);
44643
45253
  const [sourceHtml, setSourceHtml] = useState52("");
44644
45254
  const [showPreviewDialog, setShowPreviewDialog] = useState52(false);
@@ -44662,7 +45272,7 @@ var MenuBar = ({
44662
45272
  setShowSourceDialog(false);
44663
45273
  };
44664
45274
  const closeInsertMenu = () => {
44665
- setIsInsertMenuOpen(false);
45275
+ setOpenMenuKey(null);
44666
45276
  setShowImageInput(false);
44667
45277
  setShowLinkInput(false);
44668
45278
  };
@@ -44689,7 +45299,7 @@ var MenuBar = ({
44689
45299
  } catch {
44690
45300
  }
44691
45301
  }
44692
- setIsInsertMenuOpen(false);
45302
+ closeInsertMenu();
44693
45303
  };
44694
45304
  const handleInsertTable = (rows, cols) => {
44695
45305
  editor.chain().focus().insertTable({ rows, cols, withHeaderRow: true }).run();
@@ -44703,9 +45313,9 @@ var MenuBar = ({
44703
45313
  {
44704
45314
  type: "custom",
44705
45315
  key: "image",
44706
- render: () => showImageInput ? /* @__PURE__ */ jsx100(ImageInput, { onSubmit: handleImageUrl, onCancel: () => setShowImageInput(false) }) : /* @__PURE__ */ jsxs81(Fragment36, { children: [
44707
- /* @__PURE__ */ jsx100(DropdownMenuItem, { label: t("menubar.image"), icon: ImageIcon2, onClick: () => setShowImageInput(true), closeOnSelect: false }),
44708
- /* @__PURE__ */ jsx100(
45316
+ render: () => showImageInput ? /* @__PURE__ */ jsx101(ImageInput, { onSubmit: handleImageUrl, onCancel: () => setShowImageInput(false) }) : /* @__PURE__ */ jsxs82(Fragment35, { children: [
45317
+ /* @__PURE__ */ jsx101(DropdownMenuItem, { label: t("menubar.image"), icon: ImageIcon2, onClick: () => setShowImageInput(true), closeOnSelect: false }),
45318
+ /* @__PURE__ */ jsx101(
44709
45319
  DropdownMenuItem,
44710
45320
  {
44711
45321
  label: t("menubar.imageUpload"),
@@ -44720,7 +45330,7 @@ var MenuBar = ({
44720
45330
  {
44721
45331
  type: "custom",
44722
45332
  key: "link",
44723
- render: () => showLinkInput ? /* @__PURE__ */ jsx100(LinkInput, { onSubmit: handleLinkSubmit, onCancel: () => setShowLinkInput(false), initialUrl: editor.getAttributes("link").href ?? "" }) : /* @__PURE__ */ jsx100(
45333
+ render: () => showLinkInput ? /* @__PURE__ */ jsx101(LinkInput, { onSubmit: handleLinkSubmit, onCancel: () => setShowLinkInput(false), initialUrl: editor.getAttributes("link").href ?? "" }) : /* @__PURE__ */ jsx101(
44724
45334
  DropdownMenuItem,
44725
45335
  {
44726
45336
  label: t("menubar.link"),
@@ -44735,12 +45345,12 @@ var MenuBar = ({
44735
45345
  {
44736
45346
  type: "sub",
44737
45347
  label: t("menubar.insertTable"),
44738
- icon: TableIcon3,
45348
+ icon: TableIcon2,
44739
45349
  items: [
44740
45350
  {
44741
45351
  type: "custom",
44742
45352
  key: "table-grid",
44743
- render: () => /* @__PURE__ */ jsx100(
45353
+ render: () => /* @__PURE__ */ jsx101(
44744
45354
  MenuTableInsertGrid,
44745
45355
  {
44746
45356
  insertLabel: t("tableMenu.insertTable"),
@@ -44786,41 +45396,31 @@ var MenuBar = ({
44786
45396
  ];
44787
45397
  const menus = [
44788
45398
  {
45399
+ key: "file",
44789
45400
  label: t("menubar.file"),
44790
- items: buildFileMenuItems(t, editor, { onSave, onExport }),
44791
- open: void 0,
44792
- onOpenChange: void 0
45401
+ items: buildFileMenuItems(t, editor, { onSave, onExport })
44793
45402
  },
44794
- { label: t("menubar.edit"), items: buildEditMenuItems(t, editor), open: void 0, onOpenChange: void 0 },
45403
+ { key: "edit", label: t("menubar.edit"), items: buildEditMenuItems(t, editor) },
44795
45404
  {
45405
+ key: "view",
44796
45406
  label: t("menubar.view"),
44797
- items: buildViewMenuItems(t, { containerRef, onSourceCode, openSourceDialog, onPreview: handlePreview, openPreviewDialog }),
44798
- open: void 0,
44799
- onOpenChange: void 0
45407
+ items: buildViewMenuItems(t, { containerRef, onSourceCode, openSourceDialog, onPreview: handlePreview, openPreviewDialog })
44800
45408
  },
44801
45409
  {
45410
+ key: "insert",
44802
45411
  label: t("menubar.insert"),
44803
- items: insertMenuItems,
44804
- open: isInsertMenuOpen,
44805
- onOpenChange: (open) => {
44806
- setIsInsertMenuOpen(open);
44807
- if (!open) {
44808
- setShowImageInput(false);
44809
- setShowLinkInput(false);
44810
- }
44811
- }
45412
+ items: insertMenuItems
44812
45413
  },
44813
- { label: t("menubar.format"), items: buildFormatMenuItems(t, editor), open: void 0, onOpenChange: void 0 },
45414
+ { key: "format", label: t("menubar.format"), items: buildFormatMenuItems(t, editor) },
44814
45415
  {
45416
+ key: "tools",
44815
45417
  label: t("menubar.tools"),
44816
- items: buildToolsMenuItems(t, { onSourceCode, openSourceDialog }),
44817
- open: void 0,
44818
- onOpenChange: void 0
45418
+ items: buildToolsMenuItems(t, { onSourceCode, openSourceDialog })
44819
45419
  },
44820
- { label: t("menubar.table"), items: buildTableMenuItems(t, editor, handleInsertTable), open: void 0, onOpenChange: void 0 }
45420
+ { key: "table", label: t("menubar.table"), items: buildTableMenuItems(t, editor, handleInsertTable) }
44821
45421
  ];
44822
- return /* @__PURE__ */ jsxs81(Fragment36, { children: [
44823
- /* @__PURE__ */ jsx100(
45422
+ return /* @__PURE__ */ jsxs82(Fragment35, { children: [
45423
+ /* @__PURE__ */ jsx101(
44824
45424
  "input",
44825
45425
  {
44826
45426
  ref: fileInputRef,
@@ -44831,19 +45431,26 @@ var MenuBar = ({
44831
45431
  onChange: (e) => handleImageFiles(e.target.files)
44832
45432
  }
44833
45433
  ),
44834
- /* @__PURE__ */ jsxs81("div", { className: "flex items-center gap-0.5 border-b border-border/35 bg-muted/20 px-1.5 py-0.5", children: [
44835
- menus.map(({ label, items, open, onOpenChange }) => /* @__PURE__ */ jsx100(
45434
+ /* @__PURE__ */ jsxs82("div", { className: "flex items-center gap-0.5 border-b border-border/35 bg-muted/20 px-1.5 py-0.5", children: [
45435
+ menus.map(({ key, label, items }) => /* @__PURE__ */ jsx101(
44836
45436
  DropdownMenu,
44837
45437
  {
44838
- trigger: /* @__PURE__ */ jsx100(MenuBarTrigger, { children: label }),
45438
+ trigger: /* @__PURE__ */ jsx101(MenuBarTrigger, { children: label }),
44839
45439
  placement: "bottom-start",
44840
- isOpen: open,
44841
- onOpenChange,
45440
+ isOpen: openMenuKey === key,
45441
+ onOpenChange: (open) => {
45442
+ setOpenMenuKey((current) => open ? key : current === key ? null : current);
45443
+ if (key === "insert" && !open) {
45444
+ setShowImageInput(false);
45445
+ setShowLinkInput(false);
45446
+ }
45447
+ },
45448
+ openOnHover: true,
44842
45449
  children: renderMenuItems(items)
44843
45450
  },
44844
- label
45451
+ key
44845
45452
  )),
44846
- /* @__PURE__ */ jsx100(
45453
+ /* @__PURE__ */ jsx101(
44847
45454
  "button",
44848
45455
  {
44849
45456
  type: "button",
@@ -44854,20 +45461,20 @@ var MenuBar = ({
44854
45461
  "ml-auto inline-flex h-7 w-7 items-center justify-center rounded-md text-muted-foreground transition-colors",
44855
45462
  "hover:bg-accent hover:text-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-1"
44856
45463
  ),
44857
- children: /* @__PURE__ */ jsx100(Eye3, { className: "h-4 w-4", "aria-hidden": "true" })
45464
+ children: /* @__PURE__ */ jsx101(Eye3, { className: "h-4 w-4", "aria-hidden": "true" })
44858
45465
  }
44859
45466
  )
44860
45467
  ] }),
44861
- /* @__PURE__ */ jsx100(
45468
+ /* @__PURE__ */ jsx101(
44862
45469
  Modal_default,
44863
45470
  {
44864
45471
  isOpen: showSourceDialog,
44865
45472
  onClose: () => setShowSourceDialog(false),
44866
45473
  title: t("menubar.sourceCode"),
44867
45474
  size: "lg",
44868
- children: /* @__PURE__ */ jsxs81("div", { className: "space-y-3", children: [
44869
- /* @__PURE__ */ jsx100("p", { className: "text-xs text-muted-foreground", children: t("menubar.sourceCodeHint") }),
44870
- /* @__PURE__ */ jsx100(
45475
+ children: /* @__PURE__ */ jsxs82("div", { className: "space-y-3", children: [
45476
+ /* @__PURE__ */ jsx101("p", { className: "text-xs text-muted-foreground", children: t("menubar.sourceCodeHint") }),
45477
+ /* @__PURE__ */ jsx101(
44871
45478
  "textarea",
44872
45479
  {
44873
45480
  "data-testid": "source-code-textarea",
@@ -44877,8 +45484,8 @@ var MenuBar = ({
44877
45484
  spellCheck: false
44878
45485
  }
44879
45486
  ),
44880
- /* @__PURE__ */ jsxs81("div", { className: "flex gap-2 justify-end", children: [
44881
- /* @__PURE__ */ jsx100(
45487
+ /* @__PURE__ */ jsxs82("div", { className: "flex gap-2 justify-end", children: [
45488
+ /* @__PURE__ */ jsx101(
44882
45489
  "button",
44883
45490
  {
44884
45491
  type: "button",
@@ -44887,7 +45494,7 @@ var MenuBar = ({
44887
45494
  children: t("menubar.applySource")
44888
45495
  }
44889
45496
  ),
44890
- /* @__PURE__ */ jsx100(
45497
+ /* @__PURE__ */ jsx101(
44891
45498
  "button",
44892
45499
  {
44893
45500
  type: "button",
@@ -44900,7 +45507,7 @@ var MenuBar = ({
44900
45507
  ] })
44901
45508
  }
44902
45509
  ),
44903
- /* @__PURE__ */ jsx100(
45510
+ /* @__PURE__ */ jsx101(
44904
45511
  Modal_default,
44905
45512
  {
44906
45513
  isOpen: showPreviewDialog,
@@ -44911,12 +45518,12 @@ var MenuBar = ({
44911
45518
  height: "min(860px, calc(100vh - 2rem))",
44912
45519
  className: "flex flex-col overflow-hidden rounded-xl md:rounded-2xl",
44913
45520
  contentClassName: "flex min-h-0 flex-1 overflow-hidden p-0",
44914
- children: /* @__PURE__ */ jsx100(
45521
+ children: /* @__PURE__ */ jsx101(
44915
45522
  "div",
44916
45523
  {
44917
45524
  "data-testid": "preview-content",
44918
45525
  className: "min-h-0 flex-1 overflow-y-auto overscroll-contain",
44919
- children: editor.isEmpty ? /* @__PURE__ */ jsx100("p", { className: "text-muted-foreground text-sm", children: t("menubar.previewEmpty") }) : /* @__PURE__ */ jsx100(
45526
+ children: editor.isEmpty ? /* @__PURE__ */ jsx101("p", { className: "text-muted-foreground text-sm", children: t("menubar.previewEmpty") }) : /* @__PURE__ */ jsx101(
44920
45527
  "div",
44921
45528
  {
44922
45529
  className: UEDITOR_PROSEMIRROR_CLASS_NAME,
@@ -44932,18 +45539,31 @@ var MenuBar = ({
44932
45539
 
44933
45540
  // src/components/UEditor/table-formula-bar.tsx
44934
45541
  import { useEffect as useEffect41, useRef as useRef40, useState as useState53 } from "react";
44935
- import { useEditorState as useEditorState4 } from "@tiptap/react";
45542
+ import { useEditorState as useEditorState5 } from "@tiptap/react";
44936
45543
  import { AlertCircle as AlertCircle5, Check as Check14, Hash as Hash2, Sigma as Sigma3, Trash2 as Trash26 } from "lucide-react";
44937
- import { jsx as jsx101, jsxs as jsxs82 } from "react/jsx-runtime";
45544
+ import { jsx as jsx102, jsxs as jsxs83 } from "react/jsx-runtime";
44938
45545
  function TableFormulaBar({ editor }) {
44939
45546
  const t = useSmartTranslations("UEditor");
44940
45547
  const inputRef = useRef40(null);
44941
45548
  const [draftState, setDraftState] = useState53(null);
44942
- useEditorState4({
45549
+ const selectedFormulaState = useEditorState5({
44943
45550
  editor,
44944
- selector: ({ transactionNumber }) => transactionNumber
45551
+ selector: ({ editor: currentEditor }) => {
45552
+ const cell = getSelectedTableFormulaCell(currentEditor);
45553
+ if (!cell) return null;
45554
+ return {
45555
+ cellPos: cell.cellPos,
45556
+ column: cell.column,
45557
+ computedValue: cell.computedValue,
45558
+ formula: cell.formula,
45559
+ formulaState: cell.formulaState,
45560
+ label: cell.label,
45561
+ row: cell.row,
45562
+ tablePos: cell.tablePos
45563
+ };
45564
+ }
44945
45565
  });
44946
- const selectedCell = getSelectedTableFormulaCell(editor);
45566
+ const selectedCell = selectedFormulaState ? getSelectedTableFormulaCell(editor) : null;
44947
45567
  useEffect41(() => {
44948
45568
  const focusFormulaInput = () => {
44949
45569
  inputRef.current?.focus();
@@ -44984,7 +45604,7 @@ function TableFormulaBar({ editor }) {
44984
45604
  if (!editor.isDestroyed) editor.commands.focus();
44985
45605
  }, 0);
44986
45606
  };
44987
- return /* @__PURE__ */ jsxs82(
45607
+ return /* @__PURE__ */ jsxs83(
44988
45608
  "div",
44989
45609
  {
44990
45610
  "data-ueditor-formula-bar": "",
@@ -44992,7 +45612,7 @@ function TableFormulaBar({ editor }) {
44992
45612
  "aria-label": t("tableMenu.formulaBar"),
44993
45613
  className: "flex min-h-10 items-center gap-2 border-b border-border/60 bg-muted/25 px-2 py-1.5",
44994
45614
  children: [
44995
- /* @__PURE__ */ jsx101(
45615
+ /* @__PURE__ */ jsx102(
44996
45616
  "span",
44997
45617
  {
44998
45618
  "data-ueditor-formula-cell-label": "",
@@ -45000,8 +45620,8 @@ function TableFormulaBar({ editor }) {
45000
45620
  children: selectedCell.label
45001
45621
  }
45002
45622
  ),
45003
- /* @__PURE__ */ jsx101(Sigma3, { "aria-hidden": "true", className: "h-4 w-4 shrink-0 text-primary" }),
45004
- /* @__PURE__ */ jsx101(
45623
+ /* @__PURE__ */ jsx102(Sigma3, { "aria-hidden": "true", className: "h-4 w-4 shrink-0 text-primary" }),
45624
+ /* @__PURE__ */ jsx102(
45005
45625
  "input",
45006
45626
  {
45007
45627
  ref: inputRef,
@@ -45022,18 +45642,18 @@ function TableFormulaBar({ editor }) {
45022
45642
  className: "h-7 min-w-0 flex-1 rounded-md border border-border/60 bg-background px-2 font-mono text-sm text-foreground outline-none focus:border-primary/40 focus:ring-2 focus:ring-primary/15"
45023
45643
  }
45024
45644
  ),
45025
- selectedCell.formulaState === "error" && /* @__PURE__ */ jsxs82(
45645
+ selectedCell.formulaState === "error" && /* @__PURE__ */ jsxs83(
45026
45646
  "span",
45027
45647
  {
45028
45648
  role: "status",
45029
45649
  className: "hidden shrink-0 items-center gap-1 text-xs font-medium text-destructive sm:inline-flex",
45030
45650
  children: [
45031
- /* @__PURE__ */ jsx101(AlertCircle5, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
45651
+ /* @__PURE__ */ jsx102(AlertCircle5, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
45032
45652
  t("tableMenu.formulaError")
45033
45653
  ]
45034
45654
  }
45035
45655
  ),
45036
- /* @__PURE__ */ jsx101(
45656
+ /* @__PURE__ */ jsx102(
45037
45657
  "button",
45038
45658
  {
45039
45659
  type: "button",
@@ -45041,10 +45661,10 @@ function TableFormulaBar({ editor }) {
45041
45661
  "aria-label": t("tableMenu.apply"),
45042
45662
  title: t("tableMenu.apply"),
45043
45663
  className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md bg-primary text-primary-foreground transition-colors hover:bg-primary/90",
45044
- children: /* @__PURE__ */ jsx101(Check14, { "aria-hidden": "true", className: "h-4 w-4" })
45664
+ children: /* @__PURE__ */ jsx102(Check14, { "aria-hidden": "true", className: "h-4 w-4" })
45045
45665
  }
45046
45666
  ),
45047
- /* @__PURE__ */ jsx101(
45667
+ /* @__PURE__ */ jsx102(
45048
45668
  "button",
45049
45669
  {
45050
45670
  type: "button",
@@ -45055,10 +45675,10 @@ function TableFormulaBar({ editor }) {
45055
45675
  "aria-label": t("tableMenu.convertToValue"),
45056
45676
  title: t("tableMenu.convertToValue"),
45057
45677
  className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-border/60 bg-background text-muted-foreground transition-colors hover:bg-muted hover:text-foreground",
45058
- children: /* @__PURE__ */ jsx101(Hash2, { "aria-hidden": "true", className: "h-4 w-4" })
45678
+ children: /* @__PURE__ */ jsx102(Hash2, { "aria-hidden": "true", className: "h-4 w-4" })
45059
45679
  }
45060
45680
  ),
45061
- /* @__PURE__ */ jsx101(
45681
+ /* @__PURE__ */ jsx102(
45062
45682
  "button",
45063
45683
  {
45064
45684
  type: "button",
@@ -45069,7 +45689,7 @@ function TableFormulaBar({ editor }) {
45069
45689
  "aria-label": t("tableMenu.clearCell"),
45070
45690
  title: t("tableMenu.clearCell"),
45071
45691
  className: "flex h-7 w-7 shrink-0 items-center justify-center rounded-md border border-destructive/30 bg-background text-destructive transition-colors hover:bg-destructive/10",
45072
- children: /* @__PURE__ */ jsx101(Trash26, { "aria-hidden": "true", className: "h-4 w-4" })
45692
+ children: /* @__PURE__ */ jsx102(Trash26, { "aria-hidden": "true", className: "h-4 w-4" })
45073
45693
  }
45074
45694
  )
45075
45695
  ]
@@ -45078,7 +45698,7 @@ function TableFormulaBar({ editor }) {
45078
45698
  }
45079
45699
 
45080
45700
  // src/components/UEditor/UEditor.tsx
45081
- import { jsx as jsx102, jsxs as jsxs83 } from "react/jsx-runtime";
45701
+ import { jsx as jsx103, jsxs as jsxs84 } from "react/jsx-runtime";
45082
45702
  var UEditor = React91.forwardRef(({
45083
45703
  content = "",
45084
45704
  onChange,
@@ -45124,6 +45744,7 @@ var UEditor = React91.forwardRef(({
45124
45744
  const inFlightPrepareRef = useRef41(null);
45125
45745
  const lastAppliedContentRef = useRef41(content ?? "");
45126
45746
  const scheduledFormulaRecalculateRef = useRef41(false);
45747
+ const pendingFormulaTextRecalculateRef = useRef41(false);
45127
45748
  const editorInstanceRef = useRef41(null);
45128
45749
  const formulaRangePickRef = useRef41(null);
45129
45750
  const formulaRangeSurfaceRef = useRef41(null);
@@ -45262,19 +45883,32 @@ var UEditor = React91.forwardRef(({
45262
45883
  },
45263
45884
  onUpdate: ({ editor: editor2, transaction }) => {
45264
45885
  if (!transaction.getMeta(UEDITOR_TABLE_FORMULA_RECALCULATE_META)) {
45265
- scheduleFormulaRecalculate(editor2);
45886
+ if (isEditingTableFormulaText(editor2)) {
45887
+ pendingFormulaTextRecalculateRef.current = true;
45888
+ } else {
45889
+ pendingFormulaTextRecalculateRef.current = false;
45890
+ scheduleFormulaRecalculate(editor2);
45891
+ }
45892
+ }
45893
+ if (onChange || onHtmlChange) {
45894
+ const html = editor2.getHTML();
45895
+ onChange?.(html);
45896
+ onHtmlChange?.(html);
45897
+ }
45898
+ if (onJsonChange) {
45899
+ onJsonChange(editor2.getJSON());
45266
45900
  }
45267
- const html = editor2.getHTML();
45268
- onChange?.(html);
45269
- onHtmlChange?.(html);
45270
- onJsonChange?.(editor2.getJSON());
45271
45901
  },
45272
45902
  onSelectionUpdate: ({ editor: editor2 }) => {
45273
- scheduleFormulaRecalculate(editor2);
45903
+ if (pendingFormulaTextRecalculateRef.current && !isEditingTableFormulaText(editor2)) {
45904
+ pendingFormulaTextRecalculateRef.current = false;
45905
+ scheduleFormulaRecalculate(editor2);
45906
+ }
45274
45907
  },
45275
45908
  onBlur: ({ editor: editor2, event }) => {
45276
45909
  const nextTarget = event.relatedTarget;
45277
45910
  if (nextTarget instanceof Element && nextTarget.closest("[data-ueditor-formula-bar]")) return;
45911
+ pendingFormulaTextRecalculateRef.current = false;
45278
45912
  scheduleFormulaRecalculate(editor2, { force: true });
45279
45913
  }
45280
45914
  });
@@ -45346,7 +45980,7 @@ var UEditor = React91.forwardRef(({
45346
45980
  }
45347
45981
  }, [content, editor]);
45348
45982
  if (!editor) {
45349
- return /* @__PURE__ */ jsx102(
45983
+ return /* @__PURE__ */ jsx103(
45350
45984
  "div",
45351
45985
  {
45352
45986
  className: cn("w-full border bg-background flex items-center justify-center text-muted-foreground", className),
@@ -45355,7 +45989,7 @@ var UEditor = React91.forwardRef(({
45355
45989
  }
45356
45990
  );
45357
45991
  }
45358
- return /* @__PURE__ */ jsxs83(
45992
+ return /* @__PURE__ */ jsxs84(
45359
45993
  "div",
45360
45994
  {
45361
45995
  className: cn(
@@ -45371,7 +46005,7 @@ var UEditor = React91.forwardRef(({
45371
46005
  className
45372
46006
  ),
45373
46007
  children: [
45374
- editable && showMenuBar && /* @__PURE__ */ jsx102(
46008
+ editable && showMenuBar && /* @__PURE__ */ jsx103(
45375
46009
  MenuBar,
45376
46010
  {
45377
46011
  editor,
@@ -45386,7 +46020,7 @@ var UEditor = React91.forwardRef(({
45386
46020
  onPreview
45387
46021
  }
45388
46022
  ),
45389
- editable && showToolbar && /* @__PURE__ */ jsx102(
46023
+ editable && showToolbar && /* @__PURE__ */ jsx103(
45390
46024
  EditorToolbar,
45391
46025
  {
45392
46026
  editor,
@@ -45401,8 +46035,8 @@ var UEditor = React91.forwardRef(({
45401
46035
  letterSpacings
45402
46036
  }
45403
46037
  ),
45404
- editable && /* @__PURE__ */ jsx102(TableFormulaBar, { editor }),
45405
- editable && showBubbleMenu && /* @__PURE__ */ jsx102(
46038
+ editable && /* @__PURE__ */ jsx103(TableFormulaBar, { editor }),
46039
+ editable && showBubbleMenu && /* @__PURE__ */ jsx103(
45406
46040
  CustomBubbleMenu,
45407
46041
  {
45408
46042
  editor,
@@ -45410,8 +46044,8 @@ var UEditor = React91.forwardRef(({
45410
46044
  lineHeights
45411
46045
  }
45412
46046
  ),
45413
- editable && showFloatingMenu && /* @__PURE__ */ jsx102(CustomFloatingMenu, { editor }),
45414
- /* @__PURE__ */ jsxs83(
46047
+ editable && showFloatingMenu && /* @__PURE__ */ jsx103(CustomFloatingMenu, { editor }),
46048
+ /* @__PURE__ */ jsxs84(
45415
46049
  "div",
45416
46050
  {
45417
46051
  ref: (node) => {
@@ -45424,7 +46058,7 @@ var UEditor = React91.forwardRef(({
45424
46058
  maxHeight
45425
46059
  },
45426
46060
  children: [
45427
- /* @__PURE__ */ jsx102(
46061
+ /* @__PURE__ */ jsx103(
45428
46062
  "span",
45429
46063
  {
45430
46064
  ref: tableColumnGuideRef,
@@ -45432,7 +46066,7 @@ var UEditor = React91.forwardRef(({
45432
46066
  className: "pointer-events-none absolute z-20 bg-primary opacity-0 transition-opacity duration-100"
45433
46067
  }
45434
46068
  ),
45435
- /* @__PURE__ */ jsx102(
46069
+ /* @__PURE__ */ jsx103(
45436
46070
  "span",
45437
46071
  {
45438
46072
  ref: tableRowGuideRef,
@@ -45440,7 +46074,7 @@ var UEditor = React91.forwardRef(({
45440
46074
  className: "pointer-events-none absolute z-20 bg-primary opacity-0 transition-opacity duration-100"
45441
46075
  }
45442
46076
  ),
45443
- /* @__PURE__ */ jsx102(
46077
+ /* @__PURE__ */ jsx103(
45444
46078
  "span",
45445
46079
  {
45446
46080
  ref: activeTableCellHighlightRef,
@@ -45449,7 +46083,7 @@ var UEditor = React91.forwardRef(({
45449
46083
  className: "pointer-events-none hidden absolute z-20 rounded-[2px] border-2 border-primary bg-primary/10"
45450
46084
  }
45451
46085
  ),
45452
- /* @__PURE__ */ jsx102(
46086
+ /* @__PURE__ */ jsx103(
45453
46087
  "div",
45454
46088
  {
45455
46089
  ref: formulaCoordinateOverlayRef,
@@ -45457,7 +46091,7 @@ var UEditor = React91.forwardRef(({
45457
46091
  className: "pointer-events-none absolute inset-0 z-[35] hidden overflow-visible"
45458
46092
  }
45459
46093
  ),
45460
- formulaRangeHighlight && /* @__PURE__ */ jsx102(
46094
+ formulaRangeHighlight && /* @__PURE__ */ jsx103(
45461
46095
  "span",
45462
46096
  {
45463
46097
  "aria-hidden": "true",
@@ -45475,8 +46109,15 @@ var UEditor = React91.forwardRef(({
45475
46109
  }
45476
46110
  }
45477
46111
  ),
45478
- editable && /* @__PURE__ */ jsx102(TableControls, { editor, containerRef: editorContentRef }),
45479
- /* @__PURE__ */ jsx102(
46112
+ editable && /* @__PURE__ */ jsx103(
46113
+ TableControls,
46114
+ {
46115
+ editor,
46116
+ containerRef: editorContentRef,
46117
+ showCellInspector: showBubbleMenu
46118
+ }
46119
+ ),
46120
+ /* @__PURE__ */ jsx103(
45480
46121
  EditorContent,
45481
46122
  {
45482
46123
  editor,
@@ -45486,7 +46127,7 @@ var UEditor = React91.forwardRef(({
45486
46127
  ]
45487
46128
  }
45488
46129
  ),
45489
- showFooter && showCharacterCount && /* @__PURE__ */ jsx102(CharacterCountDisplay, { editor, maxCharacters })
46130
+ showFooter && showCharacterCount && /* @__PURE__ */ jsx103(CharacterCountDisplay, { editor, maxCharacters })
45490
46131
  ]
45491
46132
  }
45492
46133
  );