@zuilib/text-editor 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/EditorRoot.tsx
2
2
  import {
3
3
  useCallback as useCallback2,
4
- useEffect as useEffect8,
4
+ useEffect as useEffect9,
5
5
  useMemo as useMemo2,
6
6
  useRef as useRef5,
7
7
  useState as useState4
@@ -15,7 +15,7 @@ import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPl
15
15
  import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
16
16
  import { TablePlugin } from "@lexical/react/LexicalTablePlugin";
17
17
  import { CHECK_LIST, CODE as CODE2, TRANSFORMERS as TRANSFORMERS2 } from "@lexical/markdown";
18
- import { useLexicalComposerContext as useLexicalComposerContext6 } from "@lexical/react/LexicalComposerContext";
18
+ import { useLexicalComposerContext as useLexicalComposerContext7 } from "@lexical/react/LexicalComposerContext";
19
19
  import { HeadingNode, QuoteNode } from "@lexical/rich-text";
20
20
  import { ListItemNode, ListNode as ListNode2 } from "@lexical/list";
21
21
  import { CodeHighlightNode, CodeNode as CodeNode2 } from "@lexical/code";
@@ -1607,6 +1607,304 @@ function MarkdownSyncPlugin({
1607
1607
  return null;
1608
1608
  }
1609
1609
 
1610
+ // src/plugins/TableRowShortcutsPlugin.tsx
1611
+ import { useEffect as useEffect5 } from "react";
1612
+ import { useLexicalComposerContext as useLexicalComposerContext5 } from "@lexical/react/LexicalComposerContext";
1613
+ import { $getSelection as $getSelection4, $isRangeSelection as $isRangeSelection4, COMMAND_PRIORITY_HIGH, KEY_DOWN_COMMAND } from "lexical";
1614
+ import { $isTableRowNode as $isTableRowNode2 } from "@lexical/table";
1615
+
1616
+ // src/transformers/tableSettings.ts
1617
+ import {
1618
+ $getNodeByKey as $getNodeByKey2,
1619
+ $getSelection as $getSelection2,
1620
+ $isRangeSelection as $isRangeSelection2
1621
+ } from "lexical";
1622
+ import { $findMatchingParent } from "@lexical/utils";
1623
+ import { $isTableNode, $isTableSelection } from "@lexical/table";
1624
+ var DEFAULT_TABLE_SETTINGS = {
1625
+ width: "full",
1626
+ density: "comfortable"
1627
+ };
1628
+ var BLOCK_BLEED_PROPERTY = "--zui-text-editor-block-bleed";
1629
+ var OPTION_DECLARATIONS = {
1630
+ width: {
1631
+ full: {},
1632
+ content: { width: "auto", "table-layout": "auto", [BLOCK_BLEED_PROPERTY]: "0px" },
1633
+ text: { [BLOCK_BLEED_PROPERTY]: "0px" }
1634
+ },
1635
+ density: {
1636
+ comfortable: {},
1637
+ compact: {
1638
+ "--zui-table-cell-padding": "0.25rem 0.5rem",
1639
+ "--zui-table-font-size": "0.8125rem"
1640
+ },
1641
+ spacious: {
1642
+ "--zui-table-cell-padding": "0.875rem 1rem",
1643
+ "--zui-table-font-size": "0.9375rem"
1644
+ }
1645
+ }
1646
+ };
1647
+ var SETTING_KEYS = Object.keys(OPTION_DECLARATIONS);
1648
+ var EXPLICIT_WIDTH_PROPERTY = "--zui-table-width";
1649
+ function parseStyle(style) {
1650
+ const declarations = /* @__PURE__ */ new Map();
1651
+ for (const part of style.split(";")) {
1652
+ const index = part.indexOf(":");
1653
+ if (index === -1) continue;
1654
+ const key = part.slice(0, index).trim();
1655
+ const value = part.slice(index + 1).trim();
1656
+ if (key && value) declarations.set(key, value);
1657
+ }
1658
+ return declarations;
1659
+ }
1660
+ function serializeStyle(declarations) {
1661
+ return [...declarations].map(([key, value]) => `${key}: ${value}`).join("; ");
1662
+ }
1663
+ function optionsOf(setting) {
1664
+ return Object.entries(OPTION_DECLARATIONS[setting]);
1665
+ }
1666
+ function readSetting(declarations, setting) {
1667
+ for (const [option, decls] of optionsOf(setting)) {
1668
+ const entries = Object.entries(decls);
1669
+ if (entries.length === 0) continue;
1670
+ if (entries.every(([key, value]) => declarations.get(key) === value)) {
1671
+ return option;
1672
+ }
1673
+ }
1674
+ return DEFAULT_TABLE_SETTINGS[setting];
1675
+ }
1676
+ function writeSetting(declarations, setting, option) {
1677
+ for (const [, decls] of optionsOf(setting)) {
1678
+ for (const key of Object.keys(decls)) declarations.delete(key);
1679
+ }
1680
+ for (const [key, value] of Object.entries(OPTION_DECLARATIONS[setting][option])) {
1681
+ declarations.set(key, value);
1682
+ }
1683
+ }
1684
+ function $getTableSettings(table) {
1685
+ const declarations = parseStyle(table.getStyle());
1686
+ return {
1687
+ width: readSetting(declarations, "width"),
1688
+ density: readSetting(declarations, "density")
1689
+ };
1690
+ }
1691
+ function $setTableSettings(table, settings, options = {}) {
1692
+ const declarations = parseStyle(table.getStyle());
1693
+ for (const key of SETTING_KEYS) {
1694
+ const option = settings[key];
1695
+ if (option !== void 0) writeSetting(declarations, key, option);
1696
+ }
1697
+ if (settings.width !== void 0) {
1698
+ if (options.explicitWidth) declarations.set(EXPLICIT_WIDTH_PROPERTY, settings.width);
1699
+ else declarations.delete(EXPLICIT_WIDTH_PROPERTY);
1700
+ }
1701
+ table.setStyle(serializeStyle(declarations));
1702
+ }
1703
+ function $isTableWidthExplicit(table) {
1704
+ const declarations = parseStyle(table.getStyle());
1705
+ return declarations.get(EXPLICIT_WIDTH_PROPERTY) === readSetting(declarations, "width");
1706
+ }
1707
+ function $getTableWidth(table) {
1708
+ return $getTableSettings(table).width;
1709
+ }
1710
+ function $setTableWidth(table, width) {
1711
+ $setTableSettings(table, { width });
1712
+ }
1713
+ function $getTableDensity(table) {
1714
+ return $getTableSettings(table).density;
1715
+ }
1716
+ function $setTableDensity(table, density) {
1717
+ $setTableSettings(table, { density });
1718
+ }
1719
+ function $getSelectedTable() {
1720
+ const selection = $getSelection2();
1721
+ if ($isTableSelection(selection)) {
1722
+ const node = $getNodeByKey2(selection.tableKey);
1723
+ return $isTableNode(node) ? node : null;
1724
+ }
1725
+ if (!$isRangeSelection2(selection)) return null;
1726
+ const table = $findMatchingParent(
1727
+ selection.anchor.getNode(),
1728
+ (node) => $isTableNode(node)
1729
+ );
1730
+ return $isTableNode(table) ? table : null;
1731
+ }
1732
+ var MARKER_REG_EXP = /^<!--\s*([a-z]+\s*:\s*[a-z]+(?:\s*;\s*[a-z]+\s*:\s*[a-z]+)*)\s*;?\s*-->\s*$/;
1733
+ function isOption(setting, value) {
1734
+ return value in OPTION_DECLARATIONS[setting];
1735
+ }
1736
+ var TABLE_WIDTH_MARKER = "<!-- width: content -->";
1737
+ function parseTableSettingsMarker(text) {
1738
+ const match = MARKER_REG_EXP.exec(text);
1739
+ if (!match) return null;
1740
+ const settings = {};
1741
+ let recognised = false;
1742
+ for (const pair of match[1].split(";")) {
1743
+ const [key, value] = pair.split(":").map((s) => s.trim());
1744
+ if (key !== "width" && key !== "density") continue;
1745
+ recognised = true;
1746
+ if (key === "width" && isOption("width", value)) settings.width = value;
1747
+ if (key === "density" && isOption("density", value)) settings.density = value;
1748
+ }
1749
+ return recognised ? settings : null;
1750
+ }
1751
+ function formatTableSettingsMarker(settings, options = {}) {
1752
+ const pairs = SETTING_KEYS.filter(
1753
+ (key) => settings[key] !== DEFAULT_TABLE_SETTINGS[key] || key === "width" && options.explicitWidth
1754
+ ).map((key) => `${key}: ${settings[key]}`);
1755
+ return pairs.length > 0 ? `<!-- ${pairs.join("; ")} -->` : null;
1756
+ }
1757
+
1758
+ // src/transformers/tableRows.ts
1759
+ import {
1760
+ $createParagraphNode as $createParagraphNode2,
1761
+ $getNodeByKey as $getNodeByKey3,
1762
+ $getSelection as $getSelection3,
1763
+ $isRangeSelection as $isRangeSelection3
1764
+ } from "lexical";
1765
+ import { $findMatchingParent as $findMatchingParent2 } from "@lexical/utils";
1766
+ import {
1767
+ $createTableCellNode,
1768
+ $createTableRowNode,
1769
+ $isTableCellNode,
1770
+ $isTableNode as $isTableNode2,
1771
+ $isTableRowNode,
1772
+ $isTableSelection as $isTableSelection2,
1773
+ TableCellHeaderStates
1774
+ } from "@lexical/table";
1775
+ function $rows(table) {
1776
+ return table.getChildren().filter($isTableRowNode);
1777
+ }
1778
+ function $cells(row) {
1779
+ return row.getChildren().filter($isTableCellNode);
1780
+ }
1781
+ function $isHeaderRow(row) {
1782
+ const cells = row ? $cells(row) : [];
1783
+ return cells.length > 0 && cells.every((cell) => cell.hasHeaderState(TableCellHeaderStates.ROW));
1784
+ }
1785
+ function $getSelectedTableCell() {
1786
+ const selection = $getSelection3();
1787
+ let node = null;
1788
+ if ($isTableSelection2(selection)) node = $getNodeByKey3(selection.anchor.key);
1789
+ else if ($isRangeSelection3(selection)) node = selection.anchor.getNode();
1790
+ if (!node) return null;
1791
+ const cell = $findMatchingParent2(node, (n2) => $isTableCellNode(n2));
1792
+ return $isTableCellNode(cell) ? cell : null;
1793
+ }
1794
+ function $getTableRowPosition() {
1795
+ const cell = $getSelectedTableCell();
1796
+ const row = cell?.getParent();
1797
+ const table = row?.getParent();
1798
+ if (!cell || !$isTableRowNode(row) || !$isTableNode2(table)) return null;
1799
+ const rows = $rows(table);
1800
+ return {
1801
+ index: rows.indexOf(row),
1802
+ column: $cells(row).indexOf(cell),
1803
+ count: rows.length,
1804
+ hasHeader: $isHeaderRow(rows[0])
1805
+ };
1806
+ }
1807
+ function insertableRowIndices(position) {
1808
+ const indices = [];
1809
+ for (let i = position.hasHeader ? 1 : 0; i <= position.count; i++) indices.push(i);
1810
+ return indices;
1811
+ }
1812
+ function canDeleteRow(position) {
1813
+ return position.count > 1;
1814
+ }
1815
+ function $selectCell(cell) {
1816
+ cell?.selectStart();
1817
+ }
1818
+ function $insertTableRowAt(table, index, column = 0) {
1819
+ const rows = $rows(table);
1820
+ const minIndex = $isHeaderRow(rows[0]) ? 1 : 0;
1821
+ const at = Math.max(minIndex, Math.min(index, rows.length));
1822
+ const reference = rows[Math.max(0, at - 1)] ?? rows[0];
1823
+ const referenceCells = reference ? $cells(reference) : [];
1824
+ const row = $createTableRowNode();
1825
+ for (const cell of referenceCells) {
1826
+ const columnHeader = cell.hasHeaderState(TableCellHeaderStates.COLUMN) ? TableCellHeaderStates.COLUMN : TableCellHeaderStates.NO_STATUS;
1827
+ row.append($createTableCellNode(columnHeader).append($createParagraphNode2()));
1828
+ }
1829
+ if (referenceCells.length === 0) {
1830
+ row.append($createTableCellNode(TableCellHeaderStates.NO_STATUS).append($createParagraphNode2()));
1831
+ }
1832
+ if (at >= rows.length) table.append(row);
1833
+ else rows[at].insertBefore(row);
1834
+ const cells = $cells(row);
1835
+ $selectCell(cells[Math.min(column, cells.length - 1)]);
1836
+ return row;
1837
+ }
1838
+ function $deleteTableRowAt(table, index, column = 0) {
1839
+ const rows = $rows(table);
1840
+ const row = rows[index];
1841
+ if (!row || rows.length < 2) return false;
1842
+ const wasHeader = index === 0 && $isHeaderRow(row);
1843
+ row.remove();
1844
+ const remaining = $rows(table);
1845
+ if (wasHeader) {
1846
+ for (const cell of $cells(remaining[0])) {
1847
+ cell.setHeaderStyles(TableCellHeaderStates.ROW, TableCellHeaderStates.ROW);
1848
+ }
1849
+ }
1850
+ const target = remaining[Math.min(index, remaining.length - 1)];
1851
+ const cells = $cells(target);
1852
+ $selectCell(cells[Math.min(column, cells.length - 1)]);
1853
+ return true;
1854
+ }
1855
+ function $insertTableRowNear(table, position) {
1856
+ const at = $getTableRowPosition();
1857
+ if (!at) return null;
1858
+ return $insertTableRowAt(table, position === "below" ? at.index + 1 : at.index, at.column);
1859
+ }
1860
+ function $deleteSelectedTableRow(table) {
1861
+ const at = $getTableRowPosition();
1862
+ if (!at || !canDeleteRow(at)) return false;
1863
+ return $deleteTableRowAt(table, at.index, at.column);
1864
+ }
1865
+
1866
+ // src/plugins/TableRowShortcutsPlugin.tsx
1867
+ function shortcutFor(event) {
1868
+ const mod = event.metaKey || event.ctrlKey;
1869
+ if (event.altKey) return null;
1870
+ if (event.key === "Enter" && mod) return event.shiftKey ? "insert-above" : "insert-below";
1871
+ if (event.key === "Backspace" && mod && event.shiftKey) return "delete";
1872
+ if (event.key === "Tab" && !mod && !event.shiftKey) return "tab";
1873
+ return null;
1874
+ }
1875
+ function TableRowShortcutsPlugin() {
1876
+ const [editor] = useLexicalComposerContext5();
1877
+ useEffect5(
1878
+ () => editor.registerCommand(
1879
+ KEY_DOWN_COMMAND,
1880
+ (event) => {
1881
+ const shortcut = shortcutFor(event);
1882
+ if (!shortcut) return false;
1883
+ const table = $getSelectedTable();
1884
+ const position = $getTableRowPosition();
1885
+ if (!table || !position) return false;
1886
+ if (shortcut === "tab") {
1887
+ const selection = $getSelection4();
1888
+ const firstRow = table.getFirstChild();
1889
+ const columns = $isTableRowNode2(firstRow) ? firstRow.getChildrenSize() : 0;
1890
+ const isLastCell = position.index === position.count - 1 && position.column === columns - 1;
1891
+ if (!isLastCell || !$isRangeSelection4(selection) || !selection.isCollapsed()) return false;
1892
+ event.preventDefault();
1893
+ $insertTableRowAt(table, position.count);
1894
+ return true;
1895
+ }
1896
+ event.preventDefault();
1897
+ if (shortcut === "delete") $deleteSelectedTableRow(table);
1898
+ else $insertTableRowNear(table, shortcut === "insert-above" ? "above" : "below");
1899
+ return true;
1900
+ },
1901
+ COMMAND_PRIORITY_HIGH
1902
+ ),
1903
+ [editor]
1904
+ );
1905
+ return null;
1906
+ }
1907
+
1610
1908
  // src/nodes/FrontmatterNode.ts
1611
1909
  import {
1612
1910
  $applyNodeReplacement,
@@ -1696,15 +1994,29 @@ import {
1696
1994
  // src/drawing/canvas/DrawingCanvas.tsx
1697
1995
  import {
1698
1996
  useCallback,
1699
- useEffect as useEffect7,
1997
+ useEffect as useEffect8,
1700
1998
  useMemo,
1701
1999
  useRef as useRef4,
1702
- useState as useState3
2000
+ useState as useState3,
2001
+ useContext as useContext2
1703
2002
  } from "react";
1704
- import { $getNodeByKey as $getNodeByKey2 } from "lexical";
1705
- import { useLexicalComposerContext as useLexicalComposerContext5 } from "@lexical/react/LexicalComposerContext";
2003
+ import { $getNodeByKey as $getNodeByKey4 } from "lexical";
2004
+ import { useLexicalComposerContext as useLexicalComposerContext6 } from "@lexical/react/LexicalComposerContext";
1706
2005
  import { useLexicalEditable } from "@lexical/react/useLexicalEditable";
1707
2006
 
2007
+ // src/editorContext.ts
2008
+ import { createContext, useContext } from "react";
2009
+ var EditorContext = createContext(null);
2010
+ function useEditorContext() {
2011
+ const ctx = useContext(EditorContext);
2012
+ if (!ctx) {
2013
+ throw new Error(
2014
+ "@zuilib/text-editor: this component must be rendered inside <MarkdownEditor> or <MarkdownEditor.Root>"
2015
+ );
2016
+ }
2017
+ return ctx;
2018
+ }
2019
+
1708
2020
  // src/drawing/focusCommand.ts
1709
2021
  import { createCommand } from "lexical";
1710
2022
  var DRAWING_FOCUS_COMMAND = createCommand(
@@ -2138,23 +2450,23 @@ var BOX_DEFINITIONS = {
2138
2450
  defaultFill: "#ffec99",
2139
2451
  outline: (s) => {
2140
2452
  const b = bbox(s);
2141
- const f = NOTE_FOLD(b);
2453
+ const f3 = NOTE_FOLD(b);
2142
2454
  return [
2143
2455
  { x: b.x, y: b.y },
2144
2456
  { x: b.x + b.w, y: b.y },
2145
- { x: b.x + b.w, y: b.y + b.h - f },
2146
- { x: b.x + b.w - f, y: b.y + b.h },
2457
+ { x: b.x + b.w, y: b.y + b.h - f3 },
2458
+ { x: b.x + b.w - f3, y: b.y + b.h },
2147
2459
  { x: b.x, y: b.y + b.h }
2148
2460
  ];
2149
2461
  },
2150
2462
  textArea: (s) => {
2151
2463
  const b = bbox(s);
2152
- const f = NOTE_FOLD(b);
2464
+ const f3 = NOTE_FOLD(b);
2153
2465
  return {
2154
2466
  x: b.x + BOX_TEXT_PADDING,
2155
2467
  y: b.y + BOX_TEXT_PADDING,
2156
2468
  w: Math.max(b.w - BOX_TEXT_PADDING * 2, 20),
2157
- h: Math.max(b.h - BOX_TEXT_PADDING * 2 - f / 2, 10)
2469
+ h: Math.max(b.h - BOX_TEXT_PADDING * 2 - f3 / 2, 10)
2158
2470
  };
2159
2471
  }
2160
2472
  },
@@ -2656,13 +2968,17 @@ function segmentAngleAt(points, index, backward) {
2656
2968
  }
2657
2969
  return 0;
2658
2970
  }
2659
- function arrowHeadPath(tip, angle, length) {
2971
+ function arrowHeadPoints(tip, angle, length) {
2660
2972
  const spread = Math.PI / 7;
2661
- const hx1 = tip.x - length * Math.cos(angle - spread);
2662
- const hy1 = tip.y - length * Math.sin(angle - spread);
2663
- const hx2 = tip.x - length * Math.cos(angle + spread);
2664
- const hy2 = tip.y - length * Math.sin(angle + spread);
2665
- return `M ${fmt(hx1)} ${fmt(hy1)} L ${fmt(tip.x)} ${fmt(tip.y)} L ${fmt(hx2)} ${fmt(hy2)}`;
2973
+ return [
2974
+ { x: tip.x - length * Math.cos(angle - spread), y: tip.y - length * Math.sin(angle - spread) },
2975
+ tip,
2976
+ { x: tip.x - length * Math.cos(angle + spread), y: tip.y - length * Math.sin(angle + spread) }
2977
+ ];
2978
+ }
2979
+ function arrowHeadPath(tip, angle, length) {
2980
+ const [a, t, b] = arrowHeadPoints(tip, angle, length);
2981
+ return `M ${fmt(a.x)} ${fmt(a.y)} L ${fmt(t.x)} ${fmt(t.y)} L ${fmt(b.x)} ${fmt(b.y)}`;
2666
2982
  }
2667
2983
  function pathLength(points) {
2668
2984
  let total = 0;
@@ -3774,7 +4090,7 @@ function BoxGeometry({
3774
4090
  }
3775
4091
  );
3776
4092
  case "note": {
3777
- const f = NOTE_FOLD(b);
4093
+ const f3 = NOTE_FOLD(b);
3778
4094
  const r = b.x + b.w;
3779
4095
  const btm = b.y + b.h;
3780
4096
  return /* @__PURE__ */ jsxs4("g", { children: [
@@ -3782,7 +4098,7 @@ function BoxGeometry({
3782
4098
  "path",
3783
4099
  {
3784
4100
  ...stroke,
3785
- d: `M ${n(b.x)} ${n(b.y)} H ${n(r)} V ${n(btm - f)} L ${n(r - f)} ${n(btm)} H ${n(b.x)} Z`,
4101
+ d: `M ${n(b.x)} ${n(b.y)} H ${n(r)} V ${n(btm - f3)} L ${n(r - f3)} ${n(btm)} H ${n(b.x)} Z`,
3786
4102
  fill
3787
4103
  }
3788
4104
  ),
@@ -3790,7 +4106,7 @@ function BoxGeometry({
3790
4106
  "path",
3791
4107
  {
3792
4108
  ...stroke,
3793
- d: `M ${n(r - f)} ${n(btm)} V ${n(btm - f)} H ${n(r)}`,
4109
+ d: `M ${n(r - f3)} ${n(btm)} V ${n(btm - f3)} H ${n(r)}`,
3794
4110
  fill: "rgba(0,0,0,0.08)"
3795
4111
  }
3796
4112
  )
@@ -3873,41 +4189,418 @@ function BoxGeometry({
3873
4189
  }
3874
4190
  }
3875
4191
 
3876
- // src/drawing/canvas/ShapeView.tsx
3877
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
3878
- import { createElement } from "react";
3879
- var CONNECTOR_FONT_SIZE = 12;
3880
- var CONNECTOR_LABEL_MAX_WIDTH = 160;
3881
- function slotLayout(shape) {
3882
- const def = boxDefinition(shape);
3883
- return {
3884
- area: def ? def.textArea(shape) : bbox(shape),
3885
- slots: def ? def.textSlots : ["label", "text", "footer"]
4192
+ // src/drawing/ink.ts
4193
+ var SAMPLE_STEP = 5;
4194
+ var PRESSURE = 0.3;
4195
+ function seedFrom(text) {
4196
+ let h = 2166136261;
4197
+ for (let i = 0; i < text.length; i++) {
4198
+ h ^= text.charCodeAt(i);
4199
+ h = Math.imul(h, 16777619);
4200
+ }
4201
+ return h >>> 0;
4202
+ }
4203
+ function mulberry32(seed) {
4204
+ let a = seed >>> 0;
4205
+ return () => {
4206
+ a = a + 1831565813 | 0;
4207
+ let t = Math.imul(a ^ a >>> 15, 1 | a);
4208
+ t = t + Math.imul(t ^ t >>> 7, 61 | t) ^ t;
4209
+ return ((t ^ t >>> 14) >>> 0) / 4294967296;
3886
4210
  };
3887
4211
  }
3888
- function slotAt(shape, y) {
3889
- const { area, slots } = slotLayout(shape);
3890
- const rel = (y - area.y) / Math.max(area.h, 1);
3891
- if (rel < 0.3 && slots.includes("label")) return "label";
3892
- if (rel > 0.7 && slots.includes("footer")) return "footer";
3893
- return slots.includes("text") ? "text" : slots[0];
4212
+ function inkAmplitude(size) {
4213
+ return Math.min(4, Math.max(1, size * 0.03));
4214
+ }
4215
+ function inkFillOffset(seed) {
4216
+ const rand = mulberry32(seed ^ 2654435769);
4217
+ const angle = rand() * Math.PI * 2;
4218
+ const d = 2 + rand();
4219
+ return { x: Math.cos(angle) * d, y: Math.sin(angle) * d };
4220
+ }
4221
+ function makeField(seed, amplitude, closed) {
4222
+ const rand = mulberry32(seed);
4223
+ const int = (lo, span) => lo + Math.floor(rand() * span);
4224
+ const f1 = closed ? int(2, 2) : 1.5 + rand();
4225
+ const f22 = closed ? int(5, 3) : 3 + rand() * 2;
4226
+ const g = closed ? int(2, 2) : 1 + rand();
4227
+ const p1 = rand() * Math.PI * 2;
4228
+ const p2 = rand() * Math.PI * 2;
4229
+ const pg = rand() * Math.PI * 2;
4230
+ const a1 = amplitude * (0.55 + rand() * 0.15);
4231
+ const a2 = amplitude * 0.3;
4232
+ const TAU = Math.PI * 2;
4233
+ return {
4234
+ offset: (t) => a1 * Math.sin(TAU * f1 * t + p1) + a2 * Math.sin(TAU * f22 * t + p2),
4235
+ pressure: (t) => 1 + PRESSURE * Math.sin(TAU * g * t + pg)
4236
+ };
3894
4237
  }
3895
- var textStyle = { userSelect: "none" };
3896
- function luminance(color) {
3897
- const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(color);
3898
- if (!m) return 1;
3899
- const hex = m[1].length === 3 ? m[1].replace(/./g, (c2) => c2 + c2) : m[1];
3900
- const [r, g, b] = [0, 2, 4].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255);
3901
- return 0.2126 * r + 0.7152 * g + 0.0722 * b;
4238
+ function resample(points, closed) {
4239
+ const src = closed ? [...points, points[0]] : [...points];
4240
+ const lengths = [];
4241
+ let total = 0;
4242
+ for (let i = 1; i < src.length; i++) {
4243
+ const l = Math.hypot(src[i].x - src[i - 1].x, src[i].y - src[i - 1].y);
4244
+ lengths.push(l);
4245
+ total += l;
4246
+ }
4247
+ if (total === 0) return { points: [src[0]], ts: [0] };
4248
+ const out = [];
4249
+ const ts = [];
4250
+ let walked = 0;
4251
+ for (let i = 1; i < src.length; i++) {
4252
+ const a = src[i - 1];
4253
+ const b = src[i];
4254
+ const l = lengths[i - 1];
4255
+ const n2 = Math.max(1, Math.round(l / SAMPLE_STEP));
4256
+ for (let k = 0; k < n2; k++) {
4257
+ const u = k / n2;
4258
+ out.push({ x: a.x + (b.x - a.x) * u, y: a.y + (b.y - a.y) * u });
4259
+ ts.push((walked + l * u) / total);
4260
+ }
4261
+ walked += l;
4262
+ }
4263
+ if (!closed) {
4264
+ out.push(src[src.length - 1]);
4265
+ ts.push(1);
4266
+ }
4267
+ return { points: out, ts };
4268
+ }
4269
+ function normalAt(points, i, closed) {
4270
+ const n2 = points.length;
4271
+ const prev = points[closed ? (i - 1 + n2) % n2 : Math.max(0, i - 1)];
4272
+ const next = points[closed ? (i + 1) % n2 : Math.min(n2 - 1, i + 1)];
4273
+ const tx = next.x - prev.x;
4274
+ const ty = next.y - prev.y;
4275
+ const len = Math.hypot(tx, ty) || 1;
4276
+ return { x: -ty / len, y: tx / len };
4277
+ }
4278
+ var f = (v) => Number.isInteger(v) ? String(v) : v.toFixed(2);
4279
+ var pathOf = (points) => points.map((p, i) => `${i === 0 ? "M" : "L"} ${f(p.x)} ${f(p.y)}`).join(" ");
4280
+ function inkStroke(points, options) {
4281
+ if (points.length < 2) return { ring: "", center: "" };
4282
+ const { closed, seed, width, amplitude } = options;
4283
+ const field = makeField(seed, amplitude, closed);
4284
+ const { points: pts, ts } = resample(points, closed);
4285
+ if (pts.length < 2) return { ring: "", center: "" };
4286
+ const center2 = [];
4287
+ const outer = [];
4288
+ const inner = [];
4289
+ for (let i = 0; i < pts.length; i++) {
4290
+ const t = ts[i];
4291
+ const nrm = normalAt(pts, i, closed);
4292
+ const off = field.offset(t);
4293
+ const c2 = { x: pts[i].x + nrm.x * off, y: pts[i].y + nrm.y * off };
4294
+ const taper = closed ? 1 : 0.55 + 0.45 * Math.min(1, t / 0.1, (1 - t) / 0.1);
4295
+ const half = width * field.pressure(t) * taper / 2;
4296
+ center2.push(c2);
4297
+ outer.push({ x: c2.x + nrm.x * half, y: c2.y + nrm.y * half });
4298
+ inner.push({ x: c2.x - nrm.x * half, y: c2.y - nrm.y * half });
4299
+ }
4300
+ if (closed) {
4301
+ return {
4302
+ ring: `${pathOf(outer)} Z ${pathOf([...inner].reverse())} Z`,
4303
+ center: `${pathOf(center2)} Z`
4304
+ };
4305
+ }
4306
+ return {
4307
+ ring: `${pathOf(outer)} ${pathOf([...inner].reverse()).replace(/^M/, "L")} Z`,
4308
+ center: pathOf(center2)
4309
+ };
3902
4310
  }
3903
- function textColorFor(shape) {
3904
- if (shape.stroke === "transparent" || shape.stroke === "none") return "#1e1e1e";
3905
- if (luminance(shape.fill) < 0.35) return "#ffffff";
3906
- return shape.stroke;
4311
+ function roundedRectPolygon(r, radius, segments = 4) {
4312
+ const rad = Math.min(radius, r.w / 2, r.h / 2);
4313
+ if (rad <= 0) {
4314
+ return [
4315
+ { x: r.x, y: r.y },
4316
+ { x: r.x + r.w, y: r.y },
4317
+ { x: r.x + r.w, y: r.y + r.h },
4318
+ { x: r.x, y: r.y + r.h }
4319
+ ];
4320
+ }
4321
+ const corners = [
4322
+ [r.x + r.w - rad, r.y + rad, -Math.PI / 2],
4323
+ [r.x + r.w - rad, r.y + r.h - rad, 0],
4324
+ [r.x + rad, r.y + r.h - rad, Math.PI / 2],
4325
+ [r.x + rad, r.y + rad, Math.PI]
4326
+ ];
4327
+ const out = [];
4328
+ for (const [cx, cy, start] of corners) {
4329
+ for (let i = 0; i <= segments; i++) {
4330
+ const a = start + Math.PI / 2 * (i / segments);
4331
+ out.push({ x: cx + rad * Math.cos(a), y: cy + rad * Math.sin(a) });
4332
+ }
4333
+ }
4334
+ return out;
3907
4335
  }
3908
- var hintStyle = { userSelect: "none", pointerEvents: "none" };
3909
- function BoxTexts({
3910
- shape,
4336
+ function roundedPolyline(points, cornerRadius = 6, segments = 4) {
4337
+ if (points.length < 3) return [...points];
4338
+ const out = [points[0]];
4339
+ for (let i = 1; i < points.length - 1; i++) {
4340
+ const prev = points[i - 1];
4341
+ const p = points[i];
4342
+ const next = points[i + 1];
4343
+ const inLen = Math.hypot(p.x - prev.x, p.y - prev.y);
4344
+ const outLen = Math.hypot(next.x - p.x, next.y - p.y);
4345
+ const r = Math.min(cornerRadius, inLen / 2, outLen / 2);
4346
+ if (r < 0.5) {
4347
+ out.push(p);
4348
+ continue;
4349
+ }
4350
+ const a = { x: p.x - (p.x - prev.x) / inLen * r, y: p.y - (p.y - prev.y) / inLen * r };
4351
+ const b = { x: p.x + (next.x - p.x) / outLen * r, y: p.y + (next.y - p.y) / outLen * r };
4352
+ for (let k = 0; k <= segments; k++) {
4353
+ const u = k / segments;
4354
+ const v = 1 - u;
4355
+ out.push({
4356
+ x: v * v * a.x + 2 * v * u * p.x + u * u * b.x,
4357
+ y: v * v * a.y + 2 * v * u * p.y + u * u * b.y
4358
+ });
4359
+ }
4360
+ }
4361
+ out.push(points[points.length - 1]);
4362
+ return out;
4363
+ }
4364
+ function sampleCubic(p0, p1, p2, p3, segments = 10) {
4365
+ const out = [];
4366
+ for (let k = 1; k <= segments; k++) {
4367
+ const u = k / segments;
4368
+ const v = 1 - u;
4369
+ out.push({
4370
+ x: v * v * v * p0.x + 3 * v * v * u * p1.x + 3 * v * u * u * p2.x + u * u * u * p3.x,
4371
+ y: v * v * v * p0.y + 3 * v * v * u * p1.y + 3 * v * u * u * p2.y + u * u * u * p3.y
4372
+ });
4373
+ }
4374
+ return out;
4375
+ }
4376
+ function arcPolygon(cx, cy, rx, ry, from, to, segments = 12) {
4377
+ return Array.from({ length: segments + 1 }, (_, i) => {
4378
+ const a = from + (to - from) * i / segments;
4379
+ return { x: cx + rx * Math.cos(a), y: cy + ry * Math.sin(a) };
4380
+ });
4381
+ }
4382
+
4383
+ // src/drawing/shapes/inkRender.tsx
4384
+ import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
4385
+ var f2 = (v) => Number.isInteger(v) ? String(v) : v.toFixed(2);
4386
+ function extent(points) {
4387
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
4388
+ for (const p of points) {
4389
+ if (p.x < minX) minX = p.x;
4390
+ if (p.x > maxX) maxX = p.x;
4391
+ if (p.y < minY) minY = p.y;
4392
+ if (p.y > maxY) maxY = p.y;
4393
+ }
4394
+ return { w: maxX - minX, h: maxY - minY };
4395
+ }
4396
+ function InkBoxGeometry({ shape }) {
4397
+ const b = bbox(shape);
4398
+ const seed = seedFrom(shape.id);
4399
+ const width = shape.strokeWidth;
4400
+ const off = inkFillOffset(seed);
4401
+ const fillTransform = `translate(${f2(off.x)} ${f2(off.y)})`;
4402
+ const amplitudeOf = (points) => inkAmplitude(Math.min(extent(points).w, extent(points).h));
4403
+ const closed = (points, part, fill = shape.fill) => {
4404
+ const s = inkStroke(points, { closed: true, seed: seed + part, width, amplitude: amplitudeOf(points) });
4405
+ return /* @__PURE__ */ jsxs5("g", { children: [
4406
+ /* @__PURE__ */ jsx5("path", { d: s.center, fill, stroke: "none", transform: fillTransform }),
4407
+ /* @__PURE__ */ jsx5("path", { d: s.ring, fill: shape.stroke, fillRule: "evenodd", stroke: "none" })
4408
+ ] });
4409
+ };
4410
+ const open = (points, part, w = width) => /* @__PURE__ */ jsx5(
4411
+ "path",
4412
+ {
4413
+ d: inkStroke(points, { closed: false, seed: seed + part, width: w, amplitude: amplitudeOf(points) }).ring,
4414
+ fill: shape.stroke,
4415
+ stroke: "none"
4416
+ }
4417
+ );
4418
+ switch (shape.type) {
4419
+ case "rect":
4420
+ return closed(roundedRectPolygon(b, Math.min(8, b.w / 4, b.h / 4)), 0);
4421
+ case "ellipse":
4422
+ return closed(ellipsePolygon(b, 64), 0);
4423
+ case "diamond":
4424
+ return closed(
4425
+ [
4426
+ { x: b.x + b.w / 2, y: b.y },
4427
+ { x: b.x + b.w, y: b.y + b.h / 2 },
4428
+ { x: b.x + b.w / 2, y: b.y + b.h },
4429
+ { x: b.x, y: b.y + b.h / 2 }
4430
+ ],
4431
+ 0
4432
+ );
4433
+ case "note": {
4434
+ const fold = NOTE_FOLD(b);
4435
+ const r = b.x + b.w;
4436
+ const btm = b.y + b.h;
4437
+ const fillPts = [
4438
+ { x: b.x, y: b.y },
4439
+ { x: r, y: b.y },
4440
+ { x: r, y: btm - fold },
4441
+ { x: r - fold, y: btm },
4442
+ { x: b.x, y: btm }
4443
+ ];
4444
+ const foldPts = [
4445
+ { x: r - fold, y: btm },
4446
+ { x: r - fold, y: btm - fold },
4447
+ { x: r, y: btm - fold }
4448
+ ];
4449
+ return /* @__PURE__ */ jsxs5("g", { children: [
4450
+ closed(fillPts, 0),
4451
+ /* @__PURE__ */ jsx5(
4452
+ "path",
4453
+ {
4454
+ d: `M ${foldPts.map((p) => `${f2(p.x)} ${f2(p.y)}`).join(" L ")} Z`,
4455
+ fill: "rgba(0,0,0,0.08)",
4456
+ stroke: "none"
4457
+ }
4458
+ ),
4459
+ open(foldPts, 1)
4460
+ ] });
4461
+ }
4462
+ case "cylinder": {
4463
+ const ry = CYLINDER_RY(b);
4464
+ const rx = b.w / 2;
4465
+ const cx = b.x + rx;
4466
+ const body = [
4467
+ { x: b.x, y: b.y + ry },
4468
+ { x: b.x, y: b.y + b.h - ry },
4469
+ ...arcPolygon(cx, b.y + b.h - ry, rx, ry, Math.PI, 0, 16),
4470
+ { x: b.x + b.w, y: b.y + ry }
4471
+ ];
4472
+ const s = inkStroke(body, { closed: false, seed: seed + 0, width, amplitude: amplitudeOf(body) });
4473
+ return /* @__PURE__ */ jsxs5("g", { children: [
4474
+ /* @__PURE__ */ jsx5("path", { d: `${s.center} Z`, fill: shape.fill, stroke: "none", transform: fillTransform }),
4475
+ /* @__PURE__ */ jsx5("path", { d: s.ring, fill: shape.stroke, stroke: "none" }),
4476
+ closed(ellipsePolygon({ x: b.x, y: b.y, w: b.w, h: ry * 2 }, 48), 1)
4477
+ ] });
4478
+ }
4479
+ case "cloud": {
4480
+ const p = (u, v) => ({ x: b.x + u * b.w, y: b.y + v * b.h });
4481
+ const start = p(0.22, 0.86);
4482
+ const segs = [
4483
+ [p(0.04, 0.88), p(0, 0.58), p(0.16, 0.5)],
4484
+ [p(0.08, 0.26), p(0.3, 0.12), p(0.42, 0.28)],
4485
+ [p(0.5, 0.02), p(0.76, 0.04), p(0.78, 0.3)],
4486
+ [p(0.98, 0.26), p(1.04, 0.56), p(0.88, 0.64)],
4487
+ [p(1, 0.8), p(0.9, 0.9), p(0.76, 0.86)]
4488
+ ];
4489
+ const pts = [start];
4490
+ let from = start;
4491
+ for (const [c1, c2, to] of segs) {
4492
+ pts.push(...sampleCubic(from, c1, c2, to, 8));
4493
+ from = to;
4494
+ }
4495
+ return closed(pts, 0);
4496
+ }
4497
+ case "queue": {
4498
+ const rx = QUEUE_RX(b);
4499
+ const ry = b.h / 2;
4500
+ const body = [
4501
+ { x: b.x + rx, y: b.y },
4502
+ { x: b.x + b.w - rx, y: b.y },
4503
+ { x: b.x + b.w - rx, y: b.y + b.h },
4504
+ { x: b.x + rx, y: b.y + b.h },
4505
+ ...arcPolygon(b.x + rx, b.y + ry, rx, ry, Math.PI / 2, 3 * Math.PI / 2, 16).slice(1, -1)
4506
+ ];
4507
+ return /* @__PURE__ */ jsxs5("g", { children: [
4508
+ closed(body, 0),
4509
+ closed(ellipsePolygon({ x: b.x + b.w - rx * 2, y: b.y, w: rx * 2, h: b.h }, 48), 1)
4510
+ ] });
4511
+ }
4512
+ case "actor": {
4513
+ const figH = b.h * ACTOR_FIGURE_RATIO;
4514
+ const cx = b.x + b.w / 2;
4515
+ const r = Math.max(4, Math.min(figH * 0.16, b.w * 0.2));
4516
+ const neck = b.y + r * 2;
4517
+ const hip = b.y + figH * 0.62;
4518
+ const armY = neck + figH * 0.12;
4519
+ const reach = Math.min(b.w * 0.32, figH * 0.3);
4520
+ return /* @__PURE__ */ jsxs5("g", { children: [
4521
+ closed(ellipsePolygon({ x: cx - r, y: b.y, w: r * 2, h: r * 2 }, 32), 0),
4522
+ open([{ x: cx, y: neck }, { x: cx, y: hip }], 1),
4523
+ open([{ x: cx - reach, y: armY }, { x: cx + reach, y: armY }], 2),
4524
+ open(
4525
+ [
4526
+ { x: cx - reach, y: b.y + figH },
4527
+ { x: cx, y: hip },
4528
+ { x: cx + reach, y: b.y + figH }
4529
+ ],
4530
+ 3
4531
+ )
4532
+ ] });
4533
+ }
4534
+ default:
4535
+ return null;
4536
+ }
4537
+ }
4538
+ function InkConnector({
4539
+ shape,
4540
+ points
4541
+ }) {
4542
+ if (points.length < 2) return null;
4543
+ const seed = seedFrom(shape.id);
4544
+ const length = pathLength(points);
4545
+ const amplitude = Math.min(3, Math.max(0.8, length * 0.015));
4546
+ const width = shape.strokeWidth;
4547
+ const line = inkStroke(roundedPolyline(points), { closed: false, seed, width, amplitude });
4548
+ const heads = [];
4549
+ if (shape.type === "arrow" && length >= 1) {
4550
+ const headLength = Math.min(14, 4 + length / 4);
4551
+ const last = points.length - 1;
4552
+ heads.push(arrowHeadPoints(points[last], segmentAngleAt(points, last, false), headLength));
4553
+ if (shape.bidirectional) {
4554
+ heads.push(arrowHeadPoints(points[0], segmentAngleAt(points, 0, true), headLength));
4555
+ }
4556
+ }
4557
+ return /* @__PURE__ */ jsxs5("g", { fill: shape.stroke, stroke: "none", children: [
4558
+ /* @__PURE__ */ jsx5("path", { d: line.ring }),
4559
+ heads.map((pts, i) => /* @__PURE__ */ jsx5(
4560
+ "path",
4561
+ {
4562
+ d: inkStroke(pts, { closed: false, seed: seed + 1 + i, width: width * 1.15, amplitude: 0.8 }).ring
4563
+ },
4564
+ i
4565
+ ))
4566
+ ] });
4567
+ }
4568
+
4569
+ // src/drawing/canvas/ShapeView.tsx
4570
+ import { Fragment, jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
4571
+ import { createElement } from "react";
4572
+ var CONNECTOR_FONT_SIZE = 12;
4573
+ var CONNECTOR_LABEL_MAX_WIDTH = 160;
4574
+ function slotLayout(shape) {
4575
+ const def = boxDefinition(shape);
4576
+ return {
4577
+ area: def ? def.textArea(shape) : bbox(shape),
4578
+ slots: def ? def.textSlots : ["label", "text", "footer"]
4579
+ };
4580
+ }
4581
+ function slotAt(shape, y) {
4582
+ const { area, slots } = slotLayout(shape);
4583
+ const rel = (y - area.y) / Math.max(area.h, 1);
4584
+ if (rel < 0.3 && slots.includes("label")) return "label";
4585
+ if (rel > 0.7 && slots.includes("footer")) return "footer";
4586
+ return slots.includes("text") ? "text" : slots[0];
4587
+ }
4588
+ var textStyle = { userSelect: "none" };
4589
+ function luminance(color) {
4590
+ const m = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(color);
4591
+ if (!m) return 1;
4592
+ const hex = m[1].length === 3 ? m[1].replace(/./g, (c2) => c2 + c2) : m[1];
4593
+ const [r, g, b] = [0, 2, 4].map((i) => parseInt(hex.slice(i, i + 2), 16) / 255);
4594
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
4595
+ }
4596
+ function textColorFor(shape) {
4597
+ if (shape.stroke === "transparent" || shape.stroke === "none") return "#1e1e1e";
4598
+ if (luminance(shape.fill) < 0.35) return "#ffffff";
4599
+ return shape.stroke;
4600
+ }
4601
+ var hintStyle = { userSelect: "none", pointerEvents: "none" };
4602
+ function BoxTexts({
4603
+ shape,
3911
4604
  hideField,
3912
4605
  showHints
3913
4606
  }) {
@@ -3925,7 +4618,7 @@ function BoxTexts({
3925
4618
  fill: textColorFor(shape),
3926
4619
  textAnchor: "middle"
3927
4620
  };
3928
- return /* @__PURE__ */ jsxs5("g", { children: [
4621
+ return /* @__PURE__ */ jsxs6("g", { children: [
3929
4622
  slots.includes("label") && hideField !== "label" && (shape.label ? labelLines.map((line, i) => /* @__PURE__ */ createElement(
3930
4623
  "text",
3931
4624
  {
@@ -3940,7 +4633,7 @@ function BoxTexts({
3940
4633
  style: textStyle
3941
4634
  },
3942
4635
  line
3943
- )) : hints && /* @__PURE__ */ jsx5(
4636
+ )) : hints && /* @__PURE__ */ jsx6(
3944
4637
  "text",
3945
4638
  {
3946
4639
  ...common,
@@ -3963,7 +4656,7 @@ function BoxTexts({
3963
4656
  style: textStyle
3964
4657
  },
3965
4658
  line
3966
- )) : hints && /* @__PURE__ */ jsx5(
4659
+ )) : hints && /* @__PURE__ */ jsx6(
3967
4660
  "text",
3968
4661
  {
3969
4662
  ...common,
@@ -3987,7 +4680,7 @@ function BoxTexts({
3987
4680
  style: textStyle
3988
4681
  },
3989
4682
  line
3990
- )) : hints && /* @__PURE__ */ jsx5(
4683
+ )) : hints && /* @__PURE__ */ jsx6(
3991
4684
  "text",
3992
4685
  {
3993
4686
  ...common,
@@ -4011,8 +4704,8 @@ function ConnectorLabel({
4011
4704
  const { x: midX, y: midY } = connectorMidpoint(points);
4012
4705
  const lineH = CONNECTOR_FONT_SIZE * LINE_HEIGHT;
4013
4706
  const startY = midY - (lines.length - 1) * lineH / 2 + CONNECTOR_FONT_SIZE * 0.35;
4014
- return /* @__PURE__ */ jsxs5("g", { children: [
4015
- /* @__PURE__ */ jsx5(
4707
+ return /* @__PURE__ */ jsxs6("g", { children: [
4708
+ /* @__PURE__ */ jsx6(
4016
4709
  "rect",
4017
4710
  {
4018
4711
  x: midX - size.w / 2 - 5,
@@ -4024,7 +4717,7 @@ function ConnectorLabel({
4024
4717
  opacity: 0.94
4025
4718
  }
4026
4719
  ),
4027
- lines.map((line, i) => /* @__PURE__ */ jsx5(
4720
+ lines.map((line, i) => /* @__PURE__ */ jsx6(
4028
4721
  "text",
4029
4722
  {
4030
4723
  x: midX,
@@ -4043,7 +4736,8 @@ function ShapeView({
4043
4736
  shape,
4044
4737
  points,
4045
4738
  hideField,
4046
- showHints
4739
+ showHints,
4740
+ ink = false
4047
4741
  }) {
4048
4742
  const stroke = {
4049
4743
  stroke: shape.stroke,
@@ -4052,9 +4746,9 @@ function ShapeView({
4052
4746
  strokeLinejoin: "round"
4053
4747
  };
4054
4748
  if (isBoxType(shape.type)) {
4055
- return /* @__PURE__ */ jsxs5("g", { children: [
4056
- /* @__PURE__ */ jsx5(BoxGeometry, { shape, stroke }),
4057
- /* @__PURE__ */ jsx5(BoxTexts, { shape, hideField, showHints })
4749
+ return /* @__PURE__ */ jsxs6("g", { children: [
4750
+ ink ? /* @__PURE__ */ jsx6(InkBoxGeometry, { shape }) : /* @__PURE__ */ jsx6(BoxGeometry, { shape, stroke }),
4751
+ /* @__PURE__ */ jsx6(BoxTexts, { shape, hideField, showHints })
4058
4752
  ] });
4059
4753
  }
4060
4754
  if (isConnectorType(shape.type)) {
@@ -4062,13 +4756,15 @@ function ShapeView({
4062
4756
  { x: shape.x, y: shape.y },
4063
4757
  { x: shape.x + shape.w, y: shape.y + shape.h }
4064
4758
  ];
4065
- return /* @__PURE__ */ jsxs5("g", { children: [
4066
- /* @__PURE__ */ jsx5("path", { ...stroke, d: polylinePath(pts), fill: "none" }),
4067
- arrowHeads(shape, pts).map((d, i) => /* @__PURE__ */ jsx5("path", { ...stroke, d, fill: "none" }, i)),
4068
- shape.text && hideField !== "text" && /* @__PURE__ */ jsx5(ConnectorLabel, { shape, points: pts })
4759
+ return /* @__PURE__ */ jsxs6("g", { children: [
4760
+ ink ? /* @__PURE__ */ jsx6(InkConnector, { shape, points: pts }) : /* @__PURE__ */ jsxs6(Fragment, { children: [
4761
+ /* @__PURE__ */ jsx6("path", { ...stroke, d: polylinePath(pts), fill: "none" }),
4762
+ arrowHeads(shape, pts).map((d, i) => /* @__PURE__ */ jsx6("path", { ...stroke, d, fill: "none" }, i))
4763
+ ] }),
4764
+ shape.text && hideField !== "text" && /* @__PURE__ */ jsx6(ConnectorLabel, { shape, points: pts })
4069
4765
  ] });
4070
4766
  }
4071
- return /* @__PURE__ */ jsx5(
4767
+ return /* @__PURE__ */ jsx6(
4072
4768
  "text",
4073
4769
  {
4074
4770
  x: shape.x,
@@ -4076,7 +4772,7 @@ function ShapeView({
4076
4772
  fill: shape.stroke,
4077
4773
  fontSize: FONT_SIZE,
4078
4774
  style: { userSelect: "none", whiteSpace: "pre" },
4079
- children: (shape.text ?? "").split("\n").map((line, i) => /* @__PURE__ */ jsx5("tspan", { x: shape.x, dy: i === 0 ? 0 : FONT_SIZE * LINE_HEIGHT, children: line }, i))
4775
+ children: (shape.text ?? "").split("\n").map((line, i) => /* @__PURE__ */ jsx6("tspan", { x: shape.x, dy: i === 0 ? 0 : FONT_SIZE * LINE_HEIGHT, children: line }, i))
4080
4776
  }
4081
4777
  );
4082
4778
  }
@@ -4085,10 +4781,10 @@ function HitArea({
4085
4781
  points
4086
4782
  }) {
4087
4783
  if (isConnectorType(shape.type) && points) {
4088
- return /* @__PURE__ */ jsx5("path", { d: polylinePath(points), fill: "none", stroke: "transparent", strokeWidth: 16 });
4784
+ return /* @__PURE__ */ jsx6("path", { d: polylinePath(points), fill: "none", stroke: "transparent", strokeWidth: 16 });
4089
4785
  }
4090
4786
  const b = bbox(shape);
4091
- return /* @__PURE__ */ jsx5(
4787
+ return /* @__PURE__ */ jsx6(
4092
4788
  "rect",
4093
4789
  {
4094
4790
  x: b.x - 2,
@@ -4103,11 +4799,11 @@ function HitArea({
4103
4799
 
4104
4800
  // src/drawing/canvas/TextEditOverlay.tsx
4105
4801
  import {
4106
- useEffect as useEffect5,
4802
+ useEffect as useEffect6,
4107
4803
  useRef as useRef2,
4108
4804
  useState
4109
4805
  } from "react";
4110
- import { jsx as jsx6 } from "react/jsx-runtime";
4806
+ import { jsx as jsx7 } from "react/jsx-runtime";
4111
4807
  function TextEditOverlay({
4112
4808
  shape,
4113
4809
  field,
@@ -4119,7 +4815,7 @@ function TextEditOverlay({
4119
4815
  const ref = useRef2(null);
4120
4816
  const valueRef = useRef2(value);
4121
4817
  valueRef.current = value;
4122
- useEffect5(() => {
4818
+ useEffect6(() => {
4123
4819
  const el = ref.current;
4124
4820
  if (!el) return;
4125
4821
  el.focus();
@@ -4210,7 +4906,7 @@ function TextEditOverlay({
4210
4906
  });
4211
4907
  }
4212
4908
  const placeholder = field === "label" ? "Label" : field === "footer" ? "Footer" : "Text";
4213
- return /* @__PURE__ */ jsx6(
4909
+ return /* @__PURE__ */ jsx7(
4214
4910
  "textarea",
4215
4911
  {
4216
4912
  ref,
@@ -4227,19 +4923,19 @@ function TextEditOverlay({
4227
4923
  }
4228
4924
 
4229
4925
  // src/drawing/canvas/Toolbar.tsx
4230
- import { useEffect as useEffect6, useRef as useRef3, useState as useState2 } from "react";
4926
+ import { useEffect as useEffect7, useRef as useRef3, useState as useState2 } from "react";
4231
4927
 
4232
4928
  // src/components/blockWidthOptions.tsx
4233
- import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
4929
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
4234
4930
  var LAYOUT_OPTIONS = [
4235
4931
  {
4236
4932
  preset: "compact",
4237
4933
  label: "Compact (shrink to content, tight rows)",
4238
4934
  width: "content",
4239
4935
  density: "compact",
4240
- icon: /* @__PURE__ */ jsxs6(Fragment, { children: [
4241
- /* @__PURE__ */ jsx7("path", { d: "M3 4v12M17 4v12" }),
4242
- /* @__PURE__ */ jsx7("path", { d: "M5.5 10h3M11.5 10h3M6.5 7.5L9 10l-2.5 2.5M13.5 7.5L11 10l2.5 2.5" })
4936
+ icon: /* @__PURE__ */ jsxs7(Fragment2, { children: [
4937
+ /* @__PURE__ */ jsx8("path", { d: "M3 4v12M17 4v12" }),
4938
+ /* @__PURE__ */ jsx8("path", { d: "M5.5 10h3M11.5 10h3M6.5 7.5L9 10l-2.5 2.5M13.5 7.5L11 10l2.5 2.5" })
4243
4939
  ] })
4244
4940
  },
4245
4941
  {
@@ -4247,9 +4943,9 @@ var LAYOUT_OPTIONS = [
4247
4943
  label: "Comfortable (text width)",
4248
4944
  width: "text",
4249
4945
  density: "comfortable",
4250
- icon: /* @__PURE__ */ jsxs6(Fragment, { children: [
4251
- /* @__PURE__ */ jsx7("path", { d: "M3 4v12M17 4v12" }),
4252
- /* @__PURE__ */ jsx7("path", { d: "M6.5 7h7M6.5 10h7M6.5 13h4.5" })
4946
+ icon: /* @__PURE__ */ jsxs7(Fragment2, { children: [
4947
+ /* @__PURE__ */ jsx8("path", { d: "M3 4v12M17 4v12" }),
4948
+ /* @__PURE__ */ jsx8("path", { d: "M6.5 7h7M6.5 10h7M6.5 13h4.5" })
4253
4949
  ] })
4254
4950
  },
4255
4951
  {
@@ -4257,9 +4953,9 @@ var LAYOUT_OPTIONS = [
4257
4953
  label: "Full width",
4258
4954
  width: "full",
4259
4955
  density: "comfortable",
4260
- icon: /* @__PURE__ */ jsxs6(Fragment, { children: [
4261
- /* @__PURE__ */ jsx7("path", { d: "M3 4v12M17 4v12" }),
4262
- /* @__PURE__ */ jsx7("path", { d: "M6 10h8M8.5 7.5L6 10l2.5 2.5M11.5 7.5L14 10l-2.5 2.5" })
4956
+ icon: /* @__PURE__ */ jsxs7(Fragment2, { children: [
4957
+ /* @__PURE__ */ jsx8("path", { d: "M3 4v12M17 4v12" }),
4958
+ /* @__PURE__ */ jsx8("path", { d: "M6 10h8M8.5 7.5L6 10l2.5 2.5M11.5 7.5L14 10l-2.5 2.5" })
4263
4959
  ] })
4264
4960
  }
4265
4961
  ];
@@ -4268,7 +4964,7 @@ function layoutPreset(width) {
4268
4964
  }
4269
4965
 
4270
4966
  // src/drawing/canvas/Toolbar.tsx
4271
- import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
4967
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
4272
4968
  var PRIMARY_TOOLS = [
4273
4969
  { tool: "select", label: "Select" },
4274
4970
  { tool: "rect", label: "Rectangle" },
@@ -4287,7 +4983,7 @@ function ToolButton({
4287
4983
  className,
4288
4984
  pressed
4289
4985
  }) {
4290
- return /* @__PURE__ */ jsx8(
4986
+ return /* @__PURE__ */ jsx9(
4291
4987
  "button",
4292
4988
  {
4293
4989
  type: "button",
@@ -4296,7 +4992,7 @@ function ToolButton({
4296
4992
  "aria-pressed": pressed ?? active,
4297
4993
  className: `zui-drawing-tool ${active ? "is-active" : ""} ${className ?? ""}`,
4298
4994
  onClick,
4299
- children: /* @__PURE__ */ jsx8(Icon, { children })
4995
+ children: /* @__PURE__ */ jsx9(Icon, { children })
4300
4996
  }
4301
4997
  );
4302
4998
  }
@@ -4312,7 +5008,7 @@ function DrawingToolbar({
4312
5008
  const [lastMore, setLastMore] = useState2("note");
4313
5009
  const [copied, setCopied] = useState2(false);
4314
5010
  const moreRef = useRef3(null);
4315
- useEffect6(() => {
5011
+ useEffect7(() => {
4316
5012
  if (!moreOpen) return;
4317
5013
  const close = (e) => {
4318
5014
  if (!moreRef.current?.contains(e.target)) setMoreOpen(false);
@@ -4329,11 +5025,11 @@ function DrawingToolbar({
4329
5025
  }, [moreOpen]);
4330
5026
  const moreActive = MORE_SHAPES.includes(tool);
4331
5027
  const moreIcon = moreActive ? SHAPE_ICONS[tool] : SHAPE_ICONS[lastMore];
4332
- return /* @__PURE__ */ jsxs7(Fragment2, { children: [
4333
- /* @__PURE__ */ jsxs7("div", { className: "zui-drawing-toolbar-group", role: "toolbar", "aria-label": "Drawing tools", children: [
4334
- PRIMARY_TOOLS.map(({ tool: t, label }) => /* @__PURE__ */ jsx8(ToolButton, { label, active: tool === t, onClick: () => onToolChange(t), children: SHAPE_ICONS[t] }, t)),
4335
- /* @__PURE__ */ jsxs7("div", { className: "zui-drawing-more", ref: moreRef, children: [
4336
- /* @__PURE__ */ jsxs7(
5028
+ return /* @__PURE__ */ jsxs8(Fragment3, { children: [
5029
+ /* @__PURE__ */ jsxs8("div", { className: "zui-drawing-toolbar-group", role: "toolbar", "aria-label": "Drawing tools", children: [
5030
+ PRIMARY_TOOLS.map(({ tool: t, label }) => /* @__PURE__ */ jsx9(ToolButton, { label, active: tool === t, onClick: () => onToolChange(t), children: SHAPE_ICONS[t] }, t)),
5031
+ /* @__PURE__ */ jsxs8("div", { className: "zui-drawing-more", ref: moreRef, children: [
5032
+ /* @__PURE__ */ jsxs8(
4337
5033
  "button",
4338
5034
  {
4339
5035
  type: "button",
@@ -4344,12 +5040,12 @@ function DrawingToolbar({
4344
5040
  className: `zui-drawing-tool zui-drawing-tool-more ${moreActive ? "is-active" : ""}`,
4345
5041
  onClick: () => setMoreOpen((open) => !open),
4346
5042
  children: [
4347
- /* @__PURE__ */ jsx8(Icon, { children: moreIcon }),
4348
- /* @__PURE__ */ jsx8("span", { className: "zui-drawing-caret", "aria-hidden": "true" })
5043
+ /* @__PURE__ */ jsx9(Icon, { children: moreIcon }),
5044
+ /* @__PURE__ */ jsx9("span", { className: "zui-drawing-caret", "aria-hidden": "true" })
4349
5045
  ]
4350
5046
  }
4351
5047
  ),
4352
- moreOpen && /* @__PURE__ */ jsx8("div", { className: "zui-drawing-popover", role: "menu", children: MORE_SHAPES.map((type) => /* @__PURE__ */ jsxs7(
5048
+ moreOpen && /* @__PURE__ */ jsx9("div", { className: "zui-drawing-popover", role: "menu", children: MORE_SHAPES.map((type) => /* @__PURE__ */ jsxs8(
4353
5049
  "button",
4354
5050
  {
4355
5051
  type: "button",
@@ -4362,8 +5058,8 @@ function DrawingToolbar({
4362
5058
  setMoreOpen(false);
4363
5059
  },
4364
5060
  children: [
4365
- /* @__PURE__ */ jsx8(Icon, { size: 18, children: SHAPE_ICONS[type] }),
4366
- /* @__PURE__ */ jsx8("span", { children: BOX_DEFINITIONS[type].label })
5061
+ /* @__PURE__ */ jsx9(Icon, { size: 18, children: SHAPE_ICONS[type] }),
5062
+ /* @__PURE__ */ jsx9("span", { children: BOX_DEFINITIONS[type].label })
4367
5063
  ]
4368
5064
  },
4369
5065
  type
@@ -4371,8 +5067,8 @@ function DrawingToolbar({
4371
5067
  ] })
4372
5068
  ] }),
4373
5069
  properties,
4374
- /* @__PURE__ */ jsxs7("div", { className: "zui-drawing-toolbar-group zui-drawing-toolbar-group-end", children: [
4375
- /* @__PURE__ */ jsx8(
5070
+ /* @__PURE__ */ jsxs8("div", { className: "zui-drawing-toolbar-group zui-drawing-toolbar-group-end", children: [
5071
+ /* @__PURE__ */ jsx9(
4376
5072
  ToolButton,
4377
5073
  {
4378
5074
  label: copied ? "Copied Mermaid to clipboard" : "Copy as Mermaid",
@@ -4387,8 +5083,8 @@ function DrawingToolbar({
4387
5083
  children: copied ? UI_ICONS.check : UI_ICONS.mermaid
4388
5084
  }
4389
5085
  ),
4390
- /* @__PURE__ */ jsx8("span", { className: "zui-drawing-toolbar-divider" }),
4391
- LAYOUT_OPTIONS.map(({ preset, label, icon, width: presetWidth }) => /* @__PURE__ */ jsx8(
5086
+ /* @__PURE__ */ jsx9("span", { className: "zui-drawing-toolbar-divider" }),
5087
+ LAYOUT_OPTIONS.map(({ preset, label, icon, width: presetWidth }) => /* @__PURE__ */ jsx9(
4392
5088
  ToolButton,
4393
5089
  {
4394
5090
  label,
@@ -4403,7 +5099,7 @@ function DrawingToolbar({
4403
5099
  }
4404
5100
 
4405
5101
  // src/drawing/canvas/DrawingCanvas.tsx
4406
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
5102
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
4407
5103
  var MIN_HEIGHT = 120;
4408
5104
  var MAX_HEIGHT = 1200;
4409
5105
  var WIDTH_CLASS = {
@@ -4434,11 +5130,12 @@ function computePaths(shapes) {
4434
5130
  return paths;
4435
5131
  }
4436
5132
  function DrawingCanvas({ nodeKey, data }) {
4437
- const [editor] = useLexicalComposerContext5();
5133
+ const [editor] = useLexicalComposerContext6();
4438
5134
  const isEditable = useLexicalEditable();
4439
5135
  const [shapes, setShapes] = useState3(data.shapes);
4440
5136
  const [canvasHeight, setCanvasHeight] = useState3(data.canvasHeight);
4441
5137
  const [width, setWidth] = useState3(data.width ?? "full");
5138
+ const ink = useContext2(EditorContext)?.drawingStyle === "ink";
4442
5139
  const [tool, setTool] = useState3("select");
4443
5140
  const [selectedIds, setSelectedIds] = useState3(EMPTY_SET);
4444
5141
  const [editingText, setEditingText] = useState3(null);
@@ -4465,7 +5162,7 @@ function DrawingCanvas({ nodeKey, data }) {
4465
5162
  const paths = useMemo(() => computePaths(shapes), [shapes]);
4466
5163
  const canvasWidth = data.canvasWidth;
4467
5164
  const logicalWidth = canvasWidth ?? (width === "content" ? contentWidth(shapes, paths) : null);
4468
- useEffect7(() => {
5165
+ useEffect8(() => {
4469
5166
  const incoming = serializeDrawingData(data);
4470
5167
  if (incoming !== lastCommittedRef.current) {
4471
5168
  lastCommittedRef.current = incoming;
@@ -4476,7 +5173,7 @@ function DrawingCanvas({ nodeKey, data }) {
4476
5173
  setEditingText(null);
4477
5174
  }
4478
5175
  }, [data]);
4479
- useEffect7(() => {
5176
+ useEffect8(() => {
4480
5177
  const svg = svgRef.current;
4481
5178
  if (!logicalWidth || !svg || typeof ResizeObserver === "undefined") {
4482
5179
  setScale(1);
@@ -4506,7 +5203,7 @@ function DrawingCanvas({ nodeKey, data }) {
4506
5203
  if (json2 === lastCommittedRef.current) return;
4507
5204
  lastCommittedRef.current = json2;
4508
5205
  editor.update(() => {
4509
- const node = $getNodeByKey2(nodeKey);
5206
+ const node = $getNodeByKey4(nodeKey);
4510
5207
  if ($isDrawingNode(node)) node.setData(payload);
4511
5208
  });
4512
5209
  },
@@ -4766,7 +5463,7 @@ function DrawingCanvas({ nodeKey, data }) {
4766
5463
  }, [updateShapes]);
4767
5464
  const editingRef = useRef4(editingText);
4768
5465
  editingRef.current = editingText;
4769
- useEffect7(() => {
5466
+ useEffect8(() => {
4770
5467
  const root = rootRef.current;
4771
5468
  if (!root || !isEditable) return;
4772
5469
  const onKeyDown = (e) => {
@@ -4899,11 +5596,11 @@ function DrawingCanvas({ nodeKey, data }) {
4899
5596
  const propStroke = single?.stroke ?? selection[0]?.stroke ?? stroke;
4900
5597
  const propFill = single?.fill ?? selection[0]?.fill ?? fill;
4901
5598
  const canvasCursor = tool === "select" ? "default" : tool === "text" ? "text" : "crosshair";
4902
- return /* @__PURE__ */ jsxs8(
5599
+ return /* @__PURE__ */ jsxs9(
4903
5600
  "div",
4904
5601
  {
4905
5602
  ref: rootRef,
4906
- className: `zui-drawing-canvas ${WIDTH_CLASS[width]} ${isEditable ? "is-editable" : ""}`,
5603
+ className: `zui-drawing-canvas ${WIDTH_CLASS[width]} ${isEditable ? "is-editable" : ""} ${ink ? "is-ink" : ""}`,
4907
5604
  tabIndex: isEditable ? 0 : void 0,
4908
5605
  onFocus: () => editor.dispatchCommand(DRAWING_FOCUS_COMMAND, nodeKey),
4909
5606
  onBlur: (e) => {
@@ -4911,7 +5608,7 @@ function DrawingCanvas({ nodeKey, data }) {
4911
5608
  editor.dispatchCommand(DRAWING_FOCUS_COMMAND, null);
4912
5609
  },
4913
5610
  children: [
4914
- isEditable && /* @__PURE__ */ jsx9("div", { className: "zui-drawing-toolbar", onPointerDown: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx9(
5611
+ isEditable && /* @__PURE__ */ jsx10("div", { className: "zui-drawing-toolbar", onPointerDown: (e) => e.stopPropagation(), children: /* @__PURE__ */ jsx10(
4915
5612
  DrawingToolbar,
4916
5613
  {
4917
5614
  tool,
@@ -4925,7 +5622,7 @@ function DrawingCanvas({ nodeKey, data }) {
4925
5622
  properties: (
4926
5623
  // Inline in the same row (so the stage never shifts); shown
4927
5624
  // only while the canvas has focus (see .zui-drawing-props-host)
4928
- /* @__PURE__ */ jsx9("div", { className: "zui-drawing-props-host", children: /* @__PURE__ */ jsx9(
5625
+ /* @__PURE__ */ jsx10("div", { className: "zui-drawing-props-host", children: /* @__PURE__ */ jsx10(
4929
5626
  PropertyBar,
4930
5627
  {
4931
5628
  selection,
@@ -4940,8 +5637,8 @@ function DrawingCanvas({ nodeKey, data }) {
4940
5637
  )
4941
5638
  }
4942
5639
  ) }),
4943
- /* @__PURE__ */ jsxs8("div", { className: "zui-drawing-stage", children: [
4944
- /* @__PURE__ */ jsxs8(
5640
+ /* @__PURE__ */ jsxs9("div", { className: "zui-drawing-stage", children: [
5641
+ /* @__PURE__ */ jsxs9(
4945
5642
  "svg",
4946
5643
  {
4947
5644
  ref: svgRef,
@@ -4972,7 +5669,7 @@ function DrawingCanvas({ nodeKey, data }) {
4972
5669
  }
4973
5670
  },
4974
5671
  children: [
4975
- shapes.map((shape) => /* @__PURE__ */ jsxs8(
5672
+ shapes.map((shape) => /* @__PURE__ */ jsxs9(
4976
5673
  "g",
4977
5674
  {
4978
5675
  "data-shape-id": shape.id,
@@ -4980,11 +5677,12 @@ function DrawingCanvas({ nodeKey, data }) {
4980
5677
  style: { cursor: isEditable && tool === "select" ? "move" : void 0 },
4981
5678
  onPointerDown: (e) => handleShapePointerDown(e, shape),
4982
5679
  children: [
4983
- /* @__PURE__ */ jsx9(HitArea, { shape, points: paths.get(shape.id) }),
4984
- shape.id === editingText?.id && shape.type === "text" ? null : /* @__PURE__ */ jsx9(
5680
+ /* @__PURE__ */ jsx10(HitArea, { shape, points: paths.get(shape.id) }),
5681
+ shape.id === editingText?.id && shape.type === "text" ? null : /* @__PURE__ */ jsx10(
4985
5682
  ShapeView,
4986
5683
  {
4987
5684
  shape,
5685
+ ink,
4988
5686
  points: paths.get(shape.id),
4989
5687
  hideField: shape.id === editingText?.id ? editingText.field : null,
4990
5688
  showHints: isEditable && tool === "select" && single?.id === shape.id && shape.id !== editingText?.id
@@ -4994,7 +5692,7 @@ function DrawingCanvas({ nodeKey, data }) {
4994
5692
  },
4995
5693
  shape.id
4996
5694
  )),
4997
- hoverBox && /* @__PURE__ */ jsx9(
5695
+ hoverBox && /* @__PURE__ */ jsx10(
4998
5696
  "polygon",
4999
5697
  {
5000
5698
  className: "zui-drawing-selection zui-drawing-bind-target",
@@ -5007,7 +5705,7 @@ function DrawingCanvas({ nodeKey, data }) {
5007
5705
  pointerEvents: "none"
5008
5706
  }
5009
5707
  ),
5010
- single && isEditable && !editingText && /* @__PURE__ */ jsx9(
5708
+ single && isEditable && !editingText && /* @__PURE__ */ jsx10(
5011
5709
  SelectionOverlay,
5012
5710
  {
5013
5711
  shape: single,
@@ -5017,13 +5715,13 @@ function DrawingCanvas({ nodeKey, data }) {
5017
5715
  onWaypointRemove: removeWaypoint
5018
5716
  }
5019
5717
  ),
5020
- selection.length > 1 && isEditable && /* @__PURE__ */ jsx9(GroupSelectionOverlay, { shapes: selection, paths }),
5021
- marquee && /* @__PURE__ */ jsx9(MarqueeOverlay, { rect: marqueeRect(marquee.origin, marquee.current) })
5718
+ selection.length > 1 && isEditable && /* @__PURE__ */ jsx10(GroupSelectionOverlay, { shapes: selection, paths }),
5719
+ marquee && /* @__PURE__ */ jsx10(MarqueeOverlay, { rect: marqueeRect(marquee.origin, marquee.current) })
5022
5720
  ]
5023
5721
  }
5024
5722
  ),
5025
- isEditable && shapes.length === 0 && /* @__PURE__ */ jsx9("div", { className: "zui-drawing-empty", "aria-hidden": "true", children: "Pick a shape above, then click or drag on the canvas" }),
5026
- editingShape && editingText && /* @__PURE__ */ jsx9(
5723
+ isEditable && shapes.length === 0 && /* @__PURE__ */ jsx10("div", { className: "zui-drawing-empty", "aria-hidden": "true", children: "Pick a shape above, then click or drag on the canvas" }),
5724
+ editingShape && editingText && /* @__PURE__ */ jsx10(
5027
5725
  "div",
5028
5726
  {
5029
5727
  className: "zui-drawing-overlay",
@@ -5032,7 +5730,7 @@ function DrawingCanvas({ nodeKey, data }) {
5032
5730
  width: logicalWidth ?? void 0,
5033
5731
  height: logicalWidth ? canvasHeight : void 0
5034
5732
  },
5035
- children: /* @__PURE__ */ jsx9(
5733
+ children: /* @__PURE__ */ jsx10(
5036
5734
  TextEditOverlay,
5037
5735
  {
5038
5736
  shape: editingShape,
@@ -5044,7 +5742,7 @@ function DrawingCanvas({ nodeKey, data }) {
5044
5742
  )
5045
5743
  }
5046
5744
  ),
5047
- isEditable && /* @__PURE__ */ jsx9(
5745
+ isEditable && /* @__PURE__ */ jsx10(
5048
5746
  HeightHandle,
5049
5747
  {
5050
5748
  height: canvasHeight,
@@ -5068,7 +5766,7 @@ function HeightHandle({
5068
5766
  const latestRef = useRef4(height);
5069
5767
  latestRef.current = height;
5070
5768
  const clamp = (h) => Math.round(Math.min(MAX_HEIGHT, Math.max(MIN_HEIGHT, h)));
5071
- return /* @__PURE__ */ jsx9(
5769
+ return /* @__PURE__ */ jsx10(
5072
5770
  "div",
5073
5771
  {
5074
5772
  className: "zui-drawing-resize",
@@ -5091,13 +5789,13 @@ function HeightHandle({
5091
5789
  dragRef.current = null;
5092
5790
  onCommit(latestRef.current);
5093
5791
  },
5094
- children: /* @__PURE__ */ jsx9(Icon, { size: 14, children: UI_ICONS.grip })
5792
+ children: /* @__PURE__ */ jsx10(Icon, { size: 14, children: UI_ICONS.grip })
5095
5793
  }
5096
5794
  );
5097
5795
  }
5098
5796
 
5099
5797
  // src/nodes/DrawingNode.tsx
5100
- import { jsx as jsx10 } from "react/jsx-runtime";
5798
+ import { jsx as jsx11 } from "react/jsx-runtime";
5101
5799
  var DrawingNode = class _DrawingNode extends DecoratorNode {
5102
5800
  static getType() {
5103
5801
  return "drawing";
@@ -5161,7 +5859,7 @@ var DrawingNode = class _DrawingNode extends DecoratorNode {
5161
5859
  return false;
5162
5860
  }
5163
5861
  decorate(_editor, _config) {
5164
- return /* @__PURE__ */ jsx10(DrawingCanvas, { nodeKey: this.getKey(), data: this.getData() });
5862
+ return /* @__PURE__ */ jsx11(DrawingCanvas, { nodeKey: this.getKey(), data: this.getData() });
5165
5863
  }
5166
5864
  };
5167
5865
  function $createDrawingNode(data = serializeDrawingData(EMPTY_DRAWING)) {
@@ -5212,161 +5910,17 @@ import {
5212
5910
  TRANSFORMERS
5213
5911
  } from "@lexical/markdown";
5214
5912
  import {
5215
- $createTableCellNode,
5913
+ $createTableCellNode as $createTableCellNode2,
5216
5914
  $createTableNode,
5217
- $createTableRowNode,
5218
- $isTableCellNode,
5219
- $isTableNode as $isTableNode2,
5220
- $isTableRowNode,
5221
- TableCellHeaderStates,
5915
+ $createTableRowNode as $createTableRowNode2,
5916
+ $isTableCellNode as $isTableCellNode2,
5917
+ $isTableNode as $isTableNode3,
5918
+ $isTableRowNode as $isTableRowNode3,
5919
+ TableCellHeaderStates as TableCellHeaderStates2,
5222
5920
  TableCellNode,
5223
5921
  TableNode,
5224
5922
  TableRowNode
5225
5923
  } from "@lexical/table";
5226
-
5227
- // src/transformers/tableSettings.ts
5228
- import {
5229
- $getNodeByKey as $getNodeByKey3,
5230
- $getSelection as $getSelection2,
5231
- $isRangeSelection as $isRangeSelection2
5232
- } from "lexical";
5233
- import { $findMatchingParent } from "@lexical/utils";
5234
- import { $isTableNode, $isTableSelection } from "@lexical/table";
5235
- var DEFAULT_TABLE_SETTINGS = {
5236
- width: "full",
5237
- density: "comfortable"
5238
- };
5239
- var BLOCK_BLEED_PROPERTY = "--zui-text-editor-block-bleed";
5240
- var OPTION_DECLARATIONS = {
5241
- width: {
5242
- full: {},
5243
- content: { width: "auto", "table-layout": "auto", [BLOCK_BLEED_PROPERTY]: "0px" },
5244
- text: { [BLOCK_BLEED_PROPERTY]: "0px" }
5245
- },
5246
- density: {
5247
- comfortable: {},
5248
- compact: {
5249
- "--zui-table-cell-padding": "0.25rem 0.5rem",
5250
- "--zui-table-font-size": "0.8125rem"
5251
- },
5252
- spacious: {
5253
- "--zui-table-cell-padding": "0.875rem 1rem",
5254
- "--zui-table-font-size": "0.9375rem"
5255
- }
5256
- }
5257
- };
5258
- var SETTING_KEYS = Object.keys(OPTION_DECLARATIONS);
5259
- var EXPLICIT_WIDTH_PROPERTY = "--zui-table-width";
5260
- function parseStyle(style) {
5261
- const declarations = /* @__PURE__ */ new Map();
5262
- for (const part of style.split(";")) {
5263
- const index = part.indexOf(":");
5264
- if (index === -1) continue;
5265
- const key = part.slice(0, index).trim();
5266
- const value = part.slice(index + 1).trim();
5267
- if (key && value) declarations.set(key, value);
5268
- }
5269
- return declarations;
5270
- }
5271
- function serializeStyle(declarations) {
5272
- return [...declarations].map(([key, value]) => `${key}: ${value}`).join("; ");
5273
- }
5274
- function optionsOf(setting) {
5275
- return Object.entries(OPTION_DECLARATIONS[setting]);
5276
- }
5277
- function readSetting(declarations, setting) {
5278
- for (const [option, decls] of optionsOf(setting)) {
5279
- const entries = Object.entries(decls);
5280
- if (entries.length === 0) continue;
5281
- if (entries.every(([key, value]) => declarations.get(key) === value)) {
5282
- return option;
5283
- }
5284
- }
5285
- return DEFAULT_TABLE_SETTINGS[setting];
5286
- }
5287
- function writeSetting(declarations, setting, option) {
5288
- for (const [, decls] of optionsOf(setting)) {
5289
- for (const key of Object.keys(decls)) declarations.delete(key);
5290
- }
5291
- for (const [key, value] of Object.entries(OPTION_DECLARATIONS[setting][option])) {
5292
- declarations.set(key, value);
5293
- }
5294
- }
5295
- function $getTableSettings(table) {
5296
- const declarations = parseStyle(table.getStyle());
5297
- return {
5298
- width: readSetting(declarations, "width"),
5299
- density: readSetting(declarations, "density")
5300
- };
5301
- }
5302
- function $setTableSettings(table, settings, options = {}) {
5303
- const declarations = parseStyle(table.getStyle());
5304
- for (const key of SETTING_KEYS) {
5305
- const option = settings[key];
5306
- if (option !== void 0) writeSetting(declarations, key, option);
5307
- }
5308
- if (settings.width !== void 0) {
5309
- if (options.explicitWidth) declarations.set(EXPLICIT_WIDTH_PROPERTY, settings.width);
5310
- else declarations.delete(EXPLICIT_WIDTH_PROPERTY);
5311
- }
5312
- table.setStyle(serializeStyle(declarations));
5313
- }
5314
- function $isTableWidthExplicit(table) {
5315
- const declarations = parseStyle(table.getStyle());
5316
- return declarations.get(EXPLICIT_WIDTH_PROPERTY) === readSetting(declarations, "width");
5317
- }
5318
- function $getTableWidth(table) {
5319
- return $getTableSettings(table).width;
5320
- }
5321
- function $setTableWidth(table, width) {
5322
- $setTableSettings(table, { width });
5323
- }
5324
- function $getTableDensity(table) {
5325
- return $getTableSettings(table).density;
5326
- }
5327
- function $setTableDensity(table, density) {
5328
- $setTableSettings(table, { density });
5329
- }
5330
- function $getSelectedTable() {
5331
- const selection = $getSelection2();
5332
- if ($isTableSelection(selection)) {
5333
- const node = $getNodeByKey3(selection.tableKey);
5334
- return $isTableNode(node) ? node : null;
5335
- }
5336
- if (!$isRangeSelection2(selection)) return null;
5337
- const table = $findMatchingParent(
5338
- selection.anchor.getNode(),
5339
- (node) => $isTableNode(node)
5340
- );
5341
- return $isTableNode(table) ? table : null;
5342
- }
5343
- var MARKER_REG_EXP = /^<!--\s*([a-z]+\s*:\s*[a-z]+(?:\s*;\s*[a-z]+\s*:\s*[a-z]+)*)\s*;?\s*-->\s*$/;
5344
- function isOption(setting, value) {
5345
- return value in OPTION_DECLARATIONS[setting];
5346
- }
5347
- var TABLE_WIDTH_MARKER = "<!-- width: content -->";
5348
- function parseTableSettingsMarker(text) {
5349
- const match = MARKER_REG_EXP.exec(text);
5350
- if (!match) return null;
5351
- const settings = {};
5352
- let recognised = false;
5353
- for (const pair of match[1].split(";")) {
5354
- const [key, value] = pair.split(":").map((s) => s.trim());
5355
- if (key !== "width" && key !== "density") continue;
5356
- recognised = true;
5357
- if (key === "width" && isOption("width", value)) settings.width = value;
5358
- if (key === "density" && isOption("density", value)) settings.density = value;
5359
- }
5360
- return recognised ? settings : null;
5361
- }
5362
- function formatTableSettingsMarker(settings, options = {}) {
5363
- const pairs = SETTING_KEYS.filter(
5364
- (key) => settings[key] !== DEFAULT_TABLE_SETTINGS[key] || key === "width" && options.explicitWidth
5365
- ).map((key) => `${key}: ${settings[key]}`);
5366
- return pairs.length > 0 ? `<!-- ${pairs.join("; ")} -->` : null;
5367
- }
5368
-
5369
- // src/transformers/tableTransformer.ts
5370
5924
  var TABLE_ROW_REG_EXP = /^\|(.+)\|\s?$/;
5371
5925
  var TABLE_ROW_DIVIDER_REG_EXP = /^(\| ?:?-*:? ?)+\|\s?$/;
5372
5926
  function $getMarkerSettings(node) {
@@ -5376,11 +5930,11 @@ function $getMarkerSettings(node) {
5376
5930
  }
5377
5931
  function getTableColumnsSize(table) {
5378
5932
  const row = table.getFirstChild();
5379
- return $isTableRowNode(row) ? row.getChildrenSize() : 0;
5933
+ return $isTableRowNode3(row) ? row.getChildrenSize() : 0;
5380
5934
  }
5381
5935
  function createTableCell(textContent) {
5382
5936
  const unescaped = textContent.replace(/\\n/g, "\n");
5383
- const cell = $createTableCellNode(TableCellHeaderStates.NO_STATUS);
5937
+ const cell = $createTableCellNode2(TableCellHeaderStates2.NO_STATUS);
5384
5938
  $convertFromMarkdownString2(unescaped, TRANSFORMERS, cell);
5385
5939
  return cell;
5386
5940
  }
@@ -5392,22 +5946,22 @@ function mapToTableCells(textContent) {
5392
5946
  var TABLE = {
5393
5947
  dependencies: [TableNode, TableRowNode, TableCellNode],
5394
5948
  export: (node) => {
5395
- if (!$isTableNode2(node)) return null;
5949
+ if (!$isTableNode3(node)) return null;
5396
5950
  const output = [];
5397
5951
  const marker = formatTableSettingsMarker($getTableSettings(node), {
5398
5952
  explicitWidth: $isTableWidthExplicit(node)
5399
5953
  });
5400
5954
  if (marker) output.push(marker);
5401
5955
  for (const row of node.getChildren()) {
5402
- if (!$isTableRowNode(row)) continue;
5956
+ if (!$isTableRowNode3(row)) continue;
5403
5957
  const rowOutput = [];
5404
5958
  let isHeaderRow = false;
5405
5959
  for (const cell of row.getChildren()) {
5406
- if (!$isTableCellNode(cell)) continue;
5960
+ if (!$isTableCellNode2(cell)) continue;
5407
5961
  rowOutput.push(
5408
5962
  $convertToMarkdownString2(TRANSFORMERS, cell).replace(/\n/g, "\\n")
5409
5963
  );
5410
- if (cell.__headerState === TableCellHeaderStates.ROW) {
5964
+ if (cell.__headerState === TableCellHeaderStates2.ROW) {
5411
5965
  isHeaderRow = true;
5412
5966
  }
5413
5967
  }
@@ -5422,12 +5976,12 @@ var TABLE = {
5422
5976
  replace: (parentNode, _children, match) => {
5423
5977
  if (TABLE_ROW_DIVIDER_REG_EXP.test(match[0])) {
5424
5978
  const table2 = parentNode.getPreviousSibling();
5425
- if (!table2 || !$isTableNode2(table2)) return;
5979
+ if (!table2 || !$isTableNode3(table2)) return;
5426
5980
  const lastRow = table2.getLastChild();
5427
- if (!lastRow || !$isTableRowNode(lastRow)) return;
5981
+ if (!lastRow || !$isTableRowNode3(lastRow)) return;
5428
5982
  lastRow.getChildren().forEach((cell) => {
5429
- if ($isTableCellNode(cell)) {
5430
- cell.setHeaderStyles(TableCellHeaderStates.ROW, TableCellHeaderStates.ROW);
5983
+ if ($isTableCellNode2(cell)) {
5984
+ cell.setHeaderStyles(TableCellHeaderStates2.ROW, TableCellHeaderStates2.ROW);
5431
5985
  }
5432
5986
  });
5433
5987
  parentNode.remove();
@@ -5452,14 +6006,14 @@ var TABLE = {
5452
6006
  }
5453
6007
  const table = $createTableNode();
5454
6008
  for (const cells of rows) {
5455
- const tableRow = $createTableRowNode();
6009
+ const tableRow = $createTableRowNode2();
5456
6010
  table.append(tableRow);
5457
6011
  for (let i = 0; i < maxCells; i++) {
5458
6012
  tableRow.append(i < cells.length ? cells[i] : createTableCell(""));
5459
6013
  }
5460
6014
  }
5461
6015
  const previousSibling = parentNode.getPreviousSibling();
5462
- if ($isTableNode2(previousSibling) && getTableColumnsSize(previousSibling) === maxCells) {
6016
+ if ($isTableNode3(previousSibling) && getTableColumnsSize(previousSibling) === maxCells) {
5463
6017
  previousSibling.append(...table.getChildren());
5464
6018
  parentNode.remove();
5465
6019
  } else {
@@ -5538,21 +6092,8 @@ var editorTheme = {
5538
6092
  drawing: "zui-drawing"
5539
6093
  };
5540
6094
 
5541
- // src/editorContext.ts
5542
- import { createContext, useContext } from "react";
5543
- var EditorContext = createContext(null);
5544
- function useEditorContext() {
5545
- const ctx = useContext(EditorContext);
5546
- if (!ctx) {
5547
- throw new Error(
5548
- "@zuilib/text-editor: this component must be rendered inside <MarkdownEditor> or <MarkdownEditor.Root>"
5549
- );
5550
- }
5551
- return ctx;
5552
- }
5553
-
5554
6095
  // src/EditorRoot.tsx
5555
- import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs9 } from "react/jsx-runtime";
6096
+ import { Fragment as Fragment4, jsx as jsx12, jsxs as jsxs10 } from "react/jsx-runtime";
5556
6097
  var SYNC_TRANSFORMERS = [
5557
6098
  FRONTMATTER,
5558
6099
  DRAWING,
@@ -5583,8 +6124,8 @@ var editorNodes = [
5583
6124
  DrawingNode
5584
6125
  ];
5585
6126
  function ReadOnlyPlugin({ readOnly }) {
5586
- const [editor] = useLexicalComposerContext6();
5587
- useEffect8(() => {
6127
+ const [editor] = useLexicalComposerContext7();
6128
+ useEffect9(() => {
5588
6129
  editor.setEditable(!readOnly);
5589
6130
  }, [editor, readOnly]);
5590
6131
  return null;
@@ -5596,14 +6137,15 @@ function EditorRoot({
5596
6137
  className,
5597
6138
  mode = "edit-md",
5598
6139
  autoFocus = false,
5599
- measure,
6140
+ measure: measure2,
5600
6141
  defaultBlockWidth = NO_DEFAULT_BLOCK_WIDTH,
6142
+ drawingStyle = "clean",
5601
6143
  children
5602
6144
  }) {
5603
6145
  const latestValueRef = useRef5(value ?? "");
5604
6146
  const [mountKey, setMountKey] = useState4(0);
5605
6147
  const [capturedMarkdown, setCapturedMarkdown] = useState4(value ?? "");
5606
- useEffect8(() => {
6148
+ useEffect9(() => {
5607
6149
  if (value !== void 0) {
5608
6150
  latestValueRef.current = value;
5609
6151
  }
@@ -5616,7 +6158,7 @@ function EditorRoot({
5616
6158
  [onChange]
5617
6159
  );
5618
6160
  const prevModeRef = useRef5(mode);
5619
- useEffect8(() => {
6161
+ useEffect9(() => {
5620
6162
  if (prevModeRef.current === "edit-raw" && mode !== "edit-raw") {
5621
6163
  setCapturedMarkdown(latestValueRef.current);
5622
6164
  setMountKey((k) => k + 1);
@@ -5639,19 +6181,20 @@ function EditorRoot({
5639
6181
  autoFocus,
5640
6182
  rawValue: value ?? "",
5641
6183
  onRawChange: handleChange,
5642
- defaultBlockWidth
6184
+ defaultBlockWidth,
6185
+ drawingStyle
5643
6186
  }),
5644
- [mode, readOnly, autoFocus, value, handleChange, defaultBlockWidth]
6187
+ [mode, readOnly, autoFocus, value, handleChange, defaultBlockWidth, drawingStyle]
5645
6188
  );
5646
6189
  const isRaw = mode === "edit-raw";
5647
6190
  const rootStyle = useMemo2(
5648
- () => measure !== void 0 ? { "--zui-text-editor-measure": measure } : void 0,
5649
- [measure]
6191
+ () => measure2 !== void 0 ? { "--zui-text-editor-measure": measure2 } : void 0,
6192
+ [measure2]
5650
6193
  );
5651
- return /* @__PURE__ */ jsx11(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsx11(EditorContext.Provider, { value: context, children: /* @__PURE__ */ jsxs9("div", { className: `zui-text-editor ${className ?? ""}`, style: rootStyle, children: [
6194
+ return /* @__PURE__ */ jsx12(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsx12(EditorContext.Provider, { value: context, children: /* @__PURE__ */ jsxs10("div", { className: `zui-text-editor ${className ?? ""}`, style: rootStyle, children: [
5652
6195
  children,
5653
- !isRaw && /* @__PURE__ */ jsxs9(Fragment3, { children: [
5654
- /* @__PURE__ */ jsx11(
6196
+ !isRaw && /* @__PURE__ */ jsxs10(Fragment4, { children: [
6197
+ /* @__PURE__ */ jsx12(
5655
6198
  MarkdownSyncPlugin,
5656
6199
  {
5657
6200
  initialMarkdown: mode === "view" ? value ?? "" : capturedMarkdown,
@@ -5659,17 +6202,18 @@ function EditorRoot({
5659
6202
  transformers: SYNC_TRANSFORMERS
5660
6203
  }
5661
6204
  ),
5662
- /* @__PURE__ */ jsx11(HistoryPlugin, {}),
5663
- /* @__PURE__ */ jsx11(ListPlugin, {}),
5664
- /* @__PURE__ */ jsx11(CheckListPlugin, {}),
5665
- /* @__PURE__ */ jsx11(ChecklistShortcutPlugin, {}),
5666
- /* @__PURE__ */ jsx11(CodeBlockShortcutPlugin, {}),
5667
- /* @__PURE__ */ jsx11(CodeHighlightPlugin, {}),
5668
- /* @__PURE__ */ jsx11(TablePlugin, {}),
5669
- /* @__PURE__ */ jsx11(LinkPlugin, {}),
5670
- /* @__PURE__ */ jsx11(MarkdownShortcutPlugin, { transformers: SHORTCUT_TRANSFORMERS }),
5671
- /* @__PURE__ */ jsx11(ReadOnlyPlugin, { readOnly: readOnly || mode === "view" }),
5672
- autoFocus && /* @__PURE__ */ jsx11(AutoFocusPlugin, {})
6205
+ /* @__PURE__ */ jsx12(HistoryPlugin, {}),
6206
+ /* @__PURE__ */ jsx12(ListPlugin, {}),
6207
+ /* @__PURE__ */ jsx12(CheckListPlugin, {}),
6208
+ /* @__PURE__ */ jsx12(ChecklistShortcutPlugin, {}),
6209
+ /* @__PURE__ */ jsx12(CodeBlockShortcutPlugin, {}),
6210
+ /* @__PURE__ */ jsx12(CodeHighlightPlugin, {}),
6211
+ /* @__PURE__ */ jsx12(TablePlugin, {}),
6212
+ /* @__PURE__ */ jsx12(TableRowShortcutsPlugin, {}),
6213
+ /* @__PURE__ */ jsx12(LinkPlugin, {}),
6214
+ /* @__PURE__ */ jsx12(MarkdownShortcutPlugin, { transformers: SHORTCUT_TRANSFORMERS }),
6215
+ /* @__PURE__ */ jsx12(ReadOnlyPlugin, { readOnly: readOnly || mode === "view" }),
6216
+ autoFocus && /* @__PURE__ */ jsx12(AutoFocusPlugin, {})
5673
6217
  ] })
5674
6218
  ] }) }) }, mountKey);
5675
6219
  }
@@ -5682,14 +6226,14 @@ import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
5682
6226
  // src/plugins/FoldingPlugin.tsx
5683
6227
  import {
5684
6228
  useCallback as useCallback3,
5685
- useEffect as useEffect9,
6229
+ useEffect as useEffect10,
5686
6230
  useRef as useRef6,
5687
6231
  useState as useState5
5688
6232
  } from "react";
5689
- import { $getRoot, $getSelection as $getSelection3, $isRangeSelection as $isRangeSelection3 } from "lexical";
5690
- import { useLexicalComposerContext as useLexicalComposerContext7 } from "@lexical/react/LexicalComposerContext";
6233
+ import { $getRoot, $getSelection as $getSelection5, $isRangeSelection as $isRangeSelection5 } from "lexical";
6234
+ import { useLexicalComposerContext as useLexicalComposerContext8 } from "@lexical/react/LexicalComposerContext";
5691
6235
  import { $isHeadingNode } from "@lexical/rich-text";
5692
- import { jsx as jsx12 } from "react/jsx-runtime";
6236
+ import { jsx as jsx13 } from "react/jsx-runtime";
5693
6237
  var HEADING_LEVELS = {
5694
6238
  h1: 1,
5695
6239
  h2: 2,
@@ -5699,7 +6243,7 @@ var HEADING_LEVELS = {
5699
6243
  h6: 6
5700
6244
  };
5701
6245
  function FoldingPlugin() {
5702
- const [editor] = useLexicalComposerContext7();
6246
+ const [editor] = useLexicalComposerContext8();
5703
6247
  const [foldedKeys, setFoldedKeys] = useState5(/* @__PURE__ */ new Set());
5704
6248
  const [buttons, setButtons] = useState5([]);
5705
6249
  const foldedRef = useRef6(foldedKeys);
@@ -5725,8 +6269,8 @@ function FoldingPlugin() {
5725
6269
  hidden.add(sibling.getKey());
5726
6270
  }
5727
6271
  }
5728
- const selection = $getSelection3();
5729
- if ($isRangeSelection3(selection)) {
6272
+ const selection = $getSelection5();
6273
+ if ($isRangeSelection5(selection)) {
5730
6274
  const topLevel = selection.anchor.getNode().getTopLevelElement();
5731
6275
  if (topLevel && hidden.has(topLevel.getKey())) {
5732
6276
  let node = topLevel.getPreviousSibling();
@@ -5768,7 +6312,7 @@ function FoldingPlugin() {
5768
6312
  );
5769
6313
  });
5770
6314
  }, [editor]);
5771
- useEffect9(() => {
6315
+ useEffect10(() => {
5772
6316
  sync();
5773
6317
  const unregister = editor.registerUpdateListener(sync);
5774
6318
  const rootElement = editor.getRootElement();
@@ -5787,7 +6331,7 @@ function FoldingPlugin() {
5787
6331
  return next;
5788
6332
  });
5789
6333
  }, []);
5790
- return /* @__PURE__ */ jsx12("div", { className: "zui-text-editor-fold-gutter", children: buttons.map(({ key, folded, top, height }) => /* @__PURE__ */ jsx12(
6334
+ return /* @__PURE__ */ jsx13("div", { className: "zui-text-editor-fold-gutter", children: buttons.map(({ key, folded, top, height }) => /* @__PURE__ */ jsx13(
5791
6335
  "button",
5792
6336
  {
5793
6337
  type: "button",
@@ -5797,7 +6341,7 @@ function FoldingPlugin() {
5797
6341
  "aria-label": folded ? "Expand section" : "Collapse section",
5798
6342
  "aria-expanded": !folded,
5799
6343
  onClick: () => toggle(key),
5800
- children: /* @__PURE__ */ jsx12(
6344
+ children: /* @__PURE__ */ jsx13(
5801
6345
  "svg",
5802
6346
  {
5803
6347
  viewBox: "0 0 20 20",
@@ -5808,7 +6352,7 @@ function FoldingPlugin() {
5808
6352
  strokeWidth: "2",
5809
6353
  strokeLinecap: "round",
5810
6354
  strokeLinejoin: "round",
5811
- children: /* @__PURE__ */ jsx12("path", { d: "M6 8l4 4 4-4" })
6355
+ children: /* @__PURE__ */ jsx13("path", { d: "M6 8l4 4 4-4" })
5812
6356
  }
5813
6357
  )
5814
6358
  },
@@ -5816,17 +6360,150 @@ function FoldingPlugin() {
5816
6360
  )) });
5817
6361
  }
5818
6362
 
5819
- // src/plugins/TableSettingsPlugin.tsx
5820
- import { useCallback as useCallback5, useEffect as useEffect11, useState as useState7 } from "react";
5821
- import { useLexicalComposerContext as useLexicalComposerContext9 } from "@lexical/react/LexicalComposerContext";
6363
+ // src/plugins/TableControlsPlugin.tsx
6364
+ import { useCallback as useCallback7 } from "react";
6365
+ import { useLexicalComposerContext as useLexicalComposerContext11 } from "@lexical/react/LexicalComposerContext";
5822
6366
  import { useLexicalEditable as useLexicalEditable2 } from "@lexical/react/useLexicalEditable";
5823
6367
 
6368
+ // src/components/TableRowRail.tsx
6369
+ import { useCallback as useCallback4, useRef as useRef7, useState as useState6 } from "react";
6370
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
6371
+ var TABLE_RAIL_WIDTH = 28;
6372
+ function TableRowRail({ box, rows, position, onInsert }) {
6373
+ const rail = useRef7(null);
6374
+ const [hovered, setHovered] = useState6(null);
6375
+ const boundaryTop = useCallback4(
6376
+ (index) => {
6377
+ if (index < rows.length) return rows[index].top;
6378
+ const last = rows[rows.length - 1];
6379
+ return last ? last.top + last.height : 0;
6380
+ },
6381
+ [rows]
6382
+ );
6383
+ const onPointerMove = useCallback4(
6384
+ (event) => {
6385
+ const element = rail.current;
6386
+ if (!element) return;
6387
+ const y = event.clientY - element.getBoundingClientRect().top;
6388
+ let nearest = null;
6389
+ let distance = Number.POSITIVE_INFINITY;
6390
+ for (const index of insertableRowIndices(position)) {
6391
+ const d = Math.abs(boundaryTop(index) - y);
6392
+ if (d < distance) {
6393
+ distance = d;
6394
+ nearest = index;
6395
+ }
6396
+ }
6397
+ setHovered(nearest);
6398
+ },
6399
+ [position, boundaryTop]
6400
+ );
6401
+ if (rows.length === 0) return null;
6402
+ const current = rows[Math.min(position.index, rows.length - 1)];
6403
+ const insertAt = hovered ?? position.count;
6404
+ const insertTop = boundaryTop(insertAt);
6405
+ return /* @__PURE__ */ jsxs11(
6406
+ "div",
6407
+ {
6408
+ ref: rail,
6409
+ className: "zui-table-rail",
6410
+ style: { top: box.top, left: box.left - TABLE_RAIL_WIDTH, width: TABLE_RAIL_WIDTH, height: box.height },
6411
+ onPointerMove,
6412
+ onPointerLeave: () => setHovered(null),
6413
+ children: [
6414
+ /* @__PURE__ */ jsx14(
6415
+ "div",
6416
+ {
6417
+ className: "zui-table-rail-marker",
6418
+ style: { top: current.top + 3, height: Math.max(4, current.height - 6) },
6419
+ "aria-hidden": true
6420
+ }
6421
+ ),
6422
+ /* @__PURE__ */ jsx14(
6423
+ "button",
6424
+ {
6425
+ type: "button",
6426
+ className: `zui-table-rail-add ${hovered === null ? "is-resting" : ""}`,
6427
+ style: { top: insertTop },
6428
+ title: insertAt === position.count ? "Add row" : `Insert row ${insertAt === 0 ? "at the top" : `after row ${insertAt}`}`,
6429
+ "aria-label": insertAt === position.count ? "Add row" : `Insert row before row ${insertAt + 1}`,
6430
+ onMouseDown: (e) => e.preventDefault(),
6431
+ onClick: () => onInsert(insertAt),
6432
+ children: /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", children: /* @__PURE__ */ jsx14("path", { d: "M6 2.5v7M2.5 6h7" }) })
6433
+ }
6434
+ ),
6435
+ /* @__PURE__ */ jsx14(
6436
+ "div",
6437
+ {
6438
+ className: "zui-table-rail-line",
6439
+ style: { top: insertTop, left: TABLE_RAIL_WIDTH, width: box.width },
6440
+ "aria-hidden": true
6441
+ }
6442
+ )
6443
+ ]
6444
+ }
6445
+ );
6446
+ }
6447
+
6448
+ // src/components/shortcutLabel.ts
6449
+ var isApple = typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/.test(navigator.platform ?? "");
6450
+ function shortcutLabel(keys) {
6451
+ const parts = keys.split("+");
6452
+ if (isApple) {
6453
+ const glyphs = {
6454
+ Mod: "\u2318",
6455
+ Shift: "\u21E7",
6456
+ Alt: "\u2325",
6457
+ Enter: "\u21A9",
6458
+ Backspace: "\u232B",
6459
+ Tab: "\u21E5"
6460
+ };
6461
+ return parts.map((part) => glyphs[part] ?? part).join("");
6462
+ }
6463
+ return parts.map((part) => part === "Mod" ? "Ctrl" : part).join("+");
6464
+ }
6465
+
6466
+ // src/components/tableRowActions.tsx
6467
+ import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
6468
+ var TABLE_ROW_ACTIONS = [
6469
+ {
6470
+ action: "insert-above",
6471
+ label: "Insert row above",
6472
+ shortcut: "Mod+Shift+Enter",
6473
+ icon: /* @__PURE__ */ jsxs12(Fragment5, { children: [
6474
+ /* @__PURE__ */ jsx15("path", { d: "M3 11.5h14M3 15.5h14" }),
6475
+ /* @__PURE__ */ jsx15("path", { d: "M10 3.5v5M7.5 6h5" })
6476
+ ] })
6477
+ },
6478
+ {
6479
+ action: "insert-below",
6480
+ label: "Insert row below",
6481
+ shortcut: "Mod+Enter",
6482
+ icon: /* @__PURE__ */ jsxs12(Fragment5, { children: [
6483
+ /* @__PURE__ */ jsx15("path", { d: "M3 4.5h14M3 8.5h14" }),
6484
+ /* @__PURE__ */ jsx15("path", { d: "M10 11.5v5M7.5 14h5" })
6485
+ ] })
6486
+ },
6487
+ {
6488
+ action: "delete",
6489
+ label: "Delete row",
6490
+ shortcut: "Mod+Shift+Backspace",
6491
+ icon: /* @__PURE__ */ jsxs12(Fragment5, { children: [
6492
+ /* @__PURE__ */ jsx15("path", { d: "M3 5.5h14M3 14.5h14" }),
6493
+ /* @__PURE__ */ jsx15("path", { d: "M7.5 10h5" })
6494
+ ] })
6495
+ }
6496
+ ];
6497
+ function tableRowActionTitle(action) {
6498
+ return `${action.label} (${shortcutLabel(action.shortcut)})`;
6499
+ }
6500
+
5824
6501
  // src/useMarkdownEditor.ts
5825
- import { useCallback as useCallback4, useEffect as useEffect10, useRef as useRef7, useState as useState6 } from "react";
6502
+ import { useCallback as useCallback5, useEffect as useEffect11, useRef as useRef8, useState as useState7 } from "react";
5826
6503
  import {
5827
- $getNodeByKey as $getNodeByKey4,
5828
- $getSelection as $getSelection4,
5829
- $isRangeSelection as $isRangeSelection4,
6504
+ $getNodeByKey as $getNodeByKey5,
6505
+ $getSelection as $getSelection6,
6506
+ $isRangeSelection as $isRangeSelection6,
5830
6507
  CAN_REDO_COMMAND,
5831
6508
  CAN_UNDO_COMMAND,
5832
6509
  COMMAND_PRIORITY_LOW as COMMAND_PRIORITY_LOW2,
@@ -5834,7 +6511,7 @@ import {
5834
6511
  REDO_COMMAND,
5835
6512
  UNDO_COMMAND
5836
6513
  } from "lexical";
5837
- import { useLexicalComposerContext as useLexicalComposerContext8 } from "@lexical/react/LexicalComposerContext";
6514
+ import { useLexicalComposerContext as useLexicalComposerContext9 } from "@lexical/react/LexicalComposerContext";
5838
6515
  import { INSERT_TABLE_COMMAND } from "@lexical/table";
5839
6516
  import { $insertNodeToNearestRoot, mergeRegister as mergeRegister2 } from "@lexical/utils";
5840
6517
  var TRACKED_FORMATS = [
@@ -5846,29 +6523,31 @@ var TRACKED_FORMATS = [
5846
6523
  ];
5847
6524
  function $readDrawingWidth(key) {
5848
6525
  if (key === null) return null;
5849
- const node = $getNodeByKey4(key);
6526
+ const node = $getNodeByKey5(key);
5850
6527
  return $isDrawingNode(node) ? node.getData().width ?? "full" : null;
5851
6528
  }
5852
6529
  function useMarkdownEditor() {
5853
- const [editor] = useLexicalComposerContext8();
6530
+ const [editor] = useLexicalComposerContext9();
5854
6531
  const { defaultBlockWidth } = useEditorContext();
5855
- const [activeFormats, setActiveFormats] = useState6(
6532
+ const [activeFormats, setActiveFormats] = useState7(
5856
6533
  /* @__PURE__ */ new Set()
5857
6534
  );
5858
- const [canUndo, setCanUndo] = useState6(false);
5859
- const [canRedo, setCanRedo] = useState6(false);
5860
- const [tableSettings, setTableSettingsState] = useState6(null);
5861
- const activeDrawingRef = useRef7(null);
5862
- const [drawingWidth, setDrawingWidth] = useState6(null);
5863
- useEffect10(
6535
+ const [canUndo, setCanUndo] = useState7(false);
6536
+ const [canRedo, setCanRedo] = useState7(false);
6537
+ const [tableSettings, setTableSettingsState] = useState7(null);
6538
+ const [tableRow, setTableRow] = useState7(null);
6539
+ const activeDrawingRef = useRef8(null);
6540
+ const [drawingWidth, setDrawingWidth] = useState7(null);
6541
+ useEffect11(
5864
6542
  () => mergeRegister2(
5865
6543
  editor.registerUpdateListener(({ editorState }) => {
5866
6544
  editorState.read(() => {
5867
6545
  const table = $getSelectedTable();
5868
6546
  setTableSettingsState(table ? $getTableSettings(table) : null);
6547
+ setTableRow(table ? $getTableRowPosition() : null);
5869
6548
  setDrawingWidth($readDrawingWidth(activeDrawingRef.current));
5870
- const selection = $getSelection4();
5871
- if (!$isRangeSelection4(selection)) {
6549
+ const selection = $getSelection6();
6550
+ if (!$isRangeSelection6(selection)) {
5872
6551
  setActiveFormats(/* @__PURE__ */ new Set());
5873
6552
  return;
5874
6553
  }
@@ -5907,13 +6586,13 @@ function useMarkdownEditor() {
5907
6586
  ),
5908
6587
  [editor]
5909
6588
  );
5910
- const toggleFormat = useCallback4(
6589
+ const toggleFormat = useCallback5(
5911
6590
  (format) => {
5912
6591
  editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
5913
6592
  },
5914
6593
  [editor]
5915
6594
  );
5916
- const insertTable = useCallback4(
6595
+ const insertTable = useCallback5(
5917
6596
  ({
5918
6597
  rows = 3,
5919
6598
  columns = 3,
@@ -5935,7 +6614,7 @@ function useMarkdownEditor() {
5935
6614
  },
5936
6615
  [editor, defaultBlockWidth.table]
5937
6616
  );
5938
- const insertDrawing = useCallback4(
6617
+ const insertDrawing = useCallback5(
5939
6618
  ({ width = defaultBlockWidth.drawing } = {}) => {
5940
6619
  editor.update(() => {
5941
6620
  const data = width === void 0 ? EMPTY_DRAWING : { version: 2, canvasHeight: EMPTY_DRAWING.canvasHeight, width, shapes: [] };
@@ -5944,7 +6623,7 @@ function useMarkdownEditor() {
5944
6623
  },
5945
6624
  [editor, defaultBlockWidth.drawing]
5946
6625
  );
5947
- const updateTableSettings = useCallback4(
6626
+ const updateTableSettings = useCallback5(
5948
6627
  (settings) => {
5949
6628
  editor.update(() => {
5950
6629
  const table = $getSelectedTable();
@@ -5953,15 +6632,30 @@ function useMarkdownEditor() {
5953
6632
  },
5954
6633
  [editor]
5955
6634
  );
5956
- const setTableWidth = useCallback4(
6635
+ const setTableWidth = useCallback5(
5957
6636
  (width) => updateTableSettings({ width }),
5958
6637
  [updateTableSettings]
5959
6638
  );
5960
- const setTableDensity = useCallback4(
6639
+ const setTableDensity = useCallback5(
5961
6640
  (density) => updateTableSettings({ density }),
5962
6641
  [updateTableSettings]
5963
6642
  );
5964
- const setBlockWidth = useCallback4(
6643
+ const insertTableRow = useCallback5(
6644
+ (position = "below") => {
6645
+ editor.update(() => {
6646
+ const table = $getSelectedTable();
6647
+ if (table) $insertTableRowNear(table, position);
6648
+ });
6649
+ },
6650
+ [editor]
6651
+ );
6652
+ const deleteTableRow = useCallback5(() => {
6653
+ editor.update(() => {
6654
+ const table = $getSelectedTable();
6655
+ if (table) $deleteSelectedTableRow(table);
6656
+ });
6657
+ }, [editor]);
6658
+ const setBlockWidth = useCallback5(
5965
6659
  (width) => {
5966
6660
  const key = activeDrawingRef.current;
5967
6661
  if (key === null) {
@@ -5969,7 +6663,7 @@ function useMarkdownEditor() {
5969
6663
  return;
5970
6664
  }
5971
6665
  editor.update(() => {
5972
- const node = $getNodeByKey4(key);
6666
+ const node = $getNodeByKey5(key);
5973
6667
  if (!$isDrawingNode(node)) return;
5974
6668
  const { width: _previous, ...data } = node.getData();
5975
6669
  node.setData(width === "full" ? data : { ...data, width });
@@ -5977,10 +6671,10 @@ function useMarkdownEditor() {
5977
6671
  },
5978
6672
  [editor, updateTableSettings]
5979
6673
  );
5980
- const undo = useCallback4(() => {
6674
+ const undo = useCallback5(() => {
5981
6675
  editor.dispatchCommand(UNDO_COMMAND, void 0);
5982
6676
  }, [editor]);
5983
- const redo = useCallback4(() => {
6677
+ const redo = useCallback5(() => {
5984
6678
  editor.dispatchCommand(REDO_COMMAND, void 0);
5985
6679
  }, [editor]);
5986
6680
  return {
@@ -5995,6 +6689,9 @@ function useMarkdownEditor() {
5995
6689
  setTableWidth,
5996
6690
  tableDensity: tableSettings?.density ?? null,
5997
6691
  setTableDensity,
6692
+ tableRow,
6693
+ insertTableRow,
6694
+ deleteTableRow,
5998
6695
  canUndo,
5999
6696
  canRedo,
6000
6697
  undo,
@@ -6003,23 +6700,23 @@ function useMarkdownEditor() {
6003
6700
  }
6004
6701
 
6005
6702
  // src/components/Toolbar.tsx
6006
- import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
6703
+ import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
6007
6704
  function Toolbar({ children, className }) {
6008
- return /* @__PURE__ */ jsx13(
6705
+ return /* @__PURE__ */ jsx16(
6009
6706
  "div",
6010
6707
  {
6011
6708
  className: `zui-text-editor-toolbar ${className ?? ""}`,
6012
6709
  role: "toolbar",
6013
- children: children ?? /* @__PURE__ */ jsxs10(Fragment4, { children: [
6014
- /* @__PURE__ */ jsx13(FormatButtons, {}),
6015
- /* @__PURE__ */ jsx13(ToolbarDivider, {}),
6016
- /* @__PURE__ */ jsx13(InsertButtons, {})
6710
+ children: children ?? /* @__PURE__ */ jsxs13(Fragment6, { children: [
6711
+ /* @__PURE__ */ jsx16(FormatButtons, {}),
6712
+ /* @__PURE__ */ jsx16(ToolbarDivider, {}),
6713
+ /* @__PURE__ */ jsx16(InsertButtons, {})
6017
6714
  ] })
6018
6715
  }
6019
6716
  );
6020
6717
  }
6021
6718
  function ToolbarDivider() {
6022
- return /* @__PURE__ */ jsx13("div", { className: "zui-text-editor-toolbar-divider" });
6719
+ return /* @__PURE__ */ jsx16("div", { className: "zui-text-editor-toolbar-divider" });
6023
6720
  }
6024
6721
  function ToolbarButton({
6025
6722
  label,
@@ -6029,7 +6726,7 @@ function ToolbarButton({
6029
6726
  disabled = false,
6030
6727
  className
6031
6728
  }) {
6032
- return /* @__PURE__ */ jsx13(
6729
+ return /* @__PURE__ */ jsx16(
6033
6730
  "button",
6034
6731
  {
6035
6732
  type: "button",
@@ -6045,7 +6742,7 @@ function ToolbarButton({
6045
6742
  );
6046
6743
  }
6047
6744
  function Icon2({ children, strokeWidth = 1.5 }) {
6048
- return /* @__PURE__ */ jsx13(
6745
+ return /* @__PURE__ */ jsx16(
6049
6746
  "svg",
6050
6747
  {
6051
6748
  viewBox: "0 0 20 20",
@@ -6064,27 +6761,27 @@ var FORMAT_BUTTONS = [
6064
6761
  {
6065
6762
  format: "bold",
6066
6763
  label: "Bold",
6067
- icon: /* @__PURE__ */ jsx13(Icon2, { strokeWidth: 1.8, children: /* @__PURE__ */ jsx13("path", { d: "M6 3.5h5a3 3 0 0 1 0 6H6zm0 6h6a3 3 0 0 1 0 6H6z" }) })
6764
+ icon: /* @__PURE__ */ jsx16(Icon2, { strokeWidth: 1.8, children: /* @__PURE__ */ jsx16("path", { d: "M6 3.5h5a3 3 0 0 1 0 6H6zm0 6h6a3 3 0 0 1 0 6H6z" }) })
6068
6765
  },
6069
6766
  {
6070
6767
  format: "italic",
6071
6768
  label: "Italic",
6072
- icon: /* @__PURE__ */ jsx13(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx13("path", { d: "M8.5 3.5h6M5.5 16.5h6M11.5 3.5l-3 13" }) })
6769
+ icon: /* @__PURE__ */ jsx16(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx16("path", { d: "M8.5 3.5h6M5.5 16.5h6M11.5 3.5l-3 13" }) })
6073
6770
  },
6074
6771
  {
6075
6772
  format: "strikethrough",
6076
6773
  label: "Strikethrough",
6077
- icon: /* @__PURE__ */ jsx13(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx13("path", { d: "M4 10h12M13.5 5.5c-.6-1.2-2-2-3.5-2-2 0-3.5 1.2-3.5 2.8 0 .5.1.9.4 1.3m-.4 5c.5 1.6 2 2.9 3.9 2.9 2 0 3.6-1.2 3.6-2.9 0-.4-.1-.8-.2-1.1" }) })
6774
+ icon: /* @__PURE__ */ jsx16(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx16("path", { d: "M4 10h12M13.5 5.5c-.6-1.2-2-2-3.5-2-2 0-3.5 1.2-3.5 2.8 0 .5.1.9.4 1.3m-.4 5c.5 1.6 2 2.9 3.9 2.9 2 0 3.6-1.2 3.6-2.9 0-.4-.1-.8-.2-1.1" }) })
6078
6775
  },
6079
6776
  {
6080
6777
  format: "code",
6081
6778
  label: "Inline code",
6082
- icon: /* @__PURE__ */ jsx13(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx13("path", { d: "M7.5 6L4 10l3.5 4M12.5 6L16 10l-3.5 4" }) })
6779
+ icon: /* @__PURE__ */ jsx16(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx16("path", { d: "M7.5 6L4 10l3.5 4M12.5 6L16 10l-3.5 4" }) })
6083
6780
  }
6084
6781
  ];
6085
6782
  function FormatButtons() {
6086
6783
  const { activeFormats, toggleFormat } = useMarkdownEditor();
6087
- return /* @__PURE__ */ jsx13(Fragment4, { children: FORMAT_BUTTONS.map(({ format, label, icon }) => /* @__PURE__ */ jsx13(
6784
+ return /* @__PURE__ */ jsx16(Fragment6, { children: FORMAT_BUTTONS.map(({ format, label, icon }) => /* @__PURE__ */ jsx16(
6088
6785
  ToolbarButton,
6089
6786
  {
6090
6787
  label,
@@ -6097,36 +6794,36 @@ function FormatButtons() {
6097
6794
  }
6098
6795
  function InsertButtons() {
6099
6796
  const { insertTable, insertDrawing } = useMarkdownEditor();
6100
- return /* @__PURE__ */ jsxs10(Fragment4, { children: [
6101
- /* @__PURE__ */ jsx13(ToolbarButton, { label: "Insert table", onClick: () => insertTable(), children: /* @__PURE__ */ jsxs10(Icon2, { children: [
6102
- /* @__PURE__ */ jsx13("rect", { x: "3", y: "3.5", width: "14", height: "13", rx: "1.5" }),
6103
- /* @__PURE__ */ jsx13("path", { d: "M3 8h14M8 8v8.5M13 8v8.5" })
6797
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
6798
+ /* @__PURE__ */ jsx16(ToolbarButton, { label: "Insert table", onClick: () => insertTable(), children: /* @__PURE__ */ jsxs13(Icon2, { children: [
6799
+ /* @__PURE__ */ jsx16("rect", { x: "3", y: "3.5", width: "14", height: "13", rx: "1.5" }),
6800
+ /* @__PURE__ */ jsx16("path", { d: "M3 8h14M8 8v8.5M13 8v8.5" })
6104
6801
  ] }) }),
6105
- /* @__PURE__ */ jsx13(ToolbarButton, { label: "Insert drawing", onClick: insertDrawing, children: /* @__PURE__ */ jsxs10(Icon2, { children: [
6106
- /* @__PURE__ */ jsx13("rect", { x: "3", y: "5", width: "8", height: "6", rx: "1.5" }),
6107
- /* @__PURE__ */ jsx13("path", { d: "M13.5 8h3M14.5 6.5L17.5 8l-3 1.5" }),
6108
- /* @__PURE__ */ jsx13("ellipse", { cx: "13", cy: "14.5", rx: "4", ry: "2.8" })
6802
+ /* @__PURE__ */ jsx16(ToolbarButton, { label: "Insert drawing", onClick: insertDrawing, children: /* @__PURE__ */ jsxs13(Icon2, { children: [
6803
+ /* @__PURE__ */ jsx16("rect", { x: "3", y: "5", width: "8", height: "6", rx: "1.5" }),
6804
+ /* @__PURE__ */ jsx16("path", { d: "M13.5 8h3M14.5 6.5L17.5 8l-3 1.5" }),
6805
+ /* @__PURE__ */ jsx16("ellipse", { cx: "13", cy: "14.5", rx: "4", ry: "2.8" })
6109
6806
  ] }) })
6110
6807
  ] });
6111
6808
  }
6112
6809
  function HistoryButtons() {
6113
6810
  const { canUndo, canRedo, undo, redo } = useMarkdownEditor();
6114
- return /* @__PURE__ */ jsxs10(Fragment4, { children: [
6115
- /* @__PURE__ */ jsx13(ToolbarButton, { label: "Undo", onClick: undo, disabled: !canUndo, children: /* @__PURE__ */ jsxs10(Icon2, { children: [
6116
- /* @__PURE__ */ jsx13("path", { d: "M7 6L3.5 9.5 7 13" }),
6117
- /* @__PURE__ */ jsx13("path", { d: "M3.5 9.5H12a4 4 0 0 1 0 8h-1" })
6811
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
6812
+ /* @__PURE__ */ jsx16(ToolbarButton, { label: "Undo", onClick: undo, disabled: !canUndo, children: /* @__PURE__ */ jsxs13(Icon2, { children: [
6813
+ /* @__PURE__ */ jsx16("path", { d: "M7 6L3.5 9.5 7 13" }),
6814
+ /* @__PURE__ */ jsx16("path", { d: "M3.5 9.5H12a4 4 0 0 1 0 8h-1" })
6118
6815
  ] }) }),
6119
- /* @__PURE__ */ jsx13(ToolbarButton, { label: "Redo", onClick: redo, disabled: !canRedo, children: /* @__PURE__ */ jsxs10(Icon2, { children: [
6120
- /* @__PURE__ */ jsx13("path", { d: "M13 6l3.5 3.5L13 13" }),
6121
- /* @__PURE__ */ jsx13("path", { d: "M16.5 9.5H8a4 4 0 0 0 0 8h1" })
6816
+ /* @__PURE__ */ jsx16(ToolbarButton, { label: "Redo", onClick: redo, disabled: !canRedo, children: /* @__PURE__ */ jsxs13(Icon2, { children: [
6817
+ /* @__PURE__ */ jsx16("path", { d: "M13 6l3.5 3.5L13 13" }),
6818
+ /* @__PURE__ */ jsx16("path", { d: "M16.5 9.5H8a4 4 0 0 0 0 8h1" })
6122
6819
  ] }) })
6123
6820
  ] });
6124
6821
  }
6125
6822
 
6126
- // src/plugins/TableSettingsPlugin.tsx
6127
- import { jsx as jsx14 } from "react/jsx-runtime";
6823
+ // src/components/TableSettingsToolbar.tsx
6824
+ import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
6128
6825
  function Icon3({ children }) {
6129
- return /* @__PURE__ */ jsx14(
6826
+ return /* @__PURE__ */ jsx17(
6130
6827
  "svg",
6131
6828
  {
6132
6829
  viewBox: "0 0 20 20",
@@ -6141,32 +6838,79 @@ function Icon3({ children }) {
6141
6838
  }
6142
6839
  );
6143
6840
  }
6144
- function TableSettingsPlugin() {
6145
- const [editor] = useLexicalComposerContext9();
6146
- const isEditable = useLexicalEditable2();
6147
- const [anchor, setAnchor] = useState7(null);
6148
- const [settings, setSettings] = useState7(null);
6149
- const sync = useCallback5(() => {
6841
+ function TableSettingsToolbar({
6842
+ settings,
6843
+ position,
6844
+ style,
6845
+ onSettings,
6846
+ onRowAction
6847
+ }) {
6848
+ return /* @__PURE__ */ jsxs14("div", { className: "zui-table-settings", role: "toolbar", "aria-label": "Table", style, children: [
6849
+ LAYOUT_OPTIONS.map(({ preset, label, icon, width, density }) => /* @__PURE__ */ jsx17(
6850
+ ToolbarButton,
6851
+ {
6852
+ label,
6853
+ active: layoutPreset(settings.width) === preset,
6854
+ onClick: () => onSettings({ width, density }),
6855
+ children: /* @__PURE__ */ jsx17(Icon3, { children: icon })
6856
+ },
6857
+ preset
6858
+ )),
6859
+ /* @__PURE__ */ jsx17(ToolbarDivider, {}),
6860
+ TABLE_ROW_ACTIONS.map((rowAction) => /* @__PURE__ */ jsx17(
6861
+ ToolbarButton,
6862
+ {
6863
+ label: tableRowActionTitle(rowAction),
6864
+ disabled: rowAction.action === "delete" && !canDeleteRow(position) || rowAction.action === "insert-above" && position.hasHeader && position.index === 0,
6865
+ onClick: () => onRowAction(rowAction.action),
6866
+ children: /* @__PURE__ */ jsx17(Icon3, { children: rowAction.icon })
6867
+ },
6868
+ rowAction.action
6869
+ ))
6870
+ ] });
6871
+ }
6872
+
6873
+ // src/plugins/useSelectedTable.ts
6874
+ import { useCallback as useCallback6, useEffect as useEffect12, useState as useState8 } from "react";
6875
+ import { useLexicalComposerContext as useLexicalComposerContext10 } from "@lexical/react/LexicalComposerContext";
6876
+ function measure(element, main) {
6877
+ const rect = element.getBoundingClientRect();
6878
+ const mainRect = main.getBoundingClientRect();
6879
+ const rows = Array.from(element.querySelectorAll(":scope > tbody > tr, :scope > tr")).map(
6880
+ (row) => {
6881
+ const r = row.getBoundingClientRect();
6882
+ return { top: r.top - rect.top, height: r.height };
6883
+ }
6884
+ );
6885
+ return {
6886
+ box: {
6887
+ top: rect.top - mainRect.top,
6888
+ left: rect.left - mainRect.left,
6889
+ right: mainRect.right - rect.right,
6890
+ width: rect.width,
6891
+ height: rect.height
6892
+ },
6893
+ rows
6894
+ };
6895
+ }
6896
+ function useSelectedTable() {
6897
+ const [editor] = useLexicalComposerContext10();
6898
+ const [selected, setSelected] = useState8(null);
6899
+ const sync = useCallback6(() => {
6150
6900
  const table = editor.getEditorState().read(() => {
6151
6901
  const node = $getSelectedTable();
6152
- return node ? { key: node.getKey(), settings: $getTableSettings(node) } : null;
6902
+ const position = $getTableRowPosition();
6903
+ return node && position ? { key: node.getKey(), settings: $getTableSettings(node), position } : null;
6153
6904
  });
6154
6905
  const element = table ? editor.getElementByKey(table.key) : null;
6155
6906
  const main = editor.getRootElement()?.parentElement;
6156
6907
  if (!table || !element || !main) {
6157
- setAnchor(null);
6158
- setSettings(null);
6908
+ setSelected(null);
6159
6909
  return;
6160
6910
  }
6161
- const rect = element.getBoundingClientRect();
6162
- const mainRect = main.getBoundingClientRect();
6163
- setAnchor({
6164
- top: rect.top - mainRect.top,
6165
- right: mainRect.right - rect.right + 8
6166
- });
6167
- setSettings(table.settings);
6911
+ setSelected({ ...table, ...measure(element, main) });
6168
6912
  }, [editor]);
6169
- useEffect11(() => {
6913
+ useEffect12(() => {
6170
6914
  sync();
6171
6915
  const unregister = editor.registerUpdateListener(sync);
6172
6916
  const rootElement = editor.getRootElement();
@@ -6177,39 +6921,79 @@ function TableSettingsPlugin() {
6177
6921
  observer?.disconnect();
6178
6922
  };
6179
6923
  }, [editor, sync]);
6180
- const update = useCallback5(
6924
+ const key = selected?.key ?? null;
6925
+ useEffect12(() => {
6926
+ if (key === null || typeof ResizeObserver === "undefined") return;
6927
+ const element = editor.getElementByKey(key);
6928
+ if (!element) return;
6929
+ const observer = new ResizeObserver(sync);
6930
+ observer.observe(element);
6931
+ return () => observer.disconnect();
6932
+ }, [editor, key, sync]);
6933
+ return selected;
6934
+ }
6935
+
6936
+ // src/plugins/TableControlsPlugin.tsx
6937
+ import { Fragment as Fragment7, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
6938
+ function TableControlsPlugin() {
6939
+ const [editor] = useLexicalComposerContext11();
6940
+ const isEditable = useLexicalEditable2();
6941
+ const table = useSelectedTable();
6942
+ const updateSettings = useCallback7(
6181
6943
  (next) => {
6182
6944
  editor.update(() => {
6183
- const table = $getSelectedTable();
6184
- if (table) $setTableSettings(table, next);
6945
+ const node = $getSelectedTable();
6946
+ if (node) $setTableSettings(node, next);
6185
6947
  });
6186
6948
  },
6187
6949
  [editor]
6188
6950
  );
6189
- if (!isEditable || !anchor || !settings) return null;
6190
- return /* @__PURE__ */ jsx14(
6191
- "div",
6192
- {
6193
- className: "zui-table-settings",
6194
- role: "toolbar",
6195
- "aria-label": "Table settings",
6196
- style: { top: anchor.top, right: anchor.right },
6197
- children: LAYOUT_OPTIONS.map(({ preset, label, icon, width, density }) => /* @__PURE__ */ jsx14(
6198
- ToolbarButton,
6199
- {
6200
- label,
6201
- active: layoutPreset(settings.width) === preset,
6202
- onClick: () => update({ width, density }),
6203
- children: /* @__PURE__ */ jsx14(Icon3, { children: icon })
6204
- },
6205
- preset
6206
- ))
6207
- }
6951
+ const rowAction = useCallback7(
6952
+ (action) => {
6953
+ editor.update(() => {
6954
+ const node = $getSelectedTable();
6955
+ if (!node) return;
6956
+ if (action === "delete") $deleteSelectedTableRow(node);
6957
+ else $insertTableRowNear(node, action === "insert-above" ? "above" : "below");
6958
+ });
6959
+ },
6960
+ [editor]
6961
+ );
6962
+ const insertAt = useCallback7(
6963
+ (index) => {
6964
+ editor.update(() => {
6965
+ const node = $getSelectedTable();
6966
+ if (node) $insertTableRowAt(node, index);
6967
+ });
6968
+ },
6969
+ [editor]
6208
6970
  );
6971
+ if (!isEditable || !table) return null;
6972
+ return /* @__PURE__ */ jsxs15(Fragment7, { children: [
6973
+ /* @__PURE__ */ jsx18(
6974
+ TableSettingsToolbar,
6975
+ {
6976
+ settings: table.settings,
6977
+ position: table.position,
6978
+ style: { top: table.box.top, right: table.box.right + 8 },
6979
+ onSettings: updateSettings,
6980
+ onRowAction: rowAction
6981
+ }
6982
+ ),
6983
+ /* @__PURE__ */ jsx18(
6984
+ TableRowRail,
6985
+ {
6986
+ box: table.box,
6987
+ rows: table.rows,
6988
+ position: table.position,
6989
+ onInsert: insertAt
6990
+ }
6991
+ )
6992
+ ] });
6209
6993
  }
6210
6994
 
6211
6995
  // src/EditorContent.tsx
6212
- import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
6996
+ import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
6213
6997
  function EditorContent({
6214
6998
  placeholder = "Start writing...",
6215
6999
  foldable = true,
@@ -6217,7 +7001,7 @@ function EditorContent({
6217
7001
  }) {
6218
7002
  const { mode, readOnly, autoFocus, rawValue, onRawChange } = useEditorContext();
6219
7003
  if (mode === "edit-raw") {
6220
- return /* @__PURE__ */ jsx15(
7004
+ return /* @__PURE__ */ jsx19(
6221
7005
  "textarea",
6222
7006
  {
6223
7007
  className: "zui-text-editor-textarea",
@@ -6230,36 +7014,36 @@ function EditorContent({
6230
7014
  }
6231
7015
  );
6232
7016
  }
6233
- return /* @__PURE__ */ jsxs11("div", { className: "zui-text-editor-body", children: [
6234
- /* @__PURE__ */ jsxs11("div", { className: "zui-text-editor-main", children: [
6235
- /* @__PURE__ */ jsx15(
7017
+ return /* @__PURE__ */ jsxs16("div", { className: "zui-text-editor-body", children: [
7018
+ /* @__PURE__ */ jsxs16("div", { className: "zui-text-editor-main", children: [
7019
+ /* @__PURE__ */ jsx19(
6236
7020
  RichTextPlugin,
6237
7021
  {
6238
- contentEditable: /* @__PURE__ */ jsx15(
7022
+ contentEditable: /* @__PURE__ */ jsx19(
6239
7023
  ContentEditable,
6240
7024
  {
6241
7025
  className: "zui-text-editor-content",
6242
7026
  "aria-placeholder": placeholder,
6243
- placeholder: /* @__PURE__ */ jsx15("div", { className: "zui-text-editor-placeholder", children: placeholder })
7027
+ placeholder: /* @__PURE__ */ jsx19("div", { className: "zui-text-editor-placeholder", children: placeholder })
6244
7028
  }
6245
7029
  ),
6246
7030
  ErrorBoundary: LexicalErrorBoundary
6247
7031
  }
6248
7032
  ),
6249
- foldable && /* @__PURE__ */ jsx15(FoldingPlugin, {}),
6250
- /* @__PURE__ */ jsx15(TableSettingsPlugin, {})
7033
+ foldable && /* @__PURE__ */ jsx19(FoldingPlugin, {}),
7034
+ /* @__PURE__ */ jsx19(TableControlsPlugin, {})
6251
7035
  ] }),
6252
7036
  children
6253
7037
  ] });
6254
7038
  }
6255
7039
 
6256
7040
  // src/plugins/OutlinePlugin.tsx
6257
- import { useCallback as useCallback6, useEffect as useEffect12, useState as useState8 } from "react";
6258
- import { useLexicalComposerContext as useLexicalComposerContext10 } from "@lexical/react/LexicalComposerContext";
7041
+ import { useCallback as useCallback8, useEffect as useEffect13, useState as useState9 } from "react";
7042
+ import { useLexicalComposerContext as useLexicalComposerContext12 } from "@lexical/react/LexicalComposerContext";
6259
7043
  import {
6260
7044
  TableOfContentsPlugin
6261
7045
  } from "@lexical/react/LexicalTableOfContentsPlugin";
6262
- import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
7046
+ import { jsx as jsx20, jsxs as jsxs17 } from "react/jsx-runtime";
6263
7047
  var INDENT_PER_LEVEL = {
6264
7048
  h1: 0,
6265
7049
  h2: 1,
@@ -6269,10 +7053,10 @@ var INDENT_PER_LEVEL = {
6269
7053
  h6: 5
6270
7054
  };
6271
7055
  function OutlinePlugin() {
6272
- const [editor] = useLexicalComposerContext10();
6273
- const [collapsed, setCollapsed] = useState8(false);
6274
- const [activeKey, setActiveKey] = useState8(null);
6275
- useEffect12(() => {
7056
+ const [editor] = useLexicalComposerContext12();
7057
+ const [collapsed, setCollapsed] = useState9(false);
7058
+ const [activeKey, setActiveKey] = useState9(null);
7059
+ useEffect13(() => {
6276
7060
  const rootElement = editor.getRootElement();
6277
7061
  const scroller = rootElement?.closest(".zui-text-editor");
6278
7062
  if (!rootElement || !(scroller instanceof HTMLElement)) return;
@@ -6302,7 +7086,7 @@ function OutlinePlugin() {
6302
7086
  unregister();
6303
7087
  };
6304
7088
  }, [editor]);
6305
- const scrollTo = useCallback6(
7089
+ const scrollTo = useCallback8(
6306
7090
  (key) => {
6307
7091
  editor.getEditorState().read(() => {
6308
7092
  const element = editor.getElementByKey(key);
@@ -6311,16 +7095,16 @@ function OutlinePlugin() {
6311
7095
  },
6312
7096
  [editor]
6313
7097
  );
6314
- return /* @__PURE__ */ jsx16(TableOfContentsPlugin, { children: (entries) => {
7098
+ return /* @__PURE__ */ jsx20(TableOfContentsPlugin, { children: (entries) => {
6315
7099
  for (const [key] of entries) {
6316
7100
  editor.getElementByKey(key)?.setAttribute("data-outline-key", key);
6317
7101
  }
6318
- return /* @__PURE__ */ jsxs12(
7102
+ return /* @__PURE__ */ jsxs17(
6319
7103
  "div",
6320
7104
  {
6321
7105
  className: `zui-text-editor-outline ${collapsed ? "is-collapsed" : ""}`,
6322
7106
  children: [
6323
- /* @__PURE__ */ jsx16(
7107
+ /* @__PURE__ */ jsx20(
6324
7108
  "button",
6325
7109
  {
6326
7110
  type: "button",
@@ -6329,7 +7113,7 @@ function OutlinePlugin() {
6329
7113
  "aria-label": collapsed ? "Show outline" : "Hide outline",
6330
7114
  "aria-expanded": !collapsed,
6331
7115
  onClick: () => setCollapsed((c2) => !c2),
6332
- children: /* @__PURE__ */ jsx16(
7116
+ children: /* @__PURE__ */ jsx20(
6333
7117
  "svg",
6334
7118
  {
6335
7119
  viewBox: "0 0 20 20",
@@ -6339,14 +7123,14 @@ function OutlinePlugin() {
6339
7123
  stroke: "currentColor",
6340
7124
  strokeWidth: "1.8",
6341
7125
  strokeLinecap: "round",
6342
- children: /* @__PURE__ */ jsx16("path", { d: "M4 5h12M4 10h8M4 15h10" })
7126
+ children: /* @__PURE__ */ jsx20("path", { d: "M4 5h12M4 10h8M4 15h10" })
6343
7127
  }
6344
7128
  )
6345
7129
  }
6346
7130
  ),
6347
- !collapsed && /* @__PURE__ */ jsxs12("nav", { className: "zui-text-editor-outline-list", "aria-label": "Table of contents", children: [
6348
- entries.length === 0 && /* @__PURE__ */ jsx16("div", { className: "zui-text-editor-outline-empty", children: "No headings" }),
6349
- entries.map(([key, text, tag]) => /* @__PURE__ */ jsx16(
7131
+ !collapsed && /* @__PURE__ */ jsxs17("nav", { className: "zui-text-editor-outline-list", "aria-label": "Table of contents", children: [
7132
+ entries.length === 0 && /* @__PURE__ */ jsx20("div", { className: "zui-text-editor-outline-empty", children: "No headings" }),
7133
+ entries.map(([key, text, tag]) => /* @__PURE__ */ jsx20(
6350
7134
  "button",
6351
7135
  {
6352
7136
  type: "button",
@@ -6367,11 +7151,11 @@ function OutlinePlugin() {
6367
7151
  }
6368
7152
 
6369
7153
  // src/MarkdownEditor.tsx
6370
- import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
7154
+ import { jsx as jsx21, jsxs as jsxs18 } from "react/jsx-runtime";
6371
7155
  var DEFAULT_ITEMS = {
6372
- format: /* @__PURE__ */ jsx17(FormatButtons, {}),
6373
- insert: /* @__PURE__ */ jsx17(InsertButtons, {}),
6374
- history: /* @__PURE__ */ jsx17(HistoryButtons, {})
7156
+ format: /* @__PURE__ */ jsx21(FormatButtons, {}),
7157
+ insert: /* @__PURE__ */ jsx21(InsertButtons, {}),
7158
+ history: /* @__PURE__ */ jsx21(HistoryButtons, {})
6375
7159
  };
6376
7160
  function EditorToolbar({
6377
7161
  children,
@@ -6379,7 +7163,7 @@ function EditorToolbar({
6379
7163
  }) {
6380
7164
  const { mode, readOnly } = useEditorContext();
6381
7165
  if (mode !== "edit-md" || readOnly) return null;
6382
- return /* @__PURE__ */ jsx17(Toolbar, { className, children });
7166
+ return /* @__PURE__ */ jsx21(Toolbar, { className, children });
6383
7167
  }
6384
7168
  function MarkdownEditor({
6385
7169
  placeholder,
@@ -6388,10 +7172,10 @@ function MarkdownEditor({
6388
7172
  foldable = true,
6389
7173
  ...rootProps
6390
7174
  }) {
6391
- return /* @__PURE__ */ jsxs13(EditorRoot, { ...rootProps, children: [
6392
- toolbar === true && /* @__PURE__ */ jsx17(EditorToolbar, {}),
7175
+ return /* @__PURE__ */ jsxs18(EditorRoot, { ...rootProps, children: [
7176
+ toolbar === true && /* @__PURE__ */ jsx21(EditorToolbar, {}),
6393
7177
  typeof toolbar === "function" && toolbar(DEFAULT_ITEMS),
6394
- /* @__PURE__ */ jsx17(EditorContent, { placeholder, foldable, children: outline && /* @__PURE__ */ jsx17(OutlinePlugin, {}) })
7178
+ /* @__PURE__ */ jsx21(EditorContent, { placeholder, foldable, children: outline && /* @__PURE__ */ jsx21(OutlinePlugin, {}) })
6395
7179
  ] });
6396
7180
  }
6397
7181
  MarkdownEditor.Root = EditorRoot;
@@ -6565,10 +7349,16 @@ var DRAWING_DATA_JSON_SCHEMA = {
6565
7349
  export {
6566
7350
  $createDrawingNode,
6567
7351
  $createFrontmatterNode,
7352
+ $deleteSelectedTableRow,
7353
+ $deleteTableRowAt,
6568
7354
  $getSelectedTable,
7355
+ $getSelectedTableCell,
6569
7356
  $getTableDensity,
7357
+ $getTableRowPosition,
6570
7358
  $getTableSettings,
6571
7359
  $getTableWidth,
7360
+ $insertTableRowAt,
7361
+ $insertTableRowNear,
6572
7362
  $isDrawingNode,
6573
7363
  $isFrontmatterNode,
6574
7364
  $isTableWidthExplicit,
@@ -6609,6 +7399,7 @@ export {
6609
7399
  anchorPoint,
6610
7400
  bindEndpoints,
6611
7401
  boxOutline,
7402
+ canDeleteRow,
6612
7403
  codeTokenizer,
6613
7404
  connectorPoints,
6614
7405
  drawingToMermaid,
@@ -6618,6 +7409,10 @@ export {
6618
7409
  formatTableSettingsMarker,
6619
7410
  getCodeLanguages,
6620
7411
  hasCodeLanguage,
7412
+ inkAmplitude,
7413
+ inkFillOffset,
7414
+ inkStroke,
7415
+ insertableRowIndices,
6621
7416
  isBlockWidth,
6622
7417
  isDrawingSkeleton,
6623
7418
  makeBinding,
@@ -6629,7 +7424,10 @@ export {
6629
7424
  registerCodeLanguage,
6630
7425
  resolveBindings,
6631
7426
  resolveCodeLanguage,
7427
+ roundedPolyline,
7428
+ roundedRectPolygon,
6632
7429
  routeElbow,
7430
+ seedFrom,
6633
7431
  serializeDrawingData,
6634
7432
  tokenizeCode,
6635
7433
  useMarkdownEditor