@zuilib/text-editor 0.9.0 → 0.10.1

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,348 @@ 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
+
1615
+ // src/transformers/tableSettings.ts
1616
+ import {
1617
+ $getNodeByKey as $getNodeByKey2,
1618
+ $getSelection as $getSelection2,
1619
+ $isRangeSelection as $isRangeSelection2
1620
+ } from "lexical";
1621
+ import { $findMatchingParent } from "@lexical/utils";
1622
+ import { $isTableNode, $isTableSelection } from "@lexical/table";
1623
+ var DEFAULT_TABLE_SETTINGS = {
1624
+ width: "full",
1625
+ density: "comfortable"
1626
+ };
1627
+ var BLOCK_BLEED_PROPERTY = "--zui-text-editor-block-bleed";
1628
+ var OPTION_DECLARATIONS = {
1629
+ width: {
1630
+ full: {},
1631
+ content: { width: "auto", "table-layout": "auto", [BLOCK_BLEED_PROPERTY]: "0px" },
1632
+ text: { [BLOCK_BLEED_PROPERTY]: "0px" }
1633
+ },
1634
+ density: {
1635
+ comfortable: {},
1636
+ compact: {
1637
+ "--zui-table-cell-padding": "0.25rem 0.5rem",
1638
+ "--zui-table-font-size": "0.8125rem"
1639
+ },
1640
+ spacious: {
1641
+ "--zui-table-cell-padding": "0.875rem 1rem",
1642
+ "--zui-table-font-size": "0.9375rem"
1643
+ }
1644
+ }
1645
+ };
1646
+ var SETTING_KEYS = Object.keys(OPTION_DECLARATIONS);
1647
+ var EXPLICIT_WIDTH_PROPERTY = "--zui-table-width";
1648
+ function parseStyle(style) {
1649
+ const declarations = /* @__PURE__ */ new Map();
1650
+ for (const part of style.split(";")) {
1651
+ const index = part.indexOf(":");
1652
+ if (index === -1) continue;
1653
+ const key = part.slice(0, index).trim();
1654
+ const value = part.slice(index + 1).trim();
1655
+ if (key && value) declarations.set(key, value);
1656
+ }
1657
+ return declarations;
1658
+ }
1659
+ function serializeStyle(declarations) {
1660
+ return [...declarations].map(([key, value]) => `${key}: ${value}`).join("; ");
1661
+ }
1662
+ function optionsOf(setting) {
1663
+ return Object.entries(OPTION_DECLARATIONS[setting]);
1664
+ }
1665
+ function readSetting(declarations, setting) {
1666
+ for (const [option, decls] of optionsOf(setting)) {
1667
+ const entries = Object.entries(decls);
1668
+ if (entries.length === 0) continue;
1669
+ if (entries.every(([key, value]) => declarations.get(key) === value)) {
1670
+ return option;
1671
+ }
1672
+ }
1673
+ return DEFAULT_TABLE_SETTINGS[setting];
1674
+ }
1675
+ function writeSetting(declarations, setting, option) {
1676
+ for (const [, decls] of optionsOf(setting)) {
1677
+ for (const key of Object.keys(decls)) declarations.delete(key);
1678
+ }
1679
+ for (const [key, value] of Object.entries(OPTION_DECLARATIONS[setting][option])) {
1680
+ declarations.set(key, value);
1681
+ }
1682
+ }
1683
+ function $getTableSettings(table) {
1684
+ const declarations = parseStyle(table.getStyle());
1685
+ return {
1686
+ width: readSetting(declarations, "width"),
1687
+ density: readSetting(declarations, "density")
1688
+ };
1689
+ }
1690
+ function $setTableSettings(table, settings, options = {}) {
1691
+ const declarations = parseStyle(table.getStyle());
1692
+ for (const key of SETTING_KEYS) {
1693
+ const option = settings[key];
1694
+ if (option !== void 0) writeSetting(declarations, key, option);
1695
+ }
1696
+ if (settings.width !== void 0) {
1697
+ if (options.explicitWidth) declarations.set(EXPLICIT_WIDTH_PROPERTY, settings.width);
1698
+ else declarations.delete(EXPLICIT_WIDTH_PROPERTY);
1699
+ }
1700
+ table.setStyle(serializeStyle(declarations));
1701
+ }
1702
+ function $isTableWidthExplicit(table) {
1703
+ const declarations = parseStyle(table.getStyle());
1704
+ return declarations.get(EXPLICIT_WIDTH_PROPERTY) === readSetting(declarations, "width");
1705
+ }
1706
+ function $getTableWidth(table) {
1707
+ return $getTableSettings(table).width;
1708
+ }
1709
+ function $setTableWidth(table, width) {
1710
+ $setTableSettings(table, { width });
1711
+ }
1712
+ function $getTableDensity(table) {
1713
+ return $getTableSettings(table).density;
1714
+ }
1715
+ function $setTableDensity(table, density) {
1716
+ $setTableSettings(table, { density });
1717
+ }
1718
+ function $getSelectedTable() {
1719
+ const selection = $getSelection2();
1720
+ if ($isTableSelection(selection)) {
1721
+ const node = $getNodeByKey2(selection.tableKey);
1722
+ return $isTableNode(node) ? node : null;
1723
+ }
1724
+ if (!$isRangeSelection2(selection)) return null;
1725
+ const table = $findMatchingParent(
1726
+ selection.anchor.getNode(),
1727
+ (node) => $isTableNode(node)
1728
+ );
1729
+ return $isTableNode(table) ? table : null;
1730
+ }
1731
+ var MARKER_REG_EXP = /^<!--\s*([a-z]+\s*:\s*[a-z]+(?:\s*;\s*[a-z]+\s*:\s*[a-z]+)*)\s*;?\s*-->\s*$/;
1732
+ function isOption(setting, value) {
1733
+ return value in OPTION_DECLARATIONS[setting];
1734
+ }
1735
+ var TABLE_WIDTH_MARKER = "<!-- width: content -->";
1736
+ function parseTableSettingsMarker(text) {
1737
+ const match = MARKER_REG_EXP.exec(text);
1738
+ if (!match) return null;
1739
+ const settings = {};
1740
+ let recognised = false;
1741
+ for (const pair of match[1].split(";")) {
1742
+ const [key, value] = pair.split(":").map((s) => s.trim());
1743
+ if (key !== "width" && key !== "density") continue;
1744
+ recognised = true;
1745
+ if (key === "width" && isOption("width", value)) settings.width = value;
1746
+ if (key === "density" && isOption("density", value)) settings.density = value;
1747
+ }
1748
+ return recognised ? settings : null;
1749
+ }
1750
+ function formatTableSettingsMarker(settings, options = {}) {
1751
+ const pairs = SETTING_KEYS.filter(
1752
+ (key) => settings[key] !== DEFAULT_TABLE_SETTINGS[key] || key === "width" && options.explicitWidth
1753
+ ).map((key) => `${key}: ${settings[key]}`);
1754
+ return pairs.length > 0 ? `<!-- ${pairs.join("; ")} -->` : null;
1755
+ }
1756
+
1757
+ // src/transformers/tableGrid.ts
1758
+ import {
1759
+ $createParagraphNode as $createParagraphNode2,
1760
+ $getNodeByKey as $getNodeByKey3,
1761
+ $getSelection as $getSelection3,
1762
+ $isRangeSelection as $isRangeSelection3
1763
+ } from "lexical";
1764
+ import { $findMatchingParent as $findMatchingParent2 } from "@lexical/utils";
1765
+ import {
1766
+ $createTableCellNode,
1767
+ $createTableRowNode,
1768
+ $isTableCellNode,
1769
+ $isTableNode as $isTableNode2,
1770
+ $isTableRowNode,
1771
+ $isTableSelection as $isTableSelection2,
1772
+ TableCellHeaderStates
1773
+ } from "@lexical/table";
1774
+ function $rows(table) {
1775
+ return table.getChildren().filter($isTableRowNode);
1776
+ }
1777
+ function $cells(row) {
1778
+ return row.getChildren().filter($isTableCellNode);
1779
+ }
1780
+ function $isHeaderRow(row) {
1781
+ const cells = row ? $cells(row) : [];
1782
+ return cells.length > 0 && cells.every((cell) => cell.hasHeaderState(TableCellHeaderStates.ROW));
1783
+ }
1784
+ function $columnCount(table) {
1785
+ const first = $rows(table)[0];
1786
+ return first ? $cells(first).length : 0;
1787
+ }
1788
+ function $emptyCell(headerState) {
1789
+ return $createTableCellNode(headerState).append($createParagraphNode2());
1790
+ }
1791
+ function $selectCellAt(table, row, column) {
1792
+ const rows = $rows(table);
1793
+ const target = rows[Math.max(0, Math.min(row, rows.length - 1))];
1794
+ const cells = target ? $cells(target) : [];
1795
+ cells[Math.max(0, Math.min(column, cells.length - 1))]?.selectStart();
1796
+ }
1797
+ function $getSelectedTableCell() {
1798
+ const selection = $getSelection3();
1799
+ let node = null;
1800
+ if ($isTableSelection2(selection)) node = $getNodeByKey3(selection.anchor.key);
1801
+ else if ($isRangeSelection3(selection)) node = selection.anchor.getNode();
1802
+ if (!node) return null;
1803
+ const cell = $findMatchingParent2(node, (n2) => $isTableCellNode(n2));
1804
+ return $isTableCellNode(cell) ? cell : null;
1805
+ }
1806
+ function $getTableCellPosition() {
1807
+ const cell = $getSelectedTableCell();
1808
+ const row = cell?.getParent();
1809
+ const table = row?.getParent();
1810
+ if (!cell || !$isTableRowNode(row) || !$isTableNode2(table)) return null;
1811
+ const rows = $rows(table);
1812
+ return {
1813
+ row: rows.indexOf(row),
1814
+ column: $cells(row).indexOf(cell),
1815
+ rows: rows.length,
1816
+ columns: $columnCount(table),
1817
+ hasHeader: $isHeaderRow(rows[0])
1818
+ };
1819
+ }
1820
+ function insertableRowIndices(position) {
1821
+ const indices = [];
1822
+ for (let i = position.hasHeader ? 1 : 0; i <= position.rows; i++) indices.push(i);
1823
+ return indices;
1824
+ }
1825
+ function canDeleteRow(position) {
1826
+ return position.rows > 1;
1827
+ }
1828
+ function $insertTableRowAt(table, index, column = 0) {
1829
+ const rows = $rows(table);
1830
+ const minIndex = $isHeaderRow(rows[0]) ? 1 : 0;
1831
+ const at = Math.max(minIndex, Math.min(index, rows.length));
1832
+ const reference = rows[Math.max(0, at - 1)] ?? rows[0];
1833
+ const referenceCells = reference ? $cells(reference) : [];
1834
+ const row = $createTableRowNode();
1835
+ for (const cell of referenceCells) {
1836
+ row.append(
1837
+ $emptyCell(
1838
+ cell.hasHeaderState(TableCellHeaderStates.COLUMN) ? TableCellHeaderStates.COLUMN : TableCellHeaderStates.NO_STATUS
1839
+ )
1840
+ );
1841
+ }
1842
+ if (referenceCells.length === 0) row.append($emptyCell(TableCellHeaderStates.NO_STATUS));
1843
+ if (at >= rows.length) table.append(row);
1844
+ else rows[at].insertBefore(row);
1845
+ $selectCellAt(table, at, column);
1846
+ return row;
1847
+ }
1848
+ function $deleteTableRowAt(table, index, column = 0) {
1849
+ const rows = $rows(table);
1850
+ const row = rows[index];
1851
+ if (!row || rows.length < 2) return false;
1852
+ const wasHeader = index === 0 && $isHeaderRow(row);
1853
+ row.remove();
1854
+ const remaining = $rows(table);
1855
+ if (wasHeader) {
1856
+ for (const cell of $cells(remaining[0])) {
1857
+ cell.setHeaderStyles(TableCellHeaderStates.ROW, TableCellHeaderStates.ROW);
1858
+ }
1859
+ }
1860
+ $selectCellAt(table, index, column);
1861
+ return true;
1862
+ }
1863
+ function $insertTableRowNear(table, position) {
1864
+ const at = $getTableCellPosition();
1865
+ if (!at) return null;
1866
+ return $insertTableRowAt(table, position === "below" ? at.row + 1 : at.row, at.column);
1867
+ }
1868
+ function $deleteSelectedTableRow(table) {
1869
+ const at = $getTableCellPosition();
1870
+ if (!at || !canDeleteRow(at)) return false;
1871
+ return $deleteTableRowAt(table, at.row, at.column);
1872
+ }
1873
+ function insertableColumnIndices(position) {
1874
+ const indices = [];
1875
+ for (let i = 0; i <= position.columns; i++) indices.push(i);
1876
+ return indices;
1877
+ }
1878
+ function canDeleteColumn(position) {
1879
+ return position.columns > 1;
1880
+ }
1881
+ function $insertTableColumnAt(table, index, row = 0) {
1882
+ const at = Math.max(0, Math.min(index, $columnCount(table)));
1883
+ for (const tableRow of $rows(table)) {
1884
+ const cells = $cells(tableRow);
1885
+ const cell = $emptyCell(
1886
+ $isHeaderRow(tableRow) ? TableCellHeaderStates.ROW : TableCellHeaderStates.NO_STATUS
1887
+ );
1888
+ if (at < cells.length) cells[at].insertBefore(cell);
1889
+ else tableRow.append(cell);
1890
+ }
1891
+ $selectCellAt(table, row, at);
1892
+ }
1893
+ function $deleteTableColumnAt(table, index, row = 0) {
1894
+ const columns = $columnCount(table);
1895
+ if (index < 0 || index >= columns || columns < 2) return false;
1896
+ for (const tableRow of $rows(table)) $cells(tableRow)[index]?.remove();
1897
+ $selectCellAt(table, row, index);
1898
+ return true;
1899
+ }
1900
+ function $insertTableColumnNear(table, position) {
1901
+ const at = $getTableCellPosition();
1902
+ if (!at) return false;
1903
+ $insertTableColumnAt(table, position === "after" ? at.column + 1 : at.column, at.row);
1904
+ return true;
1905
+ }
1906
+ function $deleteSelectedTableColumn(table) {
1907
+ const at = $getTableCellPosition();
1908
+ if (!at || !canDeleteColumn(at)) return false;
1909
+ return $deleteTableColumnAt(table, at.column, at.row);
1910
+ }
1911
+
1912
+ // src/plugins/TableRowShortcutsPlugin.tsx
1913
+ function shortcutFor(event) {
1914
+ const mod = event.metaKey || event.ctrlKey;
1915
+ if (event.altKey) return null;
1916
+ if (event.key === "Enter" && mod) return event.shiftKey ? "insert-above" : "insert-below";
1917
+ if (event.key === "Backspace" && mod && event.shiftKey) return "delete";
1918
+ if (event.key === "Tab" && !mod && !event.shiftKey) return "tab";
1919
+ return null;
1920
+ }
1921
+ function TableRowShortcutsPlugin() {
1922
+ const [editor] = useLexicalComposerContext5();
1923
+ useEffect5(
1924
+ () => editor.registerCommand(
1925
+ KEY_DOWN_COMMAND,
1926
+ (event) => {
1927
+ const shortcut = shortcutFor(event);
1928
+ if (!shortcut) return false;
1929
+ const table = $getSelectedTable();
1930
+ const position = $getTableCellPosition();
1931
+ if (!table || !position) return false;
1932
+ if (shortcut === "tab") {
1933
+ const selection = $getSelection4();
1934
+ const isLastCell = position.row === position.rows - 1 && position.column === position.columns - 1;
1935
+ if (!isLastCell || !$isRangeSelection4(selection) || !selection.isCollapsed()) return false;
1936
+ event.preventDefault();
1937
+ $insertTableRowAt(table, position.rows);
1938
+ return true;
1939
+ }
1940
+ event.preventDefault();
1941
+ if (shortcut === "delete") $deleteSelectedTableRow(table);
1942
+ else $insertTableRowNear(table, shortcut === "insert-above" ? "above" : "below");
1943
+ return true;
1944
+ },
1945
+ COMMAND_PRIORITY_HIGH
1946
+ ),
1947
+ [editor]
1948
+ );
1949
+ return null;
1950
+ }
1951
+
1610
1952
  // src/nodes/FrontmatterNode.ts
1611
1953
  import {
1612
1954
  $applyNodeReplacement,
@@ -1696,14 +2038,14 @@ import {
1696
2038
  // src/drawing/canvas/DrawingCanvas.tsx
1697
2039
  import {
1698
2040
  useCallback,
1699
- useEffect as useEffect7,
2041
+ useEffect as useEffect8,
1700
2042
  useMemo,
1701
2043
  useRef as useRef4,
1702
2044
  useState as useState3,
1703
2045
  useContext as useContext2
1704
2046
  } from "react";
1705
- import { $getNodeByKey as $getNodeByKey2 } from "lexical";
1706
- import { useLexicalComposerContext as useLexicalComposerContext5 } from "@lexical/react/LexicalComposerContext";
2047
+ import { $getNodeByKey as $getNodeByKey4 } from "lexical";
2048
+ import { useLexicalComposerContext as useLexicalComposerContext6 } from "@lexical/react/LexicalComposerContext";
1707
2049
  import { useLexicalEditable } from "@lexical/react/useLexicalEditable";
1708
2050
 
1709
2051
  // src/editorContext.ts
@@ -4501,7 +4843,7 @@ function HitArea({
4501
4843
 
4502
4844
  // src/drawing/canvas/TextEditOverlay.tsx
4503
4845
  import {
4504
- useEffect as useEffect5,
4846
+ useEffect as useEffect6,
4505
4847
  useRef as useRef2,
4506
4848
  useState
4507
4849
  } from "react";
@@ -4517,7 +4859,7 @@ function TextEditOverlay({
4517
4859
  const ref = useRef2(null);
4518
4860
  const valueRef = useRef2(value);
4519
4861
  valueRef.current = value;
4520
- useEffect5(() => {
4862
+ useEffect6(() => {
4521
4863
  const el = ref.current;
4522
4864
  if (!el) return;
4523
4865
  el.focus();
@@ -4625,7 +4967,7 @@ function TextEditOverlay({
4625
4967
  }
4626
4968
 
4627
4969
  // src/drawing/canvas/Toolbar.tsx
4628
- import { useEffect as useEffect6, useRef as useRef3, useState as useState2 } from "react";
4970
+ import { useEffect as useEffect7, useRef as useRef3, useState as useState2 } from "react";
4629
4971
 
4630
4972
  // src/components/blockWidthOptions.tsx
4631
4973
  import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
@@ -4710,7 +5052,7 @@ function DrawingToolbar({
4710
5052
  const [lastMore, setLastMore] = useState2("note");
4711
5053
  const [copied, setCopied] = useState2(false);
4712
5054
  const moreRef = useRef3(null);
4713
- useEffect6(() => {
5055
+ useEffect7(() => {
4714
5056
  if (!moreOpen) return;
4715
5057
  const close = (e) => {
4716
5058
  if (!moreRef.current?.contains(e.target)) setMoreOpen(false);
@@ -4832,7 +5174,7 @@ function computePaths(shapes) {
4832
5174
  return paths;
4833
5175
  }
4834
5176
  function DrawingCanvas({ nodeKey, data }) {
4835
- const [editor] = useLexicalComposerContext5();
5177
+ const [editor] = useLexicalComposerContext6();
4836
5178
  const isEditable = useLexicalEditable();
4837
5179
  const [shapes, setShapes] = useState3(data.shapes);
4838
5180
  const [canvasHeight, setCanvasHeight] = useState3(data.canvasHeight);
@@ -4864,7 +5206,7 @@ function DrawingCanvas({ nodeKey, data }) {
4864
5206
  const paths = useMemo(() => computePaths(shapes), [shapes]);
4865
5207
  const canvasWidth = data.canvasWidth;
4866
5208
  const logicalWidth = canvasWidth ?? (width === "content" ? contentWidth(shapes, paths) : null);
4867
- useEffect7(() => {
5209
+ useEffect8(() => {
4868
5210
  const incoming = serializeDrawingData(data);
4869
5211
  if (incoming !== lastCommittedRef.current) {
4870
5212
  lastCommittedRef.current = incoming;
@@ -4875,7 +5217,7 @@ function DrawingCanvas({ nodeKey, data }) {
4875
5217
  setEditingText(null);
4876
5218
  }
4877
5219
  }, [data]);
4878
- useEffect7(() => {
5220
+ useEffect8(() => {
4879
5221
  const svg = svgRef.current;
4880
5222
  if (!logicalWidth || !svg || typeof ResizeObserver === "undefined") {
4881
5223
  setScale(1);
@@ -4905,7 +5247,7 @@ function DrawingCanvas({ nodeKey, data }) {
4905
5247
  if (json2 === lastCommittedRef.current) return;
4906
5248
  lastCommittedRef.current = json2;
4907
5249
  editor.update(() => {
4908
- const node = $getNodeByKey2(nodeKey);
5250
+ const node = $getNodeByKey4(nodeKey);
4909
5251
  if ($isDrawingNode(node)) node.setData(payload);
4910
5252
  });
4911
5253
  },
@@ -5165,7 +5507,7 @@ function DrawingCanvas({ nodeKey, data }) {
5165
5507
  }, [updateShapes]);
5166
5508
  const editingRef = useRef4(editingText);
5167
5509
  editingRef.current = editingText;
5168
- useEffect7(() => {
5510
+ useEffect8(() => {
5169
5511
  const root = rootRef.current;
5170
5512
  if (!root || !isEditable) return;
5171
5513
  const onKeyDown = (e) => {
@@ -5612,161 +5954,17 @@ import {
5612
5954
  TRANSFORMERS
5613
5955
  } from "@lexical/markdown";
5614
5956
  import {
5615
- $createTableCellNode,
5957
+ $createTableCellNode as $createTableCellNode2,
5616
5958
  $createTableNode,
5617
- $createTableRowNode,
5618
- $isTableCellNode,
5619
- $isTableNode as $isTableNode2,
5620
- $isTableRowNode,
5621
- TableCellHeaderStates,
5959
+ $createTableRowNode as $createTableRowNode2,
5960
+ $isTableCellNode as $isTableCellNode2,
5961
+ $isTableNode as $isTableNode3,
5962
+ $isTableRowNode as $isTableRowNode2,
5963
+ TableCellHeaderStates as TableCellHeaderStates2,
5622
5964
  TableCellNode,
5623
5965
  TableNode,
5624
5966
  TableRowNode
5625
5967
  } from "@lexical/table";
5626
-
5627
- // src/transformers/tableSettings.ts
5628
- import {
5629
- $getNodeByKey as $getNodeByKey3,
5630
- $getSelection as $getSelection2,
5631
- $isRangeSelection as $isRangeSelection2
5632
- } from "lexical";
5633
- import { $findMatchingParent } from "@lexical/utils";
5634
- import { $isTableNode, $isTableSelection } from "@lexical/table";
5635
- var DEFAULT_TABLE_SETTINGS = {
5636
- width: "full",
5637
- density: "comfortable"
5638
- };
5639
- var BLOCK_BLEED_PROPERTY = "--zui-text-editor-block-bleed";
5640
- var OPTION_DECLARATIONS = {
5641
- width: {
5642
- full: {},
5643
- content: { width: "auto", "table-layout": "auto", [BLOCK_BLEED_PROPERTY]: "0px" },
5644
- text: { [BLOCK_BLEED_PROPERTY]: "0px" }
5645
- },
5646
- density: {
5647
- comfortable: {},
5648
- compact: {
5649
- "--zui-table-cell-padding": "0.25rem 0.5rem",
5650
- "--zui-table-font-size": "0.8125rem"
5651
- },
5652
- spacious: {
5653
- "--zui-table-cell-padding": "0.875rem 1rem",
5654
- "--zui-table-font-size": "0.9375rem"
5655
- }
5656
- }
5657
- };
5658
- var SETTING_KEYS = Object.keys(OPTION_DECLARATIONS);
5659
- var EXPLICIT_WIDTH_PROPERTY = "--zui-table-width";
5660
- function parseStyle(style) {
5661
- const declarations = /* @__PURE__ */ new Map();
5662
- for (const part of style.split(";")) {
5663
- const index = part.indexOf(":");
5664
- if (index === -1) continue;
5665
- const key = part.slice(0, index).trim();
5666
- const value = part.slice(index + 1).trim();
5667
- if (key && value) declarations.set(key, value);
5668
- }
5669
- return declarations;
5670
- }
5671
- function serializeStyle(declarations) {
5672
- return [...declarations].map(([key, value]) => `${key}: ${value}`).join("; ");
5673
- }
5674
- function optionsOf(setting) {
5675
- return Object.entries(OPTION_DECLARATIONS[setting]);
5676
- }
5677
- function readSetting(declarations, setting) {
5678
- for (const [option, decls] of optionsOf(setting)) {
5679
- const entries = Object.entries(decls);
5680
- if (entries.length === 0) continue;
5681
- if (entries.every(([key, value]) => declarations.get(key) === value)) {
5682
- return option;
5683
- }
5684
- }
5685
- return DEFAULT_TABLE_SETTINGS[setting];
5686
- }
5687
- function writeSetting(declarations, setting, option) {
5688
- for (const [, decls] of optionsOf(setting)) {
5689
- for (const key of Object.keys(decls)) declarations.delete(key);
5690
- }
5691
- for (const [key, value] of Object.entries(OPTION_DECLARATIONS[setting][option])) {
5692
- declarations.set(key, value);
5693
- }
5694
- }
5695
- function $getTableSettings(table) {
5696
- const declarations = parseStyle(table.getStyle());
5697
- return {
5698
- width: readSetting(declarations, "width"),
5699
- density: readSetting(declarations, "density")
5700
- };
5701
- }
5702
- function $setTableSettings(table, settings, options = {}) {
5703
- const declarations = parseStyle(table.getStyle());
5704
- for (const key of SETTING_KEYS) {
5705
- const option = settings[key];
5706
- if (option !== void 0) writeSetting(declarations, key, option);
5707
- }
5708
- if (settings.width !== void 0) {
5709
- if (options.explicitWidth) declarations.set(EXPLICIT_WIDTH_PROPERTY, settings.width);
5710
- else declarations.delete(EXPLICIT_WIDTH_PROPERTY);
5711
- }
5712
- table.setStyle(serializeStyle(declarations));
5713
- }
5714
- function $isTableWidthExplicit(table) {
5715
- const declarations = parseStyle(table.getStyle());
5716
- return declarations.get(EXPLICIT_WIDTH_PROPERTY) === readSetting(declarations, "width");
5717
- }
5718
- function $getTableWidth(table) {
5719
- return $getTableSettings(table).width;
5720
- }
5721
- function $setTableWidth(table, width) {
5722
- $setTableSettings(table, { width });
5723
- }
5724
- function $getTableDensity(table) {
5725
- return $getTableSettings(table).density;
5726
- }
5727
- function $setTableDensity(table, density) {
5728
- $setTableSettings(table, { density });
5729
- }
5730
- function $getSelectedTable() {
5731
- const selection = $getSelection2();
5732
- if ($isTableSelection(selection)) {
5733
- const node = $getNodeByKey3(selection.tableKey);
5734
- return $isTableNode(node) ? node : null;
5735
- }
5736
- if (!$isRangeSelection2(selection)) return null;
5737
- const table = $findMatchingParent(
5738
- selection.anchor.getNode(),
5739
- (node) => $isTableNode(node)
5740
- );
5741
- return $isTableNode(table) ? table : null;
5742
- }
5743
- var MARKER_REG_EXP = /^<!--\s*([a-z]+\s*:\s*[a-z]+(?:\s*;\s*[a-z]+\s*:\s*[a-z]+)*)\s*;?\s*-->\s*$/;
5744
- function isOption(setting, value) {
5745
- return value in OPTION_DECLARATIONS[setting];
5746
- }
5747
- var TABLE_WIDTH_MARKER = "<!-- width: content -->";
5748
- function parseTableSettingsMarker(text) {
5749
- const match = MARKER_REG_EXP.exec(text);
5750
- if (!match) return null;
5751
- const settings = {};
5752
- let recognised = false;
5753
- for (const pair of match[1].split(";")) {
5754
- const [key, value] = pair.split(":").map((s) => s.trim());
5755
- if (key !== "width" && key !== "density") continue;
5756
- recognised = true;
5757
- if (key === "width" && isOption("width", value)) settings.width = value;
5758
- if (key === "density" && isOption("density", value)) settings.density = value;
5759
- }
5760
- return recognised ? settings : null;
5761
- }
5762
- function formatTableSettingsMarker(settings, options = {}) {
5763
- const pairs = SETTING_KEYS.filter(
5764
- (key) => settings[key] !== DEFAULT_TABLE_SETTINGS[key] || key === "width" && options.explicitWidth
5765
- ).map((key) => `${key}: ${settings[key]}`);
5766
- return pairs.length > 0 ? `<!-- ${pairs.join("; ")} -->` : null;
5767
- }
5768
-
5769
- // src/transformers/tableTransformer.ts
5770
5968
  var TABLE_ROW_REG_EXP = /^\|(.+)\|\s?$/;
5771
5969
  var TABLE_ROW_DIVIDER_REG_EXP = /^(\| ?:?-*:? ?)+\|\s?$/;
5772
5970
  function $getMarkerSettings(node) {
@@ -5776,11 +5974,11 @@ function $getMarkerSettings(node) {
5776
5974
  }
5777
5975
  function getTableColumnsSize(table) {
5778
5976
  const row = table.getFirstChild();
5779
- return $isTableRowNode(row) ? row.getChildrenSize() : 0;
5977
+ return $isTableRowNode2(row) ? row.getChildrenSize() : 0;
5780
5978
  }
5781
5979
  function createTableCell(textContent) {
5782
5980
  const unescaped = textContent.replace(/\\n/g, "\n");
5783
- const cell = $createTableCellNode(TableCellHeaderStates.NO_STATUS);
5981
+ const cell = $createTableCellNode2(TableCellHeaderStates2.NO_STATUS);
5784
5982
  $convertFromMarkdownString2(unescaped, TRANSFORMERS, cell);
5785
5983
  return cell;
5786
5984
  }
@@ -5792,22 +5990,22 @@ function mapToTableCells(textContent) {
5792
5990
  var TABLE = {
5793
5991
  dependencies: [TableNode, TableRowNode, TableCellNode],
5794
5992
  export: (node) => {
5795
- if (!$isTableNode2(node)) return null;
5993
+ if (!$isTableNode3(node)) return null;
5796
5994
  const output = [];
5797
5995
  const marker = formatTableSettingsMarker($getTableSettings(node), {
5798
5996
  explicitWidth: $isTableWidthExplicit(node)
5799
5997
  });
5800
5998
  if (marker) output.push(marker);
5801
5999
  for (const row of node.getChildren()) {
5802
- if (!$isTableRowNode(row)) continue;
6000
+ if (!$isTableRowNode2(row)) continue;
5803
6001
  const rowOutput = [];
5804
6002
  let isHeaderRow = false;
5805
6003
  for (const cell of row.getChildren()) {
5806
- if (!$isTableCellNode(cell)) continue;
6004
+ if (!$isTableCellNode2(cell)) continue;
5807
6005
  rowOutput.push(
5808
6006
  $convertToMarkdownString2(TRANSFORMERS, cell).replace(/\n/g, "\\n")
5809
6007
  );
5810
- if (cell.__headerState === TableCellHeaderStates.ROW) {
6008
+ if (cell.__headerState === TableCellHeaderStates2.ROW) {
5811
6009
  isHeaderRow = true;
5812
6010
  }
5813
6011
  }
@@ -5822,12 +6020,12 @@ var TABLE = {
5822
6020
  replace: (parentNode, _children, match) => {
5823
6021
  if (TABLE_ROW_DIVIDER_REG_EXP.test(match[0])) {
5824
6022
  const table2 = parentNode.getPreviousSibling();
5825
- if (!table2 || !$isTableNode2(table2)) return;
6023
+ if (!table2 || !$isTableNode3(table2)) return;
5826
6024
  const lastRow = table2.getLastChild();
5827
- if (!lastRow || !$isTableRowNode(lastRow)) return;
6025
+ if (!lastRow || !$isTableRowNode2(lastRow)) return;
5828
6026
  lastRow.getChildren().forEach((cell) => {
5829
- if ($isTableCellNode(cell)) {
5830
- cell.setHeaderStyles(TableCellHeaderStates.ROW, TableCellHeaderStates.ROW);
6027
+ if ($isTableCellNode2(cell)) {
6028
+ cell.setHeaderStyles(TableCellHeaderStates2.ROW, TableCellHeaderStates2.ROW);
5831
6029
  }
5832
6030
  });
5833
6031
  parentNode.remove();
@@ -5852,14 +6050,14 @@ var TABLE = {
5852
6050
  }
5853
6051
  const table = $createTableNode();
5854
6052
  for (const cells of rows) {
5855
- const tableRow = $createTableRowNode();
6053
+ const tableRow = $createTableRowNode2();
5856
6054
  table.append(tableRow);
5857
6055
  for (let i = 0; i < maxCells; i++) {
5858
6056
  tableRow.append(i < cells.length ? cells[i] : createTableCell(""));
5859
6057
  }
5860
6058
  }
5861
6059
  const previousSibling = parentNode.getPreviousSibling();
5862
- if ($isTableNode2(previousSibling) && getTableColumnsSize(previousSibling) === maxCells) {
6060
+ if ($isTableNode3(previousSibling) && getTableColumnsSize(previousSibling) === maxCells) {
5863
6061
  previousSibling.append(...table.getChildren());
5864
6062
  parentNode.remove();
5865
6063
  } else {
@@ -5970,8 +6168,8 @@ var editorNodes = [
5970
6168
  DrawingNode
5971
6169
  ];
5972
6170
  function ReadOnlyPlugin({ readOnly }) {
5973
- const [editor] = useLexicalComposerContext6();
5974
- useEffect8(() => {
6171
+ const [editor] = useLexicalComposerContext7();
6172
+ useEffect9(() => {
5975
6173
  editor.setEditable(!readOnly);
5976
6174
  }, [editor, readOnly]);
5977
6175
  return null;
@@ -5983,7 +6181,7 @@ function EditorRoot({
5983
6181
  className,
5984
6182
  mode = "edit-md",
5985
6183
  autoFocus = false,
5986
- measure,
6184
+ measure: measure2,
5987
6185
  defaultBlockWidth = NO_DEFAULT_BLOCK_WIDTH,
5988
6186
  drawingStyle = "clean",
5989
6187
  children
@@ -5991,7 +6189,7 @@ function EditorRoot({
5991
6189
  const latestValueRef = useRef5(value ?? "");
5992
6190
  const [mountKey, setMountKey] = useState4(0);
5993
6191
  const [capturedMarkdown, setCapturedMarkdown] = useState4(value ?? "");
5994
- useEffect8(() => {
6192
+ useEffect9(() => {
5995
6193
  if (value !== void 0) {
5996
6194
  latestValueRef.current = value;
5997
6195
  }
@@ -6004,7 +6202,7 @@ function EditorRoot({
6004
6202
  [onChange]
6005
6203
  );
6006
6204
  const prevModeRef = useRef5(mode);
6007
- useEffect8(() => {
6205
+ useEffect9(() => {
6008
6206
  if (prevModeRef.current === "edit-raw" && mode !== "edit-raw") {
6009
6207
  setCapturedMarkdown(latestValueRef.current);
6010
6208
  setMountKey((k) => k + 1);
@@ -6034,8 +6232,8 @@ function EditorRoot({
6034
6232
  );
6035
6233
  const isRaw = mode === "edit-raw";
6036
6234
  const rootStyle = useMemo2(
6037
- () => measure !== void 0 ? { "--zui-text-editor-measure": measure } : void 0,
6038
- [measure]
6235
+ () => measure2 !== void 0 ? { "--zui-text-editor-measure": measure2 } : void 0,
6236
+ [measure2]
6039
6237
  );
6040
6238
  return /* @__PURE__ */ jsx12(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsx12(EditorContext.Provider, { value: context, children: /* @__PURE__ */ jsxs10("div", { className: `zui-text-editor ${className ?? ""}`, style: rootStyle, children: [
6041
6239
  children,
@@ -6055,6 +6253,7 @@ function EditorRoot({
6055
6253
  /* @__PURE__ */ jsx12(CodeBlockShortcutPlugin, {}),
6056
6254
  /* @__PURE__ */ jsx12(CodeHighlightPlugin, {}),
6057
6255
  /* @__PURE__ */ jsx12(TablePlugin, {}),
6256
+ /* @__PURE__ */ jsx12(TableRowShortcutsPlugin, {}),
6058
6257
  /* @__PURE__ */ jsx12(LinkPlugin, {}),
6059
6258
  /* @__PURE__ */ jsx12(MarkdownShortcutPlugin, { transformers: SHORTCUT_TRANSFORMERS }),
6060
6259
  /* @__PURE__ */ jsx12(ReadOnlyPlugin, { readOnly: readOnly || mode === "view" }),
@@ -6071,12 +6270,12 @@ import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
6071
6270
  // src/plugins/FoldingPlugin.tsx
6072
6271
  import {
6073
6272
  useCallback as useCallback3,
6074
- useEffect as useEffect9,
6273
+ useEffect as useEffect10,
6075
6274
  useRef as useRef6,
6076
6275
  useState as useState5
6077
6276
  } from "react";
6078
- import { $getRoot, $getSelection as $getSelection3, $isRangeSelection as $isRangeSelection3 } from "lexical";
6079
- import { useLexicalComposerContext as useLexicalComposerContext7 } from "@lexical/react/LexicalComposerContext";
6277
+ import { $getRoot, $getSelection as $getSelection5, $isRangeSelection as $isRangeSelection5 } from "lexical";
6278
+ import { useLexicalComposerContext as useLexicalComposerContext8 } from "@lexical/react/LexicalComposerContext";
6080
6279
  import { $isHeadingNode } from "@lexical/rich-text";
6081
6280
  import { jsx as jsx13 } from "react/jsx-runtime";
6082
6281
  var HEADING_LEVELS = {
@@ -6088,7 +6287,7 @@ var HEADING_LEVELS = {
6088
6287
  h6: 6
6089
6288
  };
6090
6289
  function FoldingPlugin() {
6091
- const [editor] = useLexicalComposerContext7();
6290
+ const [editor] = useLexicalComposerContext8();
6092
6291
  const [foldedKeys, setFoldedKeys] = useState5(/* @__PURE__ */ new Set());
6093
6292
  const [buttons, setButtons] = useState5([]);
6094
6293
  const foldedRef = useRef6(foldedKeys);
@@ -6114,8 +6313,8 @@ function FoldingPlugin() {
6114
6313
  hidden.add(sibling.getKey());
6115
6314
  }
6116
6315
  }
6117
- const selection = $getSelection3();
6118
- if ($isRangeSelection3(selection)) {
6316
+ const selection = $getSelection5();
6317
+ if ($isRangeSelection5(selection)) {
6119
6318
  const topLevel = selection.anchor.getNode().getTopLevelElement();
6120
6319
  if (topLevel && hidden.has(topLevel.getKey())) {
6121
6320
  let node = topLevel.getPreviousSibling();
@@ -6157,7 +6356,7 @@ function FoldingPlugin() {
6157
6356
  );
6158
6357
  });
6159
6358
  }, [editor]);
6160
- useEffect9(() => {
6359
+ useEffect10(() => {
6161
6360
  sync();
6162
6361
  const unregister = editor.registerUpdateListener(sync);
6163
6362
  const rootElement = editor.getRootElement();
@@ -6205,17 +6404,109 @@ function FoldingPlugin() {
6205
6404
  )) });
6206
6405
  }
6207
6406
 
6208
- // src/plugins/TableSettingsPlugin.tsx
6209
- import { useCallback as useCallback5, useEffect as useEffect11, useState as useState7 } from "react";
6210
- import { useLexicalComposerContext as useLexicalComposerContext9 } from "@lexical/react/LexicalComposerContext";
6407
+ // src/plugins/TableControlsPlugin.tsx
6408
+ import { useCallback as useCallback7 } from "react";
6409
+ import { useLexicalComposerContext as useLexicalComposerContext11 } from "@lexical/react/LexicalComposerContext";
6211
6410
  import { useLexicalEditable as useLexicalEditable2 } from "@lexical/react/useLexicalEditable";
6212
6411
 
6412
+ // src/components/TableRail.tsx
6413
+ import { useCallback as useCallback4, useRef as useRef7, useState as useState6 } from "react";
6414
+ import { jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
6415
+ var TABLE_RAIL_WIDTH = { row: 28, column: 24 };
6416
+ var NAMES = { row: "row", column: "column" };
6417
+ function TableRail({
6418
+ axis,
6419
+ box,
6420
+ lanes,
6421
+ current,
6422
+ insertable,
6423
+ canDelete,
6424
+ onInsert,
6425
+ onDelete
6426
+ }) {
6427
+ const rail = useRef7(null);
6428
+ const [pointer, setPointer] = useState6(null);
6429
+ const width = TABLE_RAIL_WIDTH[axis];
6430
+ const vertical = axis === "row";
6431
+ const boundary = useCallback4(
6432
+ (index) => {
6433
+ if (index < lanes.length) return lanes[index].start;
6434
+ const last = lanes[lanes.length - 1];
6435
+ return last ? last.start + last.size : 0;
6436
+ },
6437
+ [lanes]
6438
+ );
6439
+ const onPointerMove = useCallback4(
6440
+ (event) => {
6441
+ const rect = rail.current?.getBoundingClientRect();
6442
+ if (!rect) return;
6443
+ setPointer(vertical ? event.clientY - rect.top : event.clientX - rect.left);
6444
+ },
6445
+ [vertical]
6446
+ );
6447
+ if (lanes.length === 0) return null;
6448
+ const handle = (() => {
6449
+ if (pointer === null) return { mode: "insert", index: lanes.length };
6450
+ let nearest = lanes.length;
6451
+ let distance = Number.POSITIVE_INFINITY;
6452
+ for (const index of insertable) {
6453
+ const d = Math.abs(boundary(index) - pointer);
6454
+ if (d < distance) {
6455
+ distance = d;
6456
+ nearest = index;
6457
+ }
6458
+ }
6459
+ const under = lanes.findIndex((lane2) => pointer >= lane2.start && pointer < lane2.start + lane2.size);
6460
+ const lane = lanes[under];
6461
+ const threshold = lane ? Math.min(10, lane.size * 0.3) : 0;
6462
+ if (!canDelete || under === -1 || distance <= threshold) return { mode: "insert", index: nearest };
6463
+ return { mode: "delete", index: under };
6464
+ })();
6465
+ const at = (value) => vertical ? { top: value } : { left: value };
6466
+ const span = (lane) => vertical ? { top: lane.start + 3, height: Math.max(4, lane.size - 6) } : { left: lane.start + 3, width: Math.max(4, lane.size - 6) };
6467
+ const across = vertical ? { left: width, width: box.width } : { top: width, height: box.height };
6468
+ const marker = lanes[Math.min(current, lanes.length - 1)];
6469
+ const isAppend = handle.mode === "insert" && handle.index === lanes.length;
6470
+ const name = NAMES[axis];
6471
+ const label = handle.mode === "delete" ? `Delete ${name} ${handle.index + 1}` : isAppend ? `Add ${name}` : `Insert ${name} before ${name} ${handle.index + 1}`;
6472
+ const previewStyle = handle.mode === "insert" ? { ...at(boundary(handle.index)), ...across } : vertical ? { top: lanes[handle.index].start, height: lanes[handle.index].size, ...across } : { left: lanes[handle.index].start, width: lanes[handle.index].size, ...across };
6473
+ return /* @__PURE__ */ jsxs11(
6474
+ "div",
6475
+ {
6476
+ ref: rail,
6477
+ className: `zui-table-rail is-${axis}`,
6478
+ style: vertical ? { top: box.top, left: box.left - width, width, height: box.height } : { top: box.top - width, left: box.left, width: box.width, height: width },
6479
+ onPointerMove,
6480
+ onPointerLeave: () => setPointer(null),
6481
+ children: [
6482
+ /* @__PURE__ */ jsx14("div", { className: "zui-table-rail-marker", style: span(marker), "aria-hidden": true }),
6483
+ /* @__PURE__ */ jsx14(
6484
+ "button",
6485
+ {
6486
+ type: "button",
6487
+ className: `zui-table-rail-handle is-${handle.mode} ${pointer === null ? "is-resting" : ""}`,
6488
+ style: at(
6489
+ handle.mode === "insert" ? boundary(handle.index) : lanes[handle.index].start + lanes[handle.index].size / 2
6490
+ ),
6491
+ title: label,
6492
+ "aria-label": label,
6493
+ onMouseDown: (e) => e.preventDefault(),
6494
+ onClick: () => handle.mode === "insert" ? onInsert(handle.index) : onDelete(handle.index),
6495
+ children: /* @__PURE__ */ jsx14("svg", { viewBox: "0 0 12 12", width: "12", height: "12", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", children: handle.mode === "insert" ? /* @__PURE__ */ jsx14("path", { d: "M6 2.5v7M2.5 6h7" }) : /* @__PURE__ */ jsx14("path", { d: "M2.5 6h7" }) })
6496
+ }
6497
+ ),
6498
+ /* @__PURE__ */ jsx14("div", { className: `zui-table-rail-preview is-${handle.mode}`, style: previewStyle, "aria-hidden": true })
6499
+ ]
6500
+ }
6501
+ );
6502
+ }
6503
+
6213
6504
  // src/useMarkdownEditor.ts
6214
- import { useCallback as useCallback4, useEffect as useEffect10, useRef as useRef7, useState as useState6 } from "react";
6505
+ import { useCallback as useCallback5, useEffect as useEffect11, useRef as useRef8, useState as useState7 } from "react";
6215
6506
  import {
6216
- $getNodeByKey as $getNodeByKey4,
6217
- $getSelection as $getSelection4,
6218
- $isRangeSelection as $isRangeSelection4,
6507
+ $getNodeByKey as $getNodeByKey5,
6508
+ $getSelection as $getSelection6,
6509
+ $isRangeSelection as $isRangeSelection6,
6219
6510
  CAN_REDO_COMMAND,
6220
6511
  CAN_UNDO_COMMAND,
6221
6512
  COMMAND_PRIORITY_LOW as COMMAND_PRIORITY_LOW2,
@@ -6223,7 +6514,7 @@ import {
6223
6514
  REDO_COMMAND,
6224
6515
  UNDO_COMMAND
6225
6516
  } from "lexical";
6226
- import { useLexicalComposerContext as useLexicalComposerContext8 } from "@lexical/react/LexicalComposerContext";
6517
+ import { useLexicalComposerContext as useLexicalComposerContext9 } from "@lexical/react/LexicalComposerContext";
6227
6518
  import { INSERT_TABLE_COMMAND } from "@lexical/table";
6228
6519
  import { $insertNodeToNearestRoot, mergeRegister as mergeRegister2 } from "@lexical/utils";
6229
6520
  var TRACKED_FORMATS = [
@@ -6235,29 +6526,31 @@ var TRACKED_FORMATS = [
6235
6526
  ];
6236
6527
  function $readDrawingWidth(key) {
6237
6528
  if (key === null) return null;
6238
- const node = $getNodeByKey4(key);
6529
+ const node = $getNodeByKey5(key);
6239
6530
  return $isDrawingNode(node) ? node.getData().width ?? "full" : null;
6240
6531
  }
6241
6532
  function useMarkdownEditor() {
6242
- const [editor] = useLexicalComposerContext8();
6533
+ const [editor] = useLexicalComposerContext9();
6243
6534
  const { defaultBlockWidth } = useEditorContext();
6244
- const [activeFormats, setActiveFormats] = useState6(
6535
+ const [activeFormats, setActiveFormats] = useState7(
6245
6536
  /* @__PURE__ */ new Set()
6246
6537
  );
6247
- const [canUndo, setCanUndo] = useState6(false);
6248
- const [canRedo, setCanRedo] = useState6(false);
6249
- const [tableSettings, setTableSettingsState] = useState6(null);
6250
- const activeDrawingRef = useRef7(null);
6251
- const [drawingWidth, setDrawingWidth] = useState6(null);
6252
- useEffect10(
6538
+ const [canUndo, setCanUndo] = useState7(false);
6539
+ const [canRedo, setCanRedo] = useState7(false);
6540
+ const [tableSettings, setTableSettingsState] = useState7(null);
6541
+ const [tableCell, setTableCell] = useState7(null);
6542
+ const activeDrawingRef = useRef8(null);
6543
+ const [drawingWidth, setDrawingWidth] = useState7(null);
6544
+ useEffect11(
6253
6545
  () => mergeRegister2(
6254
6546
  editor.registerUpdateListener(({ editorState }) => {
6255
6547
  editorState.read(() => {
6256
6548
  const table = $getSelectedTable();
6257
6549
  setTableSettingsState(table ? $getTableSettings(table) : null);
6550
+ setTableCell(table ? $getTableCellPosition() : null);
6258
6551
  setDrawingWidth($readDrawingWidth(activeDrawingRef.current));
6259
- const selection = $getSelection4();
6260
- if (!$isRangeSelection4(selection)) {
6552
+ const selection = $getSelection6();
6553
+ if (!$isRangeSelection6(selection)) {
6261
6554
  setActiveFormats(/* @__PURE__ */ new Set());
6262
6555
  return;
6263
6556
  }
@@ -6296,13 +6589,13 @@ function useMarkdownEditor() {
6296
6589
  ),
6297
6590
  [editor]
6298
6591
  );
6299
- const toggleFormat = useCallback4(
6592
+ const toggleFormat = useCallback5(
6300
6593
  (format) => {
6301
6594
  editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
6302
6595
  },
6303
6596
  [editor]
6304
6597
  );
6305
- const insertTable = useCallback4(
6598
+ const insertTable = useCallback5(
6306
6599
  ({
6307
6600
  rows = 3,
6308
6601
  columns = 3,
@@ -6324,7 +6617,7 @@ function useMarkdownEditor() {
6324
6617
  },
6325
6618
  [editor, defaultBlockWidth.table]
6326
6619
  );
6327
- const insertDrawing = useCallback4(
6620
+ const insertDrawing = useCallback5(
6328
6621
  ({ width = defaultBlockWidth.drawing } = {}) => {
6329
6622
  editor.update(() => {
6330
6623
  const data = width === void 0 ? EMPTY_DRAWING : { version: 2, canvasHeight: EMPTY_DRAWING.canvasHeight, width, shapes: [] };
@@ -6333,7 +6626,7 @@ function useMarkdownEditor() {
6333
6626
  },
6334
6627
  [editor, defaultBlockWidth.drawing]
6335
6628
  );
6336
- const updateTableSettings = useCallback4(
6629
+ const updateTableSettings = useCallback5(
6337
6630
  (settings) => {
6338
6631
  editor.update(() => {
6339
6632
  const table = $getSelectedTable();
@@ -6342,15 +6635,45 @@ function useMarkdownEditor() {
6342
6635
  },
6343
6636
  [editor]
6344
6637
  );
6345
- const setTableWidth = useCallback4(
6638
+ const setTableWidth = useCallback5(
6346
6639
  (width) => updateTableSettings({ width }),
6347
6640
  [updateTableSettings]
6348
6641
  );
6349
- const setTableDensity = useCallback4(
6642
+ const setTableDensity = useCallback5(
6350
6643
  (density) => updateTableSettings({ density }),
6351
6644
  [updateTableSettings]
6352
6645
  );
6353
- const setBlockWidth = useCallback4(
6646
+ const insertTableRow = useCallback5(
6647
+ (position = "below") => {
6648
+ editor.update(() => {
6649
+ const table = $getSelectedTable();
6650
+ if (table) $insertTableRowNear(table, position);
6651
+ });
6652
+ },
6653
+ [editor]
6654
+ );
6655
+ const deleteTableRow = useCallback5(() => {
6656
+ editor.update(() => {
6657
+ const table = $getSelectedTable();
6658
+ if (table) $deleteSelectedTableRow(table);
6659
+ });
6660
+ }, [editor]);
6661
+ const insertTableColumn = useCallback5(
6662
+ (position = "after") => {
6663
+ editor.update(() => {
6664
+ const table = $getSelectedTable();
6665
+ if (table) $insertTableColumnNear(table, position);
6666
+ });
6667
+ },
6668
+ [editor]
6669
+ );
6670
+ const deleteTableColumn = useCallback5(() => {
6671
+ editor.update(() => {
6672
+ const table = $getSelectedTable();
6673
+ if (table) $deleteSelectedTableColumn(table);
6674
+ });
6675
+ }, [editor]);
6676
+ const setBlockWidth = useCallback5(
6354
6677
  (width) => {
6355
6678
  const key = activeDrawingRef.current;
6356
6679
  if (key === null) {
@@ -6358,7 +6681,7 @@ function useMarkdownEditor() {
6358
6681
  return;
6359
6682
  }
6360
6683
  editor.update(() => {
6361
- const node = $getNodeByKey4(key);
6684
+ const node = $getNodeByKey5(key);
6362
6685
  if (!$isDrawingNode(node)) return;
6363
6686
  const { width: _previous, ...data } = node.getData();
6364
6687
  node.setData(width === "full" ? data : { ...data, width });
@@ -6366,10 +6689,10 @@ function useMarkdownEditor() {
6366
6689
  },
6367
6690
  [editor, updateTableSettings]
6368
6691
  );
6369
- const undo = useCallback4(() => {
6692
+ const undo = useCallback5(() => {
6370
6693
  editor.dispatchCommand(UNDO_COMMAND, void 0);
6371
6694
  }, [editor]);
6372
- const redo = useCallback4(() => {
6695
+ const redo = useCallback5(() => {
6373
6696
  editor.dispatchCommand(REDO_COMMAND, void 0);
6374
6697
  }, [editor]);
6375
6698
  return {
@@ -6384,6 +6707,11 @@ function useMarkdownEditor() {
6384
6707
  setTableWidth,
6385
6708
  tableDensity: tableSettings?.density ?? null,
6386
6709
  setTableDensity,
6710
+ tableCell,
6711
+ insertTableRow,
6712
+ deleteTableRow,
6713
+ insertTableColumn,
6714
+ deleteTableColumn,
6387
6715
  canUndo,
6388
6716
  canRedo,
6389
6717
  undo,
@@ -6392,23 +6720,23 @@ function useMarkdownEditor() {
6392
6720
  }
6393
6721
 
6394
6722
  // src/components/Toolbar.tsx
6395
- import { Fragment as Fragment5, jsx as jsx14, jsxs as jsxs11 } from "react/jsx-runtime";
6723
+ import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
6396
6724
  function Toolbar({ children, className }) {
6397
- return /* @__PURE__ */ jsx14(
6725
+ return /* @__PURE__ */ jsx15(
6398
6726
  "div",
6399
6727
  {
6400
6728
  className: `zui-text-editor-toolbar ${className ?? ""}`,
6401
6729
  role: "toolbar",
6402
- children: children ?? /* @__PURE__ */ jsxs11(Fragment5, { children: [
6403
- /* @__PURE__ */ jsx14(FormatButtons, {}),
6404
- /* @__PURE__ */ jsx14(ToolbarDivider, {}),
6405
- /* @__PURE__ */ jsx14(InsertButtons, {})
6730
+ children: children ?? /* @__PURE__ */ jsxs12(Fragment5, { children: [
6731
+ /* @__PURE__ */ jsx15(FormatButtons, {}),
6732
+ /* @__PURE__ */ jsx15(ToolbarDivider, {}),
6733
+ /* @__PURE__ */ jsx15(InsertButtons, {})
6406
6734
  ] })
6407
6735
  }
6408
6736
  );
6409
6737
  }
6410
6738
  function ToolbarDivider() {
6411
- return /* @__PURE__ */ jsx14("div", { className: "zui-text-editor-toolbar-divider" });
6739
+ return /* @__PURE__ */ jsx15("div", { className: "zui-text-editor-toolbar-divider" });
6412
6740
  }
6413
6741
  function ToolbarButton({
6414
6742
  label,
@@ -6418,7 +6746,7 @@ function ToolbarButton({
6418
6746
  disabled = false,
6419
6747
  className
6420
6748
  }) {
6421
- return /* @__PURE__ */ jsx14(
6749
+ return /* @__PURE__ */ jsx15(
6422
6750
  "button",
6423
6751
  {
6424
6752
  type: "button",
@@ -6434,7 +6762,7 @@ function ToolbarButton({
6434
6762
  );
6435
6763
  }
6436
6764
  function Icon2({ children, strokeWidth = 1.5 }) {
6437
- return /* @__PURE__ */ jsx14(
6765
+ return /* @__PURE__ */ jsx15(
6438
6766
  "svg",
6439
6767
  {
6440
6768
  viewBox: "0 0 20 20",
@@ -6453,27 +6781,27 @@ var FORMAT_BUTTONS = [
6453
6781
  {
6454
6782
  format: "bold",
6455
6783
  label: "Bold",
6456
- icon: /* @__PURE__ */ jsx14(Icon2, { strokeWidth: 1.8, children: /* @__PURE__ */ jsx14("path", { d: "M6 3.5h5a3 3 0 0 1 0 6H6zm0 6h6a3 3 0 0 1 0 6H6z" }) })
6784
+ icon: /* @__PURE__ */ jsx15(Icon2, { strokeWidth: 1.8, children: /* @__PURE__ */ jsx15("path", { d: "M6 3.5h5a3 3 0 0 1 0 6H6zm0 6h6a3 3 0 0 1 0 6H6z" }) })
6457
6785
  },
6458
6786
  {
6459
6787
  format: "italic",
6460
6788
  label: "Italic",
6461
- icon: /* @__PURE__ */ jsx14(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx14("path", { d: "M8.5 3.5h6M5.5 16.5h6M11.5 3.5l-3 13" }) })
6789
+ icon: /* @__PURE__ */ jsx15(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx15("path", { d: "M8.5 3.5h6M5.5 16.5h6M11.5 3.5l-3 13" }) })
6462
6790
  },
6463
6791
  {
6464
6792
  format: "strikethrough",
6465
6793
  label: "Strikethrough",
6466
- icon: /* @__PURE__ */ jsx14(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx14("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" }) })
6794
+ icon: /* @__PURE__ */ jsx15(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx15("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" }) })
6467
6795
  },
6468
6796
  {
6469
6797
  format: "code",
6470
6798
  label: "Inline code",
6471
- icon: /* @__PURE__ */ jsx14(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx14("path", { d: "M7.5 6L4 10l3.5 4M12.5 6L16 10l-3.5 4" }) })
6799
+ icon: /* @__PURE__ */ jsx15(Icon2, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx15("path", { d: "M7.5 6L4 10l3.5 4M12.5 6L16 10l-3.5 4" }) })
6472
6800
  }
6473
6801
  ];
6474
6802
  function FormatButtons() {
6475
6803
  const { activeFormats, toggleFormat } = useMarkdownEditor();
6476
- return /* @__PURE__ */ jsx14(Fragment5, { children: FORMAT_BUTTONS.map(({ format, label, icon }) => /* @__PURE__ */ jsx14(
6804
+ return /* @__PURE__ */ jsx15(Fragment5, { children: FORMAT_BUTTONS.map(({ format, label, icon }) => /* @__PURE__ */ jsx15(
6477
6805
  ToolbarButton,
6478
6806
  {
6479
6807
  label,
@@ -6486,36 +6814,36 @@ function FormatButtons() {
6486
6814
  }
6487
6815
  function InsertButtons() {
6488
6816
  const { insertTable, insertDrawing } = useMarkdownEditor();
6489
- return /* @__PURE__ */ jsxs11(Fragment5, { children: [
6490
- /* @__PURE__ */ jsx14(ToolbarButton, { label: "Insert table", onClick: () => insertTable(), children: /* @__PURE__ */ jsxs11(Icon2, { children: [
6491
- /* @__PURE__ */ jsx14("rect", { x: "3", y: "3.5", width: "14", height: "13", rx: "1.5" }),
6492
- /* @__PURE__ */ jsx14("path", { d: "M3 8h14M8 8v8.5M13 8v8.5" })
6817
+ return /* @__PURE__ */ jsxs12(Fragment5, { children: [
6818
+ /* @__PURE__ */ jsx15(ToolbarButton, { label: "Insert table", onClick: () => insertTable(), children: /* @__PURE__ */ jsxs12(Icon2, { children: [
6819
+ /* @__PURE__ */ jsx15("rect", { x: "3", y: "3.5", width: "14", height: "13", rx: "1.5" }),
6820
+ /* @__PURE__ */ jsx15("path", { d: "M3 8h14M8 8v8.5M13 8v8.5" })
6493
6821
  ] }) }),
6494
- /* @__PURE__ */ jsx14(ToolbarButton, { label: "Insert drawing", onClick: insertDrawing, children: /* @__PURE__ */ jsxs11(Icon2, { children: [
6495
- /* @__PURE__ */ jsx14("rect", { x: "3", y: "5", width: "8", height: "6", rx: "1.5" }),
6496
- /* @__PURE__ */ jsx14("path", { d: "M13.5 8h3M14.5 6.5L17.5 8l-3 1.5" }),
6497
- /* @__PURE__ */ jsx14("ellipse", { cx: "13", cy: "14.5", rx: "4", ry: "2.8" })
6822
+ /* @__PURE__ */ jsx15(ToolbarButton, { label: "Insert drawing", onClick: insertDrawing, children: /* @__PURE__ */ jsxs12(Icon2, { children: [
6823
+ /* @__PURE__ */ jsx15("rect", { x: "3", y: "5", width: "8", height: "6", rx: "1.5" }),
6824
+ /* @__PURE__ */ jsx15("path", { d: "M13.5 8h3M14.5 6.5L17.5 8l-3 1.5" }),
6825
+ /* @__PURE__ */ jsx15("ellipse", { cx: "13", cy: "14.5", rx: "4", ry: "2.8" })
6498
6826
  ] }) })
6499
6827
  ] });
6500
6828
  }
6501
6829
  function HistoryButtons() {
6502
6830
  const { canUndo, canRedo, undo, redo } = useMarkdownEditor();
6503
- return /* @__PURE__ */ jsxs11(Fragment5, { children: [
6504
- /* @__PURE__ */ jsx14(ToolbarButton, { label: "Undo", onClick: undo, disabled: !canUndo, children: /* @__PURE__ */ jsxs11(Icon2, { children: [
6505
- /* @__PURE__ */ jsx14("path", { d: "M7 6L3.5 9.5 7 13" }),
6506
- /* @__PURE__ */ jsx14("path", { d: "M3.5 9.5H12a4 4 0 0 1 0 8h-1" })
6831
+ return /* @__PURE__ */ jsxs12(Fragment5, { children: [
6832
+ /* @__PURE__ */ jsx15(ToolbarButton, { label: "Undo", onClick: undo, disabled: !canUndo, children: /* @__PURE__ */ jsxs12(Icon2, { children: [
6833
+ /* @__PURE__ */ jsx15("path", { d: "M7 6L3.5 9.5 7 13" }),
6834
+ /* @__PURE__ */ jsx15("path", { d: "M3.5 9.5H12a4 4 0 0 1 0 8h-1" })
6507
6835
  ] }) }),
6508
- /* @__PURE__ */ jsx14(ToolbarButton, { label: "Redo", onClick: redo, disabled: !canRedo, children: /* @__PURE__ */ jsxs11(Icon2, { children: [
6509
- /* @__PURE__ */ jsx14("path", { d: "M13 6l3.5 3.5L13 13" }),
6510
- /* @__PURE__ */ jsx14("path", { d: "M16.5 9.5H8a4 4 0 0 0 0 8h1" })
6836
+ /* @__PURE__ */ jsx15(ToolbarButton, { label: "Redo", onClick: redo, disabled: !canRedo, children: /* @__PURE__ */ jsxs12(Icon2, { children: [
6837
+ /* @__PURE__ */ jsx15("path", { d: "M13 6l3.5 3.5L13 13" }),
6838
+ /* @__PURE__ */ jsx15("path", { d: "M16.5 9.5H8a4 4 0 0 0 0 8h1" })
6511
6839
  ] }) })
6512
6840
  ] });
6513
6841
  }
6514
6842
 
6515
- // src/plugins/TableSettingsPlugin.tsx
6516
- import { jsx as jsx15 } from "react/jsx-runtime";
6843
+ // src/components/TableSettingsToolbar.tsx
6844
+ import { jsx as jsx16 } from "react/jsx-runtime";
6517
6845
  function Icon3({ children }) {
6518
- return /* @__PURE__ */ jsx15(
6846
+ return /* @__PURE__ */ jsx16(
6519
6847
  "svg",
6520
6848
  {
6521
6849
  viewBox: "0 0 20 20",
@@ -6530,32 +6858,66 @@ function Icon3({ children }) {
6530
6858
  }
6531
6859
  );
6532
6860
  }
6533
- function TableSettingsPlugin() {
6534
- const [editor] = useLexicalComposerContext9();
6535
- const isEditable = useLexicalEditable2();
6536
- const [anchor, setAnchor] = useState7(null);
6537
- const [settings, setSettings] = useState7(null);
6538
- const sync = useCallback5(() => {
6861
+ function TableSettingsToolbar({ settings, style, onSettings }) {
6862
+ return /* @__PURE__ */ jsx16("div", { className: "zui-table-settings", role: "toolbar", "aria-label": "Table settings", style, children: LAYOUT_OPTIONS.map(({ preset, label, icon, width, density }) => /* @__PURE__ */ jsx16(
6863
+ ToolbarButton,
6864
+ {
6865
+ label,
6866
+ active: layoutPreset(settings.width) === preset,
6867
+ onClick: () => onSettings({ width, density }),
6868
+ children: /* @__PURE__ */ jsx16(Icon3, { children: icon })
6869
+ },
6870
+ preset
6871
+ )) });
6872
+ }
6873
+
6874
+ // src/plugins/useSelectedTable.ts
6875
+ import { useCallback as useCallback6, useEffect as useEffect12, useState as useState8 } from "react";
6876
+ import { useLexicalComposerContext as useLexicalComposerContext10 } from "@lexical/react/LexicalComposerContext";
6877
+ function measure(element, main) {
6878
+ const rect = element.getBoundingClientRect();
6879
+ const mainRect = main.getBoundingClientRect();
6880
+ const rowElements = Array.from(
6881
+ element.querySelectorAll(":scope > tbody > tr, :scope > tr")
6882
+ );
6883
+ const rows = rowElements.map((row) => {
6884
+ const r = row.getBoundingClientRect();
6885
+ return { start: r.top - rect.top, size: r.height };
6886
+ });
6887
+ const columns = Array.from(rowElements[0]?.children ?? []).map((cell) => {
6888
+ const r = cell.getBoundingClientRect();
6889
+ return { start: r.left - rect.left, size: r.width };
6890
+ });
6891
+ return {
6892
+ box: {
6893
+ top: rect.top - mainRect.top,
6894
+ left: rect.left - mainRect.left,
6895
+ right: mainRect.right - rect.right,
6896
+ width: rect.width,
6897
+ height: rect.height
6898
+ },
6899
+ rows,
6900
+ columns
6901
+ };
6902
+ }
6903
+ function useSelectedTable() {
6904
+ const [editor] = useLexicalComposerContext10();
6905
+ const [selected, setSelected] = useState8(null);
6906
+ const sync = useCallback6(() => {
6539
6907
  const table = editor.getEditorState().read(() => {
6540
6908
  const node = $getSelectedTable();
6541
- return node ? { key: node.getKey(), settings: $getTableSettings(node) } : null;
6909
+ const position = $getTableCellPosition();
6910
+ return node && position ? { key: node.getKey(), settings: $getTableSettings(node), position } : null;
6542
6911
  });
6543
6912
  const element = table ? editor.getElementByKey(table.key) : null;
6544
6913
  const main = editor.getRootElement()?.parentElement;
6545
6914
  if (!table || !element || !main) {
6546
- setAnchor(null);
6547
- setSettings(null);
6915
+ setSelected(null);
6548
6916
  return;
6549
6917
  }
6550
- const rect = element.getBoundingClientRect();
6551
- const mainRect = main.getBoundingClientRect();
6552
- setAnchor({
6553
- top: rect.top - mainRect.top,
6554
- right: mainRect.right - rect.right + 8
6555
- });
6556
- setSettings(table.settings);
6918
+ setSelected({ ...table, ...measure(element, main) });
6557
6919
  }, [editor]);
6558
- useEffect11(() => {
6920
+ useEffect12(() => {
6559
6921
  sync();
6560
6922
  const unregister = editor.registerUpdateListener(sync);
6561
6923
  const rootElement = editor.getRootElement();
@@ -6566,39 +6928,79 @@ function TableSettingsPlugin() {
6566
6928
  observer?.disconnect();
6567
6929
  };
6568
6930
  }, [editor, sync]);
6569
- const update = useCallback5(
6570
- (next) => {
6931
+ const key = selected?.key ?? null;
6932
+ useEffect12(() => {
6933
+ if (key === null || typeof ResizeObserver === "undefined") return;
6934
+ const element = editor.getElementByKey(key);
6935
+ if (!element) return;
6936
+ const observer = new ResizeObserver(sync);
6937
+ observer.observe(element);
6938
+ return () => observer.disconnect();
6939
+ }, [editor, key, sync]);
6940
+ return selected;
6941
+ }
6942
+
6943
+ // src/plugins/TableControlsPlugin.tsx
6944
+ import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
6945
+ function TableControlsPlugin() {
6946
+ const [editor] = useLexicalComposerContext11();
6947
+ const isEditable = useLexicalEditable2();
6948
+ const table = useSelectedTable();
6949
+ const withTable = useCallback7(
6950
+ (fn) => {
6571
6951
  editor.update(() => {
6572
- const table = $getSelectedTable();
6573
- if (table) $setTableSettings(table, next);
6952
+ const node = $getSelectedTable();
6953
+ if (node) fn(node);
6574
6954
  });
6575
6955
  },
6576
6956
  [editor]
6577
6957
  );
6578
- if (!isEditable || !anchor || !settings) return null;
6579
- return /* @__PURE__ */ jsx15(
6580
- "div",
6581
- {
6582
- className: "zui-table-settings",
6583
- role: "toolbar",
6584
- "aria-label": "Table settings",
6585
- style: { top: anchor.top, right: anchor.right },
6586
- children: LAYOUT_OPTIONS.map(({ preset, label, icon, width, density }) => /* @__PURE__ */ jsx15(
6587
- ToolbarButton,
6588
- {
6589
- label,
6590
- active: layoutPreset(settings.width) === preset,
6591
- onClick: () => update({ width, density }),
6592
- children: /* @__PURE__ */ jsx15(Icon3, { children: icon })
6593
- },
6594
- preset
6595
- ))
6596
- }
6958
+ const updateSettings = useCallback7(
6959
+ (next) => withTable((node) => $setTableSettings(node, next)),
6960
+ [withTable]
6597
6961
  );
6962
+ if (!isEditable || !table) return null;
6963
+ const { position } = table;
6964
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
6965
+ /* @__PURE__ */ jsx17(
6966
+ TableSettingsToolbar,
6967
+ {
6968
+ settings: table.settings,
6969
+ style: { top: table.box.top - TABLE_RAIL_WIDTH.column, right: table.box.right },
6970
+ onSettings: updateSettings
6971
+ }
6972
+ ),
6973
+ /* @__PURE__ */ jsx17(
6974
+ TableRail,
6975
+ {
6976
+ axis: "row",
6977
+ box: table.box,
6978
+ lanes: table.rows,
6979
+ current: position.row,
6980
+ insertable: insertableRowIndices(position),
6981
+ canDelete: canDeleteRow(position),
6982
+ onInsert: (index) => withTable((node) => $insertTableRowAt(node, index, position.column)),
6983
+ onDelete: (index) => withTable((node) => $deleteTableRowAt(node, index, position.column))
6984
+ }
6985
+ ),
6986
+ /* @__PURE__ */ jsx17(
6987
+ TableRail,
6988
+ {
6989
+ axis: "column",
6990
+ box: table.box,
6991
+ lanes: table.columns,
6992
+ current: position.column,
6993
+ insertable: insertableColumnIndices(position),
6994
+ canDelete: canDeleteColumn(position),
6995
+ onInsert: (index) => withTable((node) => $insertTableColumnAt(node, index, position.row)),
6996
+ onDelete: (index) => withTable((node) => $deleteTableColumnAt(node, index, position.row))
6997
+ }
6998
+ )
6999
+ ] });
6598
7000
  }
6599
7001
 
6600
7002
  // src/EditorContent.tsx
6601
- import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
7003
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
6602
7004
  function EditorContent({
6603
7005
  placeholder = "Start writing...",
6604
7006
  foldable = true,
@@ -6606,7 +7008,7 @@ function EditorContent({
6606
7008
  }) {
6607
7009
  const { mode, readOnly, autoFocus, rawValue, onRawChange } = useEditorContext();
6608
7010
  if (mode === "edit-raw") {
6609
- return /* @__PURE__ */ jsx16(
7011
+ return /* @__PURE__ */ jsx18(
6610
7012
  "textarea",
6611
7013
  {
6612
7014
  className: "zui-text-editor-textarea",
@@ -6619,36 +7021,36 @@ function EditorContent({
6619
7021
  }
6620
7022
  );
6621
7023
  }
6622
- return /* @__PURE__ */ jsxs12("div", { className: "zui-text-editor-body", children: [
6623
- /* @__PURE__ */ jsxs12("div", { className: "zui-text-editor-main", children: [
6624
- /* @__PURE__ */ jsx16(
7024
+ return /* @__PURE__ */ jsxs14("div", { className: "zui-text-editor-body", children: [
7025
+ /* @__PURE__ */ jsxs14("div", { className: "zui-text-editor-main", children: [
7026
+ /* @__PURE__ */ jsx18(
6625
7027
  RichTextPlugin,
6626
7028
  {
6627
- contentEditable: /* @__PURE__ */ jsx16(
7029
+ contentEditable: /* @__PURE__ */ jsx18(
6628
7030
  ContentEditable,
6629
7031
  {
6630
7032
  className: "zui-text-editor-content",
6631
7033
  "aria-placeholder": placeholder,
6632
- placeholder: /* @__PURE__ */ jsx16("div", { className: "zui-text-editor-placeholder", children: placeholder })
7034
+ placeholder: /* @__PURE__ */ jsx18("div", { className: "zui-text-editor-placeholder", children: placeholder })
6633
7035
  }
6634
7036
  ),
6635
7037
  ErrorBoundary: LexicalErrorBoundary
6636
7038
  }
6637
7039
  ),
6638
- foldable && /* @__PURE__ */ jsx16(FoldingPlugin, {}),
6639
- /* @__PURE__ */ jsx16(TableSettingsPlugin, {})
7040
+ foldable && /* @__PURE__ */ jsx18(FoldingPlugin, {}),
7041
+ /* @__PURE__ */ jsx18(TableControlsPlugin, {})
6640
7042
  ] }),
6641
7043
  children
6642
7044
  ] });
6643
7045
  }
6644
7046
 
6645
7047
  // src/plugins/OutlinePlugin.tsx
6646
- import { useCallback as useCallback6, useEffect as useEffect12, useState as useState8 } from "react";
6647
- import { useLexicalComposerContext as useLexicalComposerContext10 } from "@lexical/react/LexicalComposerContext";
7048
+ import { useCallback as useCallback8, useEffect as useEffect13, useState as useState9 } from "react";
7049
+ import { useLexicalComposerContext as useLexicalComposerContext12 } from "@lexical/react/LexicalComposerContext";
6648
7050
  import {
6649
7051
  TableOfContentsPlugin
6650
7052
  } from "@lexical/react/LexicalTableOfContentsPlugin";
6651
- import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
7053
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
6652
7054
  var INDENT_PER_LEVEL = {
6653
7055
  h1: 0,
6654
7056
  h2: 1,
@@ -6658,10 +7060,10 @@ var INDENT_PER_LEVEL = {
6658
7060
  h6: 5
6659
7061
  };
6660
7062
  function OutlinePlugin() {
6661
- const [editor] = useLexicalComposerContext10();
6662
- const [collapsed, setCollapsed] = useState8(false);
6663
- const [activeKey, setActiveKey] = useState8(null);
6664
- useEffect12(() => {
7063
+ const [editor] = useLexicalComposerContext12();
7064
+ const [collapsed, setCollapsed] = useState9(false);
7065
+ const [activeKey, setActiveKey] = useState9(null);
7066
+ useEffect13(() => {
6665
7067
  const rootElement = editor.getRootElement();
6666
7068
  const scroller = rootElement?.closest(".zui-text-editor");
6667
7069
  if (!rootElement || !(scroller instanceof HTMLElement)) return;
@@ -6691,7 +7093,7 @@ function OutlinePlugin() {
6691
7093
  unregister();
6692
7094
  };
6693
7095
  }, [editor]);
6694
- const scrollTo = useCallback6(
7096
+ const scrollTo = useCallback8(
6695
7097
  (key) => {
6696
7098
  editor.getEditorState().read(() => {
6697
7099
  const element = editor.getElementByKey(key);
@@ -6700,16 +7102,16 @@ function OutlinePlugin() {
6700
7102
  },
6701
7103
  [editor]
6702
7104
  );
6703
- return /* @__PURE__ */ jsx17(TableOfContentsPlugin, { children: (entries) => {
7105
+ return /* @__PURE__ */ jsx19(TableOfContentsPlugin, { children: (entries) => {
6704
7106
  for (const [key] of entries) {
6705
7107
  editor.getElementByKey(key)?.setAttribute("data-outline-key", key);
6706
7108
  }
6707
- return /* @__PURE__ */ jsxs13(
7109
+ return /* @__PURE__ */ jsxs15(
6708
7110
  "div",
6709
7111
  {
6710
7112
  className: `zui-text-editor-outline ${collapsed ? "is-collapsed" : ""}`,
6711
7113
  children: [
6712
- /* @__PURE__ */ jsx17(
7114
+ /* @__PURE__ */ jsx19(
6713
7115
  "button",
6714
7116
  {
6715
7117
  type: "button",
@@ -6718,7 +7120,7 @@ function OutlinePlugin() {
6718
7120
  "aria-label": collapsed ? "Show outline" : "Hide outline",
6719
7121
  "aria-expanded": !collapsed,
6720
7122
  onClick: () => setCollapsed((c2) => !c2),
6721
- children: /* @__PURE__ */ jsx17(
7123
+ children: /* @__PURE__ */ jsx19(
6722
7124
  "svg",
6723
7125
  {
6724
7126
  viewBox: "0 0 20 20",
@@ -6728,14 +7130,14 @@ function OutlinePlugin() {
6728
7130
  stroke: "currentColor",
6729
7131
  strokeWidth: "1.8",
6730
7132
  strokeLinecap: "round",
6731
- children: /* @__PURE__ */ jsx17("path", { d: "M4 5h12M4 10h8M4 15h10" })
7133
+ children: /* @__PURE__ */ jsx19("path", { d: "M4 5h12M4 10h8M4 15h10" })
6732
7134
  }
6733
7135
  )
6734
7136
  }
6735
7137
  ),
6736
- !collapsed && /* @__PURE__ */ jsxs13("nav", { className: "zui-text-editor-outline-list", "aria-label": "Table of contents", children: [
6737
- entries.length === 0 && /* @__PURE__ */ jsx17("div", { className: "zui-text-editor-outline-empty", children: "No headings" }),
6738
- entries.map(([key, text, tag]) => /* @__PURE__ */ jsx17(
7138
+ !collapsed && /* @__PURE__ */ jsxs15("nav", { className: "zui-text-editor-outline-list", "aria-label": "Table of contents", children: [
7139
+ entries.length === 0 && /* @__PURE__ */ jsx19("div", { className: "zui-text-editor-outline-empty", children: "No headings" }),
7140
+ entries.map(([key, text, tag]) => /* @__PURE__ */ jsx19(
6739
7141
  "button",
6740
7142
  {
6741
7143
  type: "button",
@@ -6756,11 +7158,11 @@ function OutlinePlugin() {
6756
7158
  }
6757
7159
 
6758
7160
  // src/MarkdownEditor.tsx
6759
- import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
7161
+ import { jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
6760
7162
  var DEFAULT_ITEMS = {
6761
- format: /* @__PURE__ */ jsx18(FormatButtons, {}),
6762
- insert: /* @__PURE__ */ jsx18(InsertButtons, {}),
6763
- history: /* @__PURE__ */ jsx18(HistoryButtons, {})
7163
+ format: /* @__PURE__ */ jsx20(FormatButtons, {}),
7164
+ insert: /* @__PURE__ */ jsx20(InsertButtons, {}),
7165
+ history: /* @__PURE__ */ jsx20(HistoryButtons, {})
6764
7166
  };
6765
7167
  function EditorToolbar({
6766
7168
  children,
@@ -6768,7 +7170,7 @@ function EditorToolbar({
6768
7170
  }) {
6769
7171
  const { mode, readOnly } = useEditorContext();
6770
7172
  if (mode !== "edit-md" || readOnly) return null;
6771
- return /* @__PURE__ */ jsx18(Toolbar, { className, children });
7173
+ return /* @__PURE__ */ jsx20(Toolbar, { className, children });
6772
7174
  }
6773
7175
  function MarkdownEditor({
6774
7176
  placeholder,
@@ -6777,10 +7179,10 @@ function MarkdownEditor({
6777
7179
  foldable = true,
6778
7180
  ...rootProps
6779
7181
  }) {
6780
- return /* @__PURE__ */ jsxs14(EditorRoot, { ...rootProps, children: [
6781
- toolbar === true && /* @__PURE__ */ jsx18(EditorToolbar, {}),
7182
+ return /* @__PURE__ */ jsxs16(EditorRoot, { ...rootProps, children: [
7183
+ toolbar === true && /* @__PURE__ */ jsx20(EditorToolbar, {}),
6782
7184
  typeof toolbar === "function" && toolbar(DEFAULT_ITEMS),
6783
- /* @__PURE__ */ jsx18(EditorContent, { placeholder, foldable, children: outline && /* @__PURE__ */ jsx18(OutlinePlugin, {}) })
7185
+ /* @__PURE__ */ jsx20(EditorContent, { placeholder, foldable, children: outline && /* @__PURE__ */ jsx20(OutlinePlugin, {}) })
6784
7186
  ] });
6785
7187
  }
6786
7188
  MarkdownEditor.Root = EditorRoot;
@@ -6954,10 +7356,20 @@ var DRAWING_DATA_JSON_SCHEMA = {
6954
7356
  export {
6955
7357
  $createDrawingNode,
6956
7358
  $createFrontmatterNode,
7359
+ $deleteSelectedTableColumn,
7360
+ $deleteSelectedTableRow,
7361
+ $deleteTableColumnAt,
7362
+ $deleteTableRowAt,
6957
7363
  $getSelectedTable,
7364
+ $getSelectedTableCell,
7365
+ $getTableCellPosition,
6958
7366
  $getTableDensity,
6959
7367
  $getTableSettings,
6960
7368
  $getTableWidth,
7369
+ $insertTableColumnAt,
7370
+ $insertTableColumnNear,
7371
+ $insertTableRowAt,
7372
+ $insertTableRowNear,
6961
7373
  $isDrawingNode,
6962
7374
  $isFrontmatterNode,
6963
7375
  $isTableWidthExplicit,
@@ -6998,6 +7410,8 @@ export {
6998
7410
  anchorPoint,
6999
7411
  bindEndpoints,
7000
7412
  boxOutline,
7413
+ canDeleteColumn,
7414
+ canDeleteRow,
7001
7415
  codeTokenizer,
7002
7416
  connectorPoints,
7003
7417
  drawingToMermaid,
@@ -7010,6 +7424,8 @@ export {
7010
7424
  inkAmplitude,
7011
7425
  inkFillOffset,
7012
7426
  inkStroke,
7427
+ insertableColumnIndices,
7428
+ insertableRowIndices,
7013
7429
  isBlockWidth,
7014
7430
  isDrawingSkeleton,
7015
7431
  makeBinding,