@zuilib/text-editor 0.3.0 → 0.3.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
@@ -357,6 +357,9 @@ function parseDrawingData(json) {
357
357
  return {
358
358
  version: 1,
359
359
  height: typeof raw.height === "number" && raw.height >= 80 ? raw.height : DEFAULT_DRAWING_HEIGHT,
360
+ // `full` is the default and stays implicit so existing payloads are
361
+ // serialized byte-for-byte unchanged
362
+ width: raw.width === "content" ? "content" : void 0,
360
363
  shapes
361
364
  };
362
365
  } catch {
@@ -373,6 +376,27 @@ function isValidShape(value) {
373
376
  ));
374
377
  }
375
378
 
379
+ // src/components/blockWidthOptions.tsx
380
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
381
+ var BLOCK_WIDTH_OPTIONS = [
382
+ {
383
+ width: "full",
384
+ label: "Full width",
385
+ icon: /* @__PURE__ */ jsxs(Fragment, { children: [
386
+ /* @__PURE__ */ jsx("path", { d: "M3 4v12M17 4v12" }),
387
+ /* @__PURE__ */ jsx("path", { d: "M6 10h8M8.5 7.5L6 10l2.5 2.5M11.5 7.5L14 10l-2.5 2.5" })
388
+ ] })
389
+ },
390
+ {
391
+ width: "content",
392
+ label: "Content width",
393
+ icon: /* @__PURE__ */ jsxs(Fragment, { children: [
394
+ /* @__PURE__ */ jsx("path", { d: "M3 4v12M17 4v12" }),
395
+ /* @__PURE__ */ jsx("path", { d: "M5.5 10h3M11.5 10h3M6.5 7.5L9 10l-2.5 2.5M13.5 7.5L11 10l2.5 2.5" })
396
+ ] })
397
+ }
398
+ ];
399
+
376
400
  // src/components/drawingGeometry.ts
377
401
  var BINDING_GAP = 6;
378
402
  var BINDING_TOLERANCE = 8;
@@ -615,10 +639,12 @@ function resolveBindings(shapes) {
615
639
  }
616
640
 
617
641
  // src/components/DrawingCanvas.tsx
618
- import { jsx, jsxs } from "react/jsx-runtime";
642
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
619
643
  import { createElement } from "react";
620
644
  var MIN_HEIGHT = 120;
621
645
  var MAX_HEIGHT = 900;
646
+ var MIN_CONTENT_WIDTH = 240;
647
+ var CONTENT_WIDTH_PADDING = 40;
622
648
  var SELECTION_COLOR = "#6965db";
623
649
  var CONNECTOR_FONT_SIZE = 12;
624
650
  var CONNECTOR_LABEL_MAX_WIDTH = 160;
@@ -649,7 +675,7 @@ function BoxTexts({
649
675
  opacity: 0.35,
650
676
  style: { userSelect: "none", pointerEvents: "none" }
651
677
  };
652
- return /* @__PURE__ */ jsxs("g", { children: [
678
+ return /* @__PURE__ */ jsxs2("g", { children: [
653
679
  hideField !== "label" && (shape.label ? labelLines.map((line, i) => /* @__PURE__ */ createElement(
654
680
  "text",
655
681
  {
@@ -662,7 +688,7 @@ function BoxTexts({
662
688
  opacity: 0.85
663
689
  },
664
690
  line
665
- )) : showHints && /* @__PURE__ */ jsx("text", { ...hint, x: cx, y: b.y + SMALL_FONT_SIZE + 7, fontSize: SMALL_FONT_SIZE, children: "Label" })),
691
+ )) : showHints && /* @__PURE__ */ jsx2("text", { ...hint, x: cx, y: b.y + SMALL_FONT_SIZE + 7, fontSize: SMALL_FONT_SIZE, children: "Label" })),
666
692
  hideField !== "text" && (shape.text ? mainLines.map((line, i) => /* @__PURE__ */ createElement(
667
693
  "text",
668
694
  {
@@ -673,7 +699,7 @@ function BoxTexts({
673
699
  fontSize: FONT_SIZE
674
700
  },
675
701
  line
676
- )) : showHints && /* @__PURE__ */ jsx("text", { ...hint, x: cx, y: mainStart, fontSize: FONT_SIZE, children: "Text" })),
702
+ )) : showHints && /* @__PURE__ */ jsx2("text", { ...hint, x: cx, y: mainStart, fontSize: FONT_SIZE, children: "Text" })),
677
703
  hideField !== "footer" && (shape.footer ? footerLines.map((line, i) => /* @__PURE__ */ createElement(
678
704
  "text",
679
705
  {
@@ -685,7 +711,7 @@ function BoxTexts({
685
711
  opacity: 0.65
686
712
  },
687
713
  line
688
- )) : showHints && /* @__PURE__ */ jsx("text", { ...hint, x: cx, y: b.y + b.h - 9, fontSize: SMALL_FONT_SIZE, children: "Footer" }))
714
+ )) : showHints && /* @__PURE__ */ jsx2("text", { ...hint, x: cx, y: b.y + b.h - 9, fontSize: SMALL_FONT_SIZE, children: "Footer" }))
689
715
  ] });
690
716
  }
691
717
  function ShapeView({
@@ -702,8 +728,8 @@ function ShapeView({
702
728
  switch (shape.type) {
703
729
  case "rect": {
704
730
  const b = bbox(shape);
705
- return /* @__PURE__ */ jsxs("g", { children: [
706
- /* @__PURE__ */ jsx(
731
+ return /* @__PURE__ */ jsxs2("g", { children: [
732
+ /* @__PURE__ */ jsx2(
707
733
  "rect",
708
734
  {
709
735
  ...common,
@@ -715,13 +741,13 @@ function ShapeView({
715
741
  fill: shape.fill
716
742
  }
717
743
  ),
718
- /* @__PURE__ */ jsx(BoxTexts, { shape, hideField, showHints })
744
+ /* @__PURE__ */ jsx2(BoxTexts, { shape, hideField, showHints })
719
745
  ] });
720
746
  }
721
747
  case "ellipse": {
722
748
  const b = bbox(shape);
723
- return /* @__PURE__ */ jsxs("g", { children: [
724
- /* @__PURE__ */ jsx(
749
+ return /* @__PURE__ */ jsxs2("g", { children: [
750
+ /* @__PURE__ */ jsx2(
725
751
  "ellipse",
726
752
  {
727
753
  ...common,
@@ -732,13 +758,13 @@ function ShapeView({
732
758
  fill: shape.fill
733
759
  }
734
760
  ),
735
- /* @__PURE__ */ jsx(BoxTexts, { shape, hideField, showHints })
761
+ /* @__PURE__ */ jsx2(BoxTexts, { shape, hideField, showHints })
736
762
  ] });
737
763
  }
738
764
  case "triangle":
739
765
  case "pentagon":
740
- return /* @__PURE__ */ jsxs("g", { children: [
741
- /* @__PURE__ */ jsx(
766
+ return /* @__PURE__ */ jsxs2("g", { children: [
767
+ /* @__PURE__ */ jsx2(
742
768
  "polygon",
743
769
  {
744
770
  ...common,
@@ -746,12 +772,12 @@ function ShapeView({
746
772
  fill: shape.fill
747
773
  }
748
774
  ),
749
- /* @__PURE__ */ jsx(BoxTexts, { shape, hideField, showHints })
775
+ /* @__PURE__ */ jsx2(BoxTexts, { shape, hideField, showHints })
750
776
  ] });
751
777
  case "line":
752
778
  case "arrow":
753
- return /* @__PURE__ */ jsxs("g", { children: [
754
- /* @__PURE__ */ jsx(
779
+ return /* @__PURE__ */ jsxs2("g", { children: [
780
+ /* @__PURE__ */ jsx2(
755
781
  "path",
756
782
  {
757
783
  ...common,
@@ -759,10 +785,10 @@ function ShapeView({
759
785
  fill: "none"
760
786
  }
761
787
  ),
762
- shape.text && hideField !== "text" && /* @__PURE__ */ jsx(ConnectorLabel, { shape })
788
+ shape.text && hideField !== "text" && /* @__PURE__ */ jsx2(ConnectorLabel, { shape })
763
789
  ] });
764
790
  case "text":
765
- return /* @__PURE__ */ jsx(
791
+ return /* @__PURE__ */ jsx2(
766
792
  "text",
767
793
  {
768
794
  x: shape.x,
@@ -771,7 +797,7 @@ function ShapeView({
771
797
  fontSize: FONT_SIZE,
772
798
  fontFamily: "ui-sans-serif, system-ui, sans-serif",
773
799
  style: { userSelect: "none", whiteSpace: "pre" },
774
- children: (shape.text ?? "").split("\n").map((line, i) => /* @__PURE__ */ jsx("tspan", { x: shape.x, dy: i === 0 ? 0 : FONT_SIZE * 1.35, children: line }, i))
800
+ children: (shape.text ?? "").split("\n").map((line, i) => /* @__PURE__ */ jsx2("tspan", { x: shape.x, dy: i === 0 ? 0 : FONT_SIZE * 1.35, children: line }, i))
775
801
  }
776
802
  );
777
803
  }
@@ -783,8 +809,8 @@ function ConnectorLabel({ shape }) {
783
809
  const { x: midX, y: midY } = connectorMidpoint(shape);
784
810
  const lineH = CONNECTOR_FONT_SIZE * LINE_HEIGHT;
785
811
  const startY = midY - (lines.length - 1) * lineH / 2 + CONNECTOR_FONT_SIZE * 0.35;
786
- return /* @__PURE__ */ jsxs("g", { children: [
787
- /* @__PURE__ */ jsx(
812
+ return /* @__PURE__ */ jsxs2("g", { children: [
813
+ /* @__PURE__ */ jsx2(
788
814
  "rect",
789
815
  {
790
816
  x: midX - size.w / 2 - 5,
@@ -796,7 +822,7 @@ function ConnectorLabel({ shape }) {
796
822
  opacity: 0.92
797
823
  }
798
824
  ),
799
- lines.map((line, i) => /* @__PURE__ */ jsx(
825
+ lines.map((line, i) => /* @__PURE__ */ jsx2(
800
826
  "text",
801
827
  {
802
828
  x: midX,
@@ -813,20 +839,20 @@ function ConnectorLabel({ shape }) {
813
839
  ] });
814
840
  }
815
841
  var TOOL_ICONS = {
816
- select: /* @__PURE__ */ jsx("path", { d: "M4 2l12 6.5-5.2 1.6L8 16z", fill: "currentColor", stroke: "none" }),
817
- rect: /* @__PURE__ */ jsx("rect", { x: "3", y: "4.5", width: "14", height: "11", rx: "2" }),
818
- ellipse: /* @__PURE__ */ jsx("ellipse", { cx: "10", cy: "10", rx: "7", ry: "5.5" }),
819
- triangle: /* @__PURE__ */ jsx("path", { d: "M10 3.5L17 16.5H3z", strokeLinejoin: "round" }),
820
- pentagon: /* @__PURE__ */ jsx("path", { d: "M10 3L16.8 8.1L14.2 16.2H5.8L3.2 8.1z", strokeLinejoin: "round" }),
821
- arrow: /* @__PURE__ */ jsxs("g", { children: [
822
- /* @__PURE__ */ jsx("path", { d: "M4 16L16 4" }),
823
- /* @__PURE__ */ jsx("path", { d: "M9 4h7v7" })
842
+ select: /* @__PURE__ */ jsx2("path", { d: "M4 2l12 6.5-5.2 1.6L8 16z", fill: "currentColor", stroke: "none" }),
843
+ rect: /* @__PURE__ */ jsx2("rect", { x: "3", y: "4.5", width: "14", height: "11", rx: "2" }),
844
+ ellipse: /* @__PURE__ */ jsx2("ellipse", { cx: "10", cy: "10", rx: "7", ry: "5.5" }),
845
+ triangle: /* @__PURE__ */ jsx2("path", { d: "M10 3.5L17 16.5H3z", strokeLinejoin: "round" }),
846
+ pentagon: /* @__PURE__ */ jsx2("path", { d: "M10 3L16.8 8.1L14.2 16.2H5.8L3.2 8.1z", strokeLinejoin: "round" }),
847
+ arrow: /* @__PURE__ */ jsxs2("g", { children: [
848
+ /* @__PURE__ */ jsx2("path", { d: "M4 16L16 4" }),
849
+ /* @__PURE__ */ jsx2("path", { d: "M9 4h7v7" })
824
850
  ] }),
825
- line: /* @__PURE__ */ jsx("path", { d: "M4 16L16 4" }),
826
- text: /* @__PURE__ */ jsxs("g", { children: [
827
- /* @__PURE__ */ jsx("path", { d: "M4 5V3.5h12V5" }),
828
- /* @__PURE__ */ jsx("path", { d: "M10 3.5V16.5" }),
829
- /* @__PURE__ */ jsx("path", { d: "M7 16.5h6" })
851
+ line: /* @__PURE__ */ jsx2("path", { d: "M4 16L16 4" }),
852
+ text: /* @__PURE__ */ jsxs2("g", { children: [
853
+ /* @__PURE__ */ jsx2("path", { d: "M4 5V3.5h12V5" }),
854
+ /* @__PURE__ */ jsx2("path", { d: "M10 3.5V16.5" }),
855
+ /* @__PURE__ */ jsx2("path", { d: "M7 16.5h6" })
830
856
  ] })
831
857
  };
832
858
  function bindEndpoints(shape, shapes) {
@@ -849,11 +875,24 @@ var TOOLS = [
849
875
  { tool: "line", label: "Line" },
850
876
  { tool: "text", label: "Text" }
851
877
  ];
878
+ function contentWidth(shapes) {
879
+ let right = 0;
880
+ for (const shape of shapes) {
881
+ if (isConnectorType(shape.type)) {
882
+ for (const p of connectorPoints(shape)) right = Math.max(right, p.x);
883
+ } else {
884
+ const b = bbox(shape);
885
+ right = Math.max(right, b.x + b.w);
886
+ }
887
+ }
888
+ return Math.max(MIN_CONTENT_WIDTH, Math.ceil(right + CONTENT_WIDTH_PADDING));
889
+ }
852
890
  function DrawingCanvas({ nodeKey, data }) {
853
891
  const [editor] = useLexicalComposerContext5();
854
892
  const isEditable = useLexicalEditable();
855
893
  const [shapes, setShapes] = useState(data.shapes);
856
894
  const [height, setHeight] = useState(data.height);
895
+ const [width, setWidth] = useState(data.width ?? "full");
857
896
  const [tool, setTool] = useState("select");
858
897
  const [selectedId, setSelectedId] = useState(null);
859
898
  const [editingText, setEditingText] = useState(null);
@@ -866,21 +905,25 @@ function DrawingCanvas({ nodeKey, data }) {
866
905
  shapesRef.current = shapes;
867
906
  const heightRef = useRef2(height);
868
907
  heightRef.current = height;
908
+ const widthRef = useRef2(width);
909
+ widthRef.current = width;
869
910
  useEffect5(() => {
870
911
  const incoming = serializeDrawingData(data);
871
912
  if (incoming !== lastCommittedRef.current) {
872
913
  lastCommittedRef.current = incoming;
873
914
  setShapes(data.shapes);
874
915
  setHeight(data.height);
916
+ setWidth(data.width ?? "full");
875
917
  setSelectedId(null);
876
918
  setEditingText(null);
877
919
  }
878
920
  }, [data]);
879
921
  const commit = useCallback(
880
- (nextShapes, nextHeight) => {
922
+ (nextShapes, nextHeight, nextWidth) => {
881
923
  const payload = {
882
924
  version: 1,
883
925
  height: nextHeight ?? heightRef.current,
926
+ width: (nextWidth ?? widthRef.current) === "content" ? "content" : void 0,
884
927
  shapes: nextShapes
885
928
  };
886
929
  const json = serializeDrawingData(payload);
@@ -895,6 +938,13 @@ function DrawingCanvas({ nodeKey, data }) {
895
938
  },
896
939
  [editor, nodeKey]
897
940
  );
941
+ const applyWidth = useCallback(
942
+ (next) => {
943
+ setWidth(next);
944
+ commit(shapesRef.current, void 0, next);
945
+ },
946
+ [commit]
947
+ );
898
948
  const updateShapes = useCallback(
899
949
  (updater, options) => {
900
950
  setShapes((prev) => {
@@ -1299,15 +1349,15 @@ function DrawingCanvas({ nodeKey, data }) {
1299
1349
  const editingShape = shapes.find((s) => s.id === editingText?.id) ?? null;
1300
1350
  const showFill = selectedShape != null ? isBoxType(selectedShape.type) : tool !== "select" && isBoxType(tool);
1301
1351
  const canvasCursor = tool === "select" ? "default" : tool === "text" ? "text" : "crosshair";
1302
- return /* @__PURE__ */ jsxs(
1352
+ return /* @__PURE__ */ jsxs2(
1303
1353
  "div",
1304
1354
  {
1305
- className: "zui-drawing-canvas",
1355
+ className: `zui-drawing-canvas ${width === "content" ? "is-content-width" : ""}`,
1306
1356
  tabIndex: isEditable ? 0 : void 0,
1307
1357
  onKeyDown: handleKeyDown,
1308
1358
  children: [
1309
- isEditable && /* @__PURE__ */ jsxs("div", { className: "zui-drawing-toolbar", onPointerDown: (e) => e.stopPropagation(), children: [
1310
- /* @__PURE__ */ jsx("div", { className: "zui-drawing-toolbar-group", children: TOOLS.map(({ tool: t, label }) => /* @__PURE__ */ jsx(
1359
+ isEditable && /* @__PURE__ */ jsxs2("div", { className: "zui-drawing-toolbar", onPointerDown: (e) => e.stopPropagation(), children: [
1360
+ /* @__PURE__ */ jsx2("div", { className: "zui-drawing-toolbar-group", children: TOOLS.map(({ tool: t, label }) => /* @__PURE__ */ jsx2(
1311
1361
  "button",
1312
1362
  {
1313
1363
  type: "button",
@@ -1318,7 +1368,7 @@ function DrawingCanvas({ nodeKey, data }) {
1318
1368
  setTool(t);
1319
1369
  if (t !== "select") setSelectedId(null);
1320
1370
  },
1321
- children: /* @__PURE__ */ jsx(
1371
+ children: /* @__PURE__ */ jsx2(
1322
1372
  "svg",
1323
1373
  {
1324
1374
  viewBox: "0 0 20 20",
@@ -1335,9 +1385,9 @@ function DrawingCanvas({ nodeKey, data }) {
1335
1385
  },
1336
1386
  t
1337
1387
  )) }),
1338
- /* @__PURE__ */ jsxs("div", { className: "zui-drawing-toolbar-group", children: [
1339
- /* @__PURE__ */ jsx("span", { className: "zui-drawing-swatch-label", children: "Stroke" }),
1340
- STROKE_COLORS.map((color) => /* @__PURE__ */ jsx(
1388
+ /* @__PURE__ */ jsxs2("div", { className: "zui-drawing-toolbar-group", children: [
1389
+ /* @__PURE__ */ jsx2("span", { className: "zui-drawing-swatch-label", children: "Stroke" }),
1390
+ STROKE_COLORS.map((color) => /* @__PURE__ */ jsx2(
1341
1391
  "button",
1342
1392
  {
1343
1393
  type: "button",
@@ -1350,9 +1400,9 @@ function DrawingCanvas({ nodeKey, data }) {
1350
1400
  color
1351
1401
  ))
1352
1402
  ] }),
1353
- showFill && /* @__PURE__ */ jsxs("div", { className: "zui-drawing-toolbar-group", children: [
1354
- /* @__PURE__ */ jsx("span", { className: "zui-drawing-swatch-label", children: "Fill" }),
1355
- FILL_COLORS.map((color) => /* @__PURE__ */ jsx(
1403
+ showFill && /* @__PURE__ */ jsxs2("div", { className: "zui-drawing-toolbar-group", children: [
1404
+ /* @__PURE__ */ jsx2("span", { className: "zui-drawing-swatch-label", children: "Fill" }),
1405
+ FILL_COLORS.map((color) => /* @__PURE__ */ jsx2(
1356
1406
  "button",
1357
1407
  {
1358
1408
  type: "button",
@@ -1365,8 +1415,8 @@ function DrawingCanvas({ nodeKey, data }) {
1365
1415
  color
1366
1416
  ))
1367
1417
  ] }),
1368
- selectedShape && isConnectorType(selectedShape.type) && /* @__PURE__ */ jsxs("div", { className: "zui-drawing-toolbar-group", children: [
1369
- /* @__PURE__ */ jsx(
1418
+ selectedShape && isConnectorType(selectedShape.type) && /* @__PURE__ */ jsxs2("div", { className: "zui-drawing-toolbar-group", children: [
1419
+ /* @__PURE__ */ jsx2(
1370
1420
  "button",
1371
1421
  {
1372
1422
  type: "button",
@@ -1374,7 +1424,7 @@ function DrawingCanvas({ nodeKey, data }) {
1374
1424
  "aria-label": "Straight connector",
1375
1425
  className: `zui-drawing-tool ${selectedShape.routing !== "elbow" ? "is-active" : ""}`,
1376
1426
  onClick: () => applyRouting(false),
1377
- children: /* @__PURE__ */ jsx(
1427
+ children: /* @__PURE__ */ jsx2(
1378
1428
  "svg",
1379
1429
  {
1380
1430
  viewBox: "0 0 20 20",
@@ -1384,12 +1434,12 @@ function DrawingCanvas({ nodeKey, data }) {
1384
1434
  stroke: "currentColor",
1385
1435
  strokeWidth: "1.6",
1386
1436
  strokeLinecap: "round",
1387
- children: /* @__PURE__ */ jsx("path", { d: "M4 16L16 4" })
1437
+ children: /* @__PURE__ */ jsx2("path", { d: "M4 16L16 4" })
1388
1438
  }
1389
1439
  )
1390
1440
  }
1391
1441
  ),
1392
- /* @__PURE__ */ jsx(
1442
+ /* @__PURE__ */ jsx2(
1393
1443
  "button",
1394
1444
  {
1395
1445
  type: "button",
@@ -1397,7 +1447,7 @@ function DrawingCanvas({ nodeKey, data }) {
1397
1447
  "aria-label": "Elbow connector",
1398
1448
  className: `zui-drawing-tool ${selectedShape.routing === "elbow" ? "is-active" : ""}`,
1399
1449
  onClick: () => applyRouting(true),
1400
- children: /* @__PURE__ */ jsx(
1450
+ children: /* @__PURE__ */ jsx2(
1401
1451
  "svg",
1402
1452
  {
1403
1453
  viewBox: "0 0 20 20",
@@ -1408,14 +1458,14 @@ function DrawingCanvas({ nodeKey, data }) {
1408
1458
  strokeWidth: "1.6",
1409
1459
  strokeLinecap: "round",
1410
1460
  strokeLinejoin: "round",
1411
- children: /* @__PURE__ */ jsx("path", { d: "M4 16v-6h12V4" })
1461
+ children: /* @__PURE__ */ jsx2("path", { d: "M4 16v-6h12V4" })
1412
1462
  }
1413
1463
  )
1414
1464
  }
1415
1465
  )
1416
1466
  ] }),
1417
- selectedShape?.type === "arrow" && /* @__PURE__ */ jsxs("div", { className: "zui-drawing-toolbar-group", children: [
1418
- /* @__PURE__ */ jsx(
1467
+ selectedShape?.type === "arrow" && /* @__PURE__ */ jsxs2("div", { className: "zui-drawing-toolbar-group", children: [
1468
+ /* @__PURE__ */ jsx2(
1419
1469
  "button",
1420
1470
  {
1421
1471
  type: "button",
@@ -1423,7 +1473,7 @@ function DrawingCanvas({ nodeKey, data }) {
1423
1473
  "aria-label": "One-way arrow",
1424
1474
  className: `zui-drawing-tool ${!selectedShape.bidirectional ? "is-active" : ""}`,
1425
1475
  onClick: () => applyDirection(false),
1426
- children: /* @__PURE__ */ jsx(
1476
+ children: /* @__PURE__ */ jsx2(
1427
1477
  "svg",
1428
1478
  {
1429
1479
  viewBox: "0 0 20 20",
@@ -1434,12 +1484,12 @@ function DrawingCanvas({ nodeKey, data }) {
1434
1484
  strokeWidth: "1.6",
1435
1485
  strokeLinecap: "round",
1436
1486
  strokeLinejoin: "round",
1437
- children: /* @__PURE__ */ jsx("path", { d: "M3 10h13M12 5.5L16.5 10L12 14.5" })
1487
+ children: /* @__PURE__ */ jsx2("path", { d: "M3 10h13M12 5.5L16.5 10L12 14.5" })
1438
1488
  }
1439
1489
  )
1440
1490
  }
1441
1491
  ),
1442
- /* @__PURE__ */ jsx(
1492
+ /* @__PURE__ */ jsx2(
1443
1493
  "button",
1444
1494
  {
1445
1495
  type: "button",
@@ -1447,7 +1497,7 @@ function DrawingCanvas({ nodeKey, data }) {
1447
1497
  "aria-label": "Two-way arrow",
1448
1498
  className: `zui-drawing-tool ${selectedShape.bidirectional ? "is-active" : ""}`,
1449
1499
  onClick: () => applyDirection(true),
1450
- children: /* @__PURE__ */ jsx(
1500
+ children: /* @__PURE__ */ jsx2(
1451
1501
  "svg",
1452
1502
  {
1453
1503
  viewBox: "0 0 20 20",
@@ -1458,13 +1508,13 @@ function DrawingCanvas({ nodeKey, data }) {
1458
1508
  strokeWidth: "1.6",
1459
1509
  strokeLinecap: "round",
1460
1510
  strokeLinejoin: "round",
1461
- children: /* @__PURE__ */ jsx("path", { d: "M3.5 10h13M8 5.5L3.5 10L8 14.5M12 5.5L16.5 10L12 14.5" })
1511
+ children: /* @__PURE__ */ jsx2("path", { d: "M3.5 10h13M8 5.5L3.5 10L8 14.5M12 5.5L16.5 10L12 14.5" })
1462
1512
  }
1463
1513
  )
1464
1514
  }
1465
1515
  )
1466
1516
  ] }),
1467
- selectedShape && /* @__PURE__ */ jsx("div", { className: "zui-drawing-toolbar-group", children: /* @__PURE__ */ jsx(
1517
+ selectedShape && /* @__PURE__ */ jsx2("div", { className: "zui-drawing-toolbar-group", children: /* @__PURE__ */ jsx2(
1468
1518
  "button",
1469
1519
  {
1470
1520
  type: "button",
@@ -1472,7 +1522,7 @@ function DrawingCanvas({ nodeKey, data }) {
1472
1522
  "aria-label": "Delete shape",
1473
1523
  className: "zui-drawing-tool zui-drawing-tool-danger",
1474
1524
  onClick: deleteSelected,
1475
- children: /* @__PURE__ */ jsx(
1525
+ children: /* @__PURE__ */ jsx2(
1476
1526
  "svg",
1477
1527
  {
1478
1528
  viewBox: "0 0 20 20",
@@ -1482,18 +1532,48 @@ function DrawingCanvas({ nodeKey, data }) {
1482
1532
  stroke: "currentColor",
1483
1533
  strokeWidth: "1.6",
1484
1534
  strokeLinecap: "round",
1485
- children: /* @__PURE__ */ jsx("path", { d: "M4 6h12M8 6V4h4v2M6 6l1 10h6l1-10M8.5 9v4M11.5 9v4" })
1535
+ children: /* @__PURE__ */ jsx2("path", { d: "M4 6h12M8 6V4h4v2M6 6l1 10h6l1-10M8.5 9v4M11.5 9v4" })
1486
1536
  }
1487
1537
  )
1488
1538
  }
1489
- ) })
1539
+ ) }),
1540
+ /* @__PURE__ */ jsx2("div", { className: "zui-drawing-toolbar-group zui-drawing-toolbar-group-end", children: BLOCK_WIDTH_OPTIONS.map(({ width: option, label, icon }) => /* @__PURE__ */ jsx2(
1541
+ "button",
1542
+ {
1543
+ type: "button",
1544
+ title: label,
1545
+ "aria-label": label,
1546
+ "aria-pressed": width === option,
1547
+ className: `zui-drawing-tool ${width === option ? "is-active" : ""}`,
1548
+ onClick: () => applyWidth(option),
1549
+ children: /* @__PURE__ */ jsx2(
1550
+ "svg",
1551
+ {
1552
+ viewBox: "0 0 20 20",
1553
+ width: "16",
1554
+ height: "16",
1555
+ fill: "none",
1556
+ stroke: "currentColor",
1557
+ strokeWidth: "1.6",
1558
+ strokeLinecap: "round",
1559
+ strokeLinejoin: "round",
1560
+ children: icon
1561
+ }
1562
+ )
1563
+ },
1564
+ option
1565
+ )) })
1490
1566
  ] }),
1491
- /* @__PURE__ */ jsxs(
1567
+ /* @__PURE__ */ jsxs2(
1492
1568
  "svg",
1493
1569
  {
1494
1570
  ref: svgRef,
1495
1571
  className: "zui-drawing-surface",
1496
- style: { height, cursor: canvasCursor },
1572
+ style: {
1573
+ height,
1574
+ width: width === "content" ? contentWidth(shapes) : void 0,
1575
+ cursor: canvasCursor
1576
+ },
1497
1577
  onPointerDown: handleBackgroundPointerDown,
1498
1578
  onPointerMove: handlePointerMove,
1499
1579
  onPointerUp: handlePointerUp,
@@ -1515,7 +1595,7 @@ function DrawingCanvas({ nodeKey, data }) {
1515
1595
  }
1516
1596
  },
1517
1597
  children: [
1518
- shapes.map((shape) => /* @__PURE__ */ jsxs(
1598
+ shapes.map((shape) => /* @__PURE__ */ jsxs2(
1519
1599
  "g",
1520
1600
  {
1521
1601
  "data-shape-id": shape.id,
@@ -1524,7 +1604,7 @@ function DrawingCanvas({ nodeKey, data }) {
1524
1604
  },
1525
1605
  onPointerDown: (e) => handleShapePointerDown(e, shape),
1526
1606
  children: [
1527
- isConnectorType(shape.type) && /* @__PURE__ */ jsx(
1607
+ isConnectorType(shape.type) && /* @__PURE__ */ jsx2(
1528
1608
  "path",
1529
1609
  {
1530
1610
  d: connectorPath(shape),
@@ -1533,8 +1613,8 @@ function DrawingCanvas({ nodeKey, data }) {
1533
1613
  strokeWidth: 14
1534
1614
  }
1535
1615
  ),
1536
- (isBoxType(shape.type) || shape.type === "text") && /* @__PURE__ */ jsx(HitArea, { shape }),
1537
- shape.id === editingText?.id && shape.type === "text" ? null : /* @__PURE__ */ jsx(
1616
+ (isBoxType(shape.type) || shape.type === "text") && /* @__PURE__ */ jsx2(HitArea, { shape }),
1617
+ shape.id === editingText?.id && shape.type === "text" ? null : /* @__PURE__ */ jsx2(
1538
1618
  ShapeView,
1539
1619
  {
1540
1620
  shape,
@@ -1546,7 +1626,7 @@ function DrawingCanvas({ nodeKey, data }) {
1546
1626
  },
1547
1627
  shape.id
1548
1628
  )),
1549
- selectedShape && isEditable && !editingText && /* @__PURE__ */ jsx(
1629
+ selectedShape && isEditable && !editingText && /* @__PURE__ */ jsx2(
1550
1630
  SelectionOverlay,
1551
1631
  {
1552
1632
  shape: selectedShape,
@@ -1558,7 +1638,7 @@ function DrawingCanvas({ nodeKey, data }) {
1558
1638
  ]
1559
1639
  }
1560
1640
  ),
1561
- editingShape && editingText && /* @__PURE__ */ jsx(
1641
+ editingShape && editingText && /* @__PURE__ */ jsx2(
1562
1642
  TextEditOverlay,
1563
1643
  {
1564
1644
  shape: editingShape,
@@ -1567,7 +1647,7 @@ function DrawingCanvas({ nodeKey, data }) {
1567
1647
  },
1568
1648
  `${editingShape.id}:${editingText.field}`
1569
1649
  ),
1570
- isEditable && /* @__PURE__ */ jsx(
1650
+ isEditable && /* @__PURE__ */ jsx2(
1571
1651
  "div",
1572
1652
  {
1573
1653
  className: "zui-drawing-resize",
@@ -1606,7 +1686,7 @@ function DrawingCanvas({ nodeKey, data }) {
1606
1686
  }
1607
1687
  function HitArea({ shape }) {
1608
1688
  const b = bbox(shape);
1609
- return /* @__PURE__ */ jsx(
1689
+ return /* @__PURE__ */ jsx2(
1610
1690
  "rect",
1611
1691
  {
1612
1692
  x: b.x,
@@ -1640,8 +1720,8 @@ function SelectionOverlay({
1640
1720
  if (hasElbowHandle && i === 1) return [];
1641
1721
  return [{ index: i, x: (p.x + q.x) / 2, y: (p.y + q.y) / 2 }];
1642
1722
  });
1643
- return /* @__PURE__ */ jsxs("g", { children: [
1644
- ghosts.map(({ index, x, y }) => /* @__PURE__ */ jsx(
1723
+ return /* @__PURE__ */ jsxs2("g", { children: [
1724
+ ghosts.map(({ index, x, y }) => /* @__PURE__ */ jsx2(
1645
1725
  "circle",
1646
1726
  {
1647
1727
  cx: x,
@@ -1654,11 +1734,11 @@ function SelectionOverlay({
1654
1734
  opacity: 0.6,
1655
1735
  style: { cursor: "copy" },
1656
1736
  onPointerDown: (e) => onWaypointAdd(e, shape.id, index, { x, y }),
1657
- children: /* @__PURE__ */ jsx("title", { children: "Drag to add a point" })
1737
+ children: /* @__PURE__ */ jsx2("title", { children: "Drag to add a point" })
1658
1738
  },
1659
1739
  `ghost-${index}`
1660
1740
  )),
1661
- waypoints.map((p, i) => /* @__PURE__ */ jsx(
1741
+ waypoints.map((p, i) => /* @__PURE__ */ jsx2(
1662
1742
  "rect",
1663
1743
  {
1664
1744
  x: p.x - 4,
@@ -1679,11 +1759,11 @@ function SelectionOverlay({
1679
1759
  e.stopPropagation();
1680
1760
  onWaypointRemove(shape.id, i);
1681
1761
  },
1682
- children: /* @__PURE__ */ jsx("title", { children: "Drag to move, double-click to remove" })
1762
+ children: /* @__PURE__ */ jsx2("title", { children: "Drag to move, double-click to remove" })
1683
1763
  },
1684
1764
  `wp-${i}`
1685
1765
  )),
1686
- ends.map(({ end, x, y }) => /* @__PURE__ */ jsx(
1766
+ ends.map(({ end, x, y }) => /* @__PURE__ */ jsx2(
1687
1767
  "circle",
1688
1768
  {
1689
1769
  cx: x,
@@ -1702,7 +1782,7 @@ function SelectionOverlay({
1702
1782
  },
1703
1783
  end
1704
1784
  )),
1705
- elbowMid && /* @__PURE__ */ jsx(
1785
+ elbowMid && /* @__PURE__ */ jsx2(
1706
1786
  "rect",
1707
1787
  {
1708
1788
  x: elbowMid.x - 4,
@@ -1732,8 +1812,8 @@ function SelectionOverlay({
1732
1812
  { corner: "se", x: b.x + b.w + pad, y: b.y + b.h + pad }
1733
1813
  ];
1734
1814
  const resizable = shape.type !== "text";
1735
- return /* @__PURE__ */ jsxs("g", { children: [
1736
- /* @__PURE__ */ jsx(
1815
+ return /* @__PURE__ */ jsxs2("g", { children: [
1816
+ /* @__PURE__ */ jsx2(
1737
1817
  "rect",
1738
1818
  {
1739
1819
  x: b.x - pad,
@@ -1747,7 +1827,7 @@ function SelectionOverlay({
1747
1827
  pointerEvents: "none"
1748
1828
  }
1749
1829
  ),
1750
- resizable && corners.map(({ corner, x, y }) => /* @__PURE__ */ jsx(
1830
+ resizable && corners.map(({ corner, x, y }) => /* @__PURE__ */ jsx2(
1751
1831
  "rect",
1752
1832
  {
1753
1833
  x: x - 4,
@@ -1823,7 +1903,7 @@ function TextEditOverlay({
1823
1903
  });
1824
1904
  }
1825
1905
  const placeholder = field === "label" ? "Label" : field === "footer" ? "Footer" : "Text";
1826
- return /* @__PURE__ */ jsx(
1906
+ return /* @__PURE__ */ jsx2(
1827
1907
  "textarea",
1828
1908
  {
1829
1909
  ref,
@@ -1849,7 +1929,7 @@ function TextEditOverlay({
1849
1929
  }
1850
1930
 
1851
1931
  // src/nodes/DrawingNode.tsx
1852
- import { jsx as jsx2 } from "react/jsx-runtime";
1932
+ import { jsx as jsx3 } from "react/jsx-runtime";
1853
1933
  var DrawingNode = class _DrawingNode extends DecoratorNode {
1854
1934
  static getType() {
1855
1935
  return "drawing";
@@ -1913,7 +1993,7 @@ var DrawingNode = class _DrawingNode extends DecoratorNode {
1913
1993
  return false;
1914
1994
  }
1915
1995
  decorate(_editor, _config) {
1916
- return /* @__PURE__ */ jsx2(DrawingCanvas, { nodeKey: this.getKey(), data: this.getData() });
1996
+ return /* @__PURE__ */ jsx3(DrawingCanvas, { nodeKey: this.getKey(), data: this.getData() });
1917
1997
  }
1918
1998
  };
1919
1999
  function $createDrawingNode(data = serializeDrawingData(EMPTY_DRAWING)) {
@@ -1958,15 +2038,54 @@ import {
1958
2038
  $createTableNode,
1959
2039
  $createTableRowNode,
1960
2040
  $isTableCellNode,
1961
- $isTableNode,
2041
+ $isTableNode as $isTableNode2,
1962
2042
  $isTableRowNode,
1963
2043
  TableCellHeaderStates,
1964
2044
  TableCellNode,
1965
2045
  TableNode,
1966
2046
  TableRowNode
1967
2047
  } from "@lexical/table";
2048
+
2049
+ // src/transformers/tableWidth.ts
2050
+ import {
2051
+ $getNodeByKey as $getNodeByKey3,
2052
+ $getSelection as $getSelection2,
2053
+ $isRangeSelection as $isRangeSelection2
2054
+ } from "lexical";
2055
+ import { $findMatchingParent } from "@lexical/utils";
2056
+ import { $isTableNode, $isTableSelection } from "@lexical/table";
2057
+ var TABLE_WIDTH_MARKER = "<!-- width: content -->";
2058
+ var TABLE_WIDTH_MARKER_REG_EXP = /^<!--\s*width:\s*content\s*-->\s*$/;
2059
+ var CONTENT_WIDTH_STYLE = "width: auto; table-layout: auto";
2060
+ var CONTENT_WIDTH_REG_EXP = /(^|;)\s*width:\s*auto\s*(;|$)/;
2061
+ function $getTableWidth(table) {
2062
+ return CONTENT_WIDTH_REG_EXP.test(table.getStyle()) ? "content" : "full";
2063
+ }
2064
+ function $setTableWidth(table, width) {
2065
+ table.setStyle(width === "content" ? CONTENT_WIDTH_STYLE : "");
2066
+ }
2067
+ function $getSelectedTable() {
2068
+ const selection = $getSelection2();
2069
+ if ($isTableSelection(selection)) {
2070
+ const node = $getNodeByKey3(selection.tableKey);
2071
+ return $isTableNode(node) ? node : null;
2072
+ }
2073
+ if (!$isRangeSelection2(selection)) return null;
2074
+ const table = $findMatchingParent(
2075
+ selection.anchor.getNode(),
2076
+ (node) => $isTableNode(node)
2077
+ );
2078
+ return $isTableNode(table) ? table : null;
2079
+ }
2080
+
2081
+ // src/transformers/tableTransformer.ts
1968
2082
  var TABLE_ROW_REG_EXP = /^\|(.+)\|\s?$/;
1969
2083
  var TABLE_ROW_DIVIDER_REG_EXP = /^(\| ?:?-*:? ?)+\|\s?$/;
2084
+ function $isTableWidthMarker(node) {
2085
+ if (!$isParagraphNode2(node) || node.getChildrenSize() !== 1) return false;
2086
+ const child = node.getFirstChild();
2087
+ return $isTextNode(child) && TABLE_WIDTH_MARKER_REG_EXP.test(child.getTextContent());
2088
+ }
1970
2089
  function getTableColumnsSize(table) {
1971
2090
  const row = table.getFirstChild();
1972
2091
  return $isTableRowNode(row) ? row.getChildrenSize() : 0;
@@ -1985,8 +2104,9 @@ function mapToTableCells(textContent) {
1985
2104
  var TABLE = {
1986
2105
  dependencies: [TableNode, TableRowNode, TableCellNode],
1987
2106
  export: (node) => {
1988
- if (!$isTableNode(node)) return null;
2107
+ if (!$isTableNode2(node)) return null;
1989
2108
  const output = [];
2109
+ if ($getTableWidth(node) === "content") output.push(TABLE_WIDTH_MARKER);
1990
2110
  for (const row of node.getChildren()) {
1991
2111
  if (!$isTableRowNode(row)) continue;
1992
2112
  const rowOutput = [];
@@ -2011,7 +2131,7 @@ var TABLE = {
2011
2131
  replace: (parentNode, _children, match) => {
2012
2132
  if (TABLE_ROW_DIVIDER_REG_EXP.test(match[0])) {
2013
2133
  const table2 = parentNode.getPreviousSibling();
2014
- if (!table2 || !$isTableNode(table2)) return;
2134
+ if (!table2 || !$isTableNode2(table2)) return;
2015
2135
  const lastRow = table2.getLastChild();
2016
2136
  if (!lastRow || !$isTableRowNode(lastRow)) return;
2017
2137
  lastRow.getChildren().forEach((cell) => {
@@ -2048,10 +2168,14 @@ var TABLE = {
2048
2168
  }
2049
2169
  }
2050
2170
  const previousSibling = parentNode.getPreviousSibling();
2051
- if ($isTableNode(previousSibling) && getTableColumnsSize(previousSibling) === maxCells) {
2171
+ if ($isTableNode2(previousSibling) && getTableColumnsSize(previousSibling) === maxCells) {
2052
2172
  previousSibling.append(...table.getChildren());
2053
2173
  parentNode.remove();
2054
2174
  } else {
2175
+ if ($isTableWidthMarker(previousSibling)) {
2176
+ $setTableWidth(table, "content");
2177
+ previousSibling?.remove();
2178
+ }
2055
2179
  parentNode.replace(table);
2056
2180
  }
2057
2181
  table.selectEnd();
@@ -2139,7 +2263,7 @@ var editorTheme = {
2139
2263
  };
2140
2264
 
2141
2265
  // src/EditorRoot.tsx
2142
- import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
2266
+ import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
2143
2267
  var SYNC_TRANSFORMERS = [FRONTMATTER, DRAWING, CHECK_LIST, TABLE, ...TRANSFORMERS2];
2144
2268
  var SHORTCUT_TRANSFORMERS = [TABLE, ...TRANSFORMERS2.filter((t) => t !== CODE)];
2145
2269
  var EditorContext = createContext(null);
@@ -2229,10 +2353,10 @@ function EditorRoot({
2229
2353
  [mode, readOnly, autoFocus, value, handleChange]
2230
2354
  );
2231
2355
  const isRaw = mode === "edit-raw";
2232
- return /* @__PURE__ */ jsx3(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsx3(EditorContext.Provider, { value: context, children: /* @__PURE__ */ jsxs2("div", { className: `zui-text-editor ${className ?? ""}`, children: [
2356
+ return /* @__PURE__ */ jsx4(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsx4(EditorContext.Provider, { value: context, children: /* @__PURE__ */ jsxs3("div", { className: `zui-text-editor ${className ?? ""}`, children: [
2233
2357
  children,
2234
- !isRaw && /* @__PURE__ */ jsxs2(Fragment, { children: [
2235
- /* @__PURE__ */ jsx3(
2358
+ !isRaw && /* @__PURE__ */ jsxs3(Fragment2, { children: [
2359
+ /* @__PURE__ */ jsx4(
2236
2360
  MarkdownSyncPlugin,
2237
2361
  {
2238
2362
  initialMarkdown: mode === "view" ? value ?? "" : capturedMarkdown,
@@ -2240,17 +2364,17 @@ function EditorRoot({
2240
2364
  transformers: SYNC_TRANSFORMERS
2241
2365
  }
2242
2366
  ),
2243
- /* @__PURE__ */ jsx3(HistoryPlugin, {}),
2244
- /* @__PURE__ */ jsx3(ListPlugin, {}),
2245
- /* @__PURE__ */ jsx3(CheckListPlugin, {}),
2246
- /* @__PURE__ */ jsx3(ChecklistShortcutPlugin, {}),
2247
- /* @__PURE__ */ jsx3(CodeBlockShortcutPlugin, {}),
2248
- /* @__PURE__ */ jsx3(CodeHighlightPlugin, {}),
2249
- /* @__PURE__ */ jsx3(TablePlugin, {}),
2250
- /* @__PURE__ */ jsx3(LinkPlugin, {}),
2251
- /* @__PURE__ */ jsx3(MarkdownShortcutPlugin, { transformers: SHORTCUT_TRANSFORMERS }),
2252
- /* @__PURE__ */ jsx3(ReadOnlyPlugin, { readOnly: readOnly || mode === "view" }),
2253
- autoFocus && /* @__PURE__ */ jsx3(AutoFocusPlugin, {})
2367
+ /* @__PURE__ */ jsx4(HistoryPlugin, {}),
2368
+ /* @__PURE__ */ jsx4(ListPlugin, {}),
2369
+ /* @__PURE__ */ jsx4(CheckListPlugin, {}),
2370
+ /* @__PURE__ */ jsx4(ChecklistShortcutPlugin, {}),
2371
+ /* @__PURE__ */ jsx4(CodeBlockShortcutPlugin, {}),
2372
+ /* @__PURE__ */ jsx4(CodeHighlightPlugin, {}),
2373
+ /* @__PURE__ */ jsx4(TablePlugin, {}),
2374
+ /* @__PURE__ */ jsx4(LinkPlugin, {}),
2375
+ /* @__PURE__ */ jsx4(MarkdownShortcutPlugin, { transformers: SHORTCUT_TRANSFORMERS }),
2376
+ /* @__PURE__ */ jsx4(ReadOnlyPlugin, { readOnly: readOnly || mode === "view" }),
2377
+ autoFocus && /* @__PURE__ */ jsx4(AutoFocusPlugin, {})
2254
2378
  ] })
2255
2379
  ] }) }) }, mountKey);
2256
2380
  }
@@ -2267,10 +2391,10 @@ import {
2267
2391
  useRef as useRef4,
2268
2392
  useState as useState3
2269
2393
  } from "react";
2270
- import { $getRoot, $getSelection as $getSelection2, $isRangeSelection as $isRangeSelection2 } from "lexical";
2394
+ import { $getRoot, $getSelection as $getSelection3, $isRangeSelection as $isRangeSelection3 } from "lexical";
2271
2395
  import { useLexicalComposerContext as useLexicalComposerContext7 } from "@lexical/react/LexicalComposerContext";
2272
2396
  import { $isHeadingNode } from "@lexical/rich-text";
2273
- import { jsx as jsx4 } from "react/jsx-runtime";
2397
+ import { jsx as jsx5 } from "react/jsx-runtime";
2274
2398
  var HEADING_LEVELS = {
2275
2399
  h1: 1,
2276
2400
  h2: 2,
@@ -2306,8 +2430,8 @@ function FoldingPlugin() {
2306
2430
  hidden.add(sibling.getKey());
2307
2431
  }
2308
2432
  }
2309
- const selection = $getSelection2();
2310
- if ($isRangeSelection2(selection)) {
2433
+ const selection = $getSelection3();
2434
+ if ($isRangeSelection3(selection)) {
2311
2435
  const topLevel = selection.anchor.getNode().getTopLevelElement();
2312
2436
  if (topLevel && hidden.has(topLevel.getKey())) {
2313
2437
  let node = topLevel.getPreviousSibling();
@@ -2368,7 +2492,7 @@ function FoldingPlugin() {
2368
2492
  return next;
2369
2493
  });
2370
2494
  }, []);
2371
- return /* @__PURE__ */ jsx4("div", { className: "zui-text-editor-fold-gutter", children: buttons.map(({ key, folded, top, height }) => /* @__PURE__ */ jsx4(
2495
+ return /* @__PURE__ */ jsx5("div", { className: "zui-text-editor-fold-gutter", children: buttons.map(({ key, folded, top, height }) => /* @__PURE__ */ jsx5(
2372
2496
  "button",
2373
2497
  {
2374
2498
  type: "button",
@@ -2378,7 +2502,7 @@ function FoldingPlugin() {
2378
2502
  "aria-label": folded ? "Expand section" : "Collapse section",
2379
2503
  "aria-expanded": !folded,
2380
2504
  onClick: () => toggle(key),
2381
- children: /* @__PURE__ */ jsx4(
2505
+ children: /* @__PURE__ */ jsx5(
2382
2506
  "svg",
2383
2507
  {
2384
2508
  viewBox: "0 0 20 20",
@@ -2389,7 +2513,7 @@ function FoldingPlugin() {
2389
2513
  strokeWidth: "2",
2390
2514
  strokeLinecap: "round",
2391
2515
  strokeLinejoin: "round",
2392
- children: /* @__PURE__ */ jsx4("path", { d: "M6 8l4 4 4-4" })
2516
+ children: /* @__PURE__ */ jsx5("path", { d: "M6 8l4 4 4-4" })
2393
2517
  }
2394
2518
  )
2395
2519
  },
@@ -2397,168 +2521,16 @@ function FoldingPlugin() {
2397
2521
  )) });
2398
2522
  }
2399
2523
 
2400
- // src/EditorContent.tsx
2401
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
2402
- function EditorContent({
2403
- placeholder = "Start writing...",
2404
- foldable = true,
2405
- children
2406
- }) {
2407
- const { mode, readOnly, autoFocus, rawValue, onRawChange } = useEditorContext();
2408
- if (mode === "edit-raw") {
2409
- return /* @__PURE__ */ jsx5(
2410
- "textarea",
2411
- {
2412
- className: "zui-text-editor-textarea",
2413
- value: rawValue,
2414
- onChange: (e) => onRawChange(e.target.value),
2415
- placeholder,
2416
- readOnly,
2417
- autoFocus,
2418
- spellCheck: false
2419
- }
2420
- );
2421
- }
2422
- return /* @__PURE__ */ jsxs3("div", { className: "zui-text-editor-body", children: [
2423
- /* @__PURE__ */ jsxs3("div", { className: "zui-text-editor-main", children: [
2424
- /* @__PURE__ */ jsx5(
2425
- RichTextPlugin,
2426
- {
2427
- contentEditable: /* @__PURE__ */ jsx5(
2428
- ContentEditable,
2429
- {
2430
- className: "zui-text-editor-content",
2431
- "aria-placeholder": placeholder,
2432
- placeholder: /* @__PURE__ */ jsx5("div", { className: "zui-text-editor-placeholder", children: placeholder })
2433
- }
2434
- ),
2435
- ErrorBoundary: LexicalErrorBoundary
2436
- }
2437
- ),
2438
- foldable && /* @__PURE__ */ jsx5(FoldingPlugin, {})
2439
- ] }),
2440
- children
2441
- ] });
2442
- }
2443
-
2444
- // src/plugins/OutlinePlugin.tsx
2445
- import { useCallback as useCallback4, useEffect as useEffect8, useState as useState4 } from "react";
2446
- import { useLexicalComposerContext as useLexicalComposerContext8 } from "@lexical/react/LexicalComposerContext";
2447
- import {
2448
- TableOfContentsPlugin
2449
- } from "@lexical/react/LexicalTableOfContentsPlugin";
2450
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
2451
- var INDENT_PER_LEVEL = {
2452
- h1: 0,
2453
- h2: 1,
2454
- h3: 2,
2455
- h4: 3,
2456
- h5: 4,
2457
- h6: 5
2458
- };
2459
- function OutlinePlugin() {
2460
- const [editor] = useLexicalComposerContext8();
2461
- const [collapsed, setCollapsed] = useState4(false);
2462
- const [activeKey, setActiveKey] = useState4(null);
2463
- useEffect8(() => {
2464
- const rootElement = editor.getRootElement();
2465
- const scroller = rootElement?.closest(".zui-text-editor");
2466
- if (!rootElement || !(scroller instanceof HTMLElement)) return;
2467
- let frame = 0;
2468
- const updateActive = () => {
2469
- cancelAnimationFrame(frame);
2470
- frame = requestAnimationFrame(() => {
2471
- const headings = rootElement.querySelectorAll(
2472
- "h1, h2, h3, h4, h5, h6"
2473
- );
2474
- const threshold = scroller.scrollTop + 80;
2475
- let current = null;
2476
- for (const el of headings) {
2477
- if (el.offsetTop <= threshold) {
2478
- current = el.getAttribute("data-outline-key");
2479
- }
2480
- }
2481
- setActiveKey(current);
2482
- });
2483
- };
2484
- updateActive();
2485
- scroller.addEventListener("scroll", updateActive, { passive: true });
2486
- const unregister = editor.registerUpdateListener(updateActive);
2487
- return () => {
2488
- cancelAnimationFrame(frame);
2489
- scroller.removeEventListener("scroll", updateActive);
2490
- unregister();
2491
- };
2492
- }, [editor]);
2493
- const scrollTo = useCallback4(
2494
- (key) => {
2495
- editor.getEditorState().read(() => {
2496
- const element = editor.getElementByKey(key);
2497
- element?.scrollIntoView({ behavior: "smooth", block: "start" });
2498
- });
2499
- },
2500
- [editor]
2501
- );
2502
- return /* @__PURE__ */ jsx6(TableOfContentsPlugin, { children: (entries) => {
2503
- for (const [key] of entries) {
2504
- editor.getElementByKey(key)?.setAttribute("data-outline-key", key);
2505
- }
2506
- return /* @__PURE__ */ jsxs4(
2507
- "div",
2508
- {
2509
- className: `zui-text-editor-outline ${collapsed ? "is-collapsed" : ""}`,
2510
- children: [
2511
- /* @__PURE__ */ jsx6(
2512
- "button",
2513
- {
2514
- type: "button",
2515
- className: "zui-text-editor-outline-toggle",
2516
- title: collapsed ? "Show outline" : "Hide outline",
2517
- "aria-label": collapsed ? "Show outline" : "Hide outline",
2518
- "aria-expanded": !collapsed,
2519
- onClick: () => setCollapsed((c) => !c),
2520
- children: /* @__PURE__ */ jsx6(
2521
- "svg",
2522
- {
2523
- viewBox: "0 0 20 20",
2524
- width: "14",
2525
- height: "14",
2526
- fill: "none",
2527
- stroke: "currentColor",
2528
- strokeWidth: "1.8",
2529
- strokeLinecap: "round",
2530
- children: /* @__PURE__ */ jsx6("path", { d: "M4 5h12M4 10h8M4 15h10" })
2531
- }
2532
- )
2533
- }
2534
- ),
2535
- !collapsed && /* @__PURE__ */ jsxs4("nav", { className: "zui-text-editor-outline-list", "aria-label": "Table of contents", children: [
2536
- entries.length === 0 && /* @__PURE__ */ jsx6("div", { className: "zui-text-editor-outline-empty", children: "No headings" }),
2537
- entries.map(([key, text, tag]) => /* @__PURE__ */ jsx6(
2538
- "button",
2539
- {
2540
- type: "button",
2541
- className: `zui-text-editor-outline-item ${key === activeKey ? "is-active" : ""}`,
2542
- style: {
2543
- paddingLeft: `${0.5 + INDENT_PER_LEVEL[tag] * 0.75}rem`
2544
- },
2545
- onClick: () => scrollTo(key),
2546
- children: text || "Untitled"
2547
- },
2548
- key
2549
- ))
2550
- ] })
2551
- ]
2552
- }
2553
- );
2554
- } });
2555
- }
2524
+ // src/plugins/TableWidthPlugin.tsx
2525
+ import { useCallback as useCallback5, useEffect as useEffect9, useState as useState5 } from "react";
2526
+ import { useLexicalComposerContext as useLexicalComposerContext9 } from "@lexical/react/LexicalComposerContext";
2527
+ import { useLexicalEditable as useLexicalEditable2 } from "@lexical/react/useLexicalEditable";
2556
2528
 
2557
2529
  // src/useMarkdownEditor.ts
2558
- import { useCallback as useCallback5, useEffect as useEffect9, useState as useState5 } from "react";
2530
+ import { useCallback as useCallback4, useEffect as useEffect8, useState as useState4 } from "react";
2559
2531
  import {
2560
- $getSelection as $getSelection3,
2561
- $isRangeSelection as $isRangeSelection3,
2532
+ $getSelection as $getSelection4,
2533
+ $isRangeSelection as $isRangeSelection4,
2562
2534
  CAN_REDO_COMMAND,
2563
2535
  CAN_UNDO_COMMAND,
2564
2536
  COMMAND_PRIORITY_LOW as COMMAND_PRIORITY_LOW2,
@@ -2566,7 +2538,7 @@ import {
2566
2538
  REDO_COMMAND,
2567
2539
  UNDO_COMMAND
2568
2540
  } from "lexical";
2569
- import { useLexicalComposerContext as useLexicalComposerContext9 } from "@lexical/react/LexicalComposerContext";
2541
+ import { useLexicalComposerContext as useLexicalComposerContext8 } from "@lexical/react/LexicalComposerContext";
2570
2542
  import { INSERT_TABLE_COMMAND } from "@lexical/table";
2571
2543
  import { $insertNodeToNearestRoot, mergeRegister } from "@lexical/utils";
2572
2544
  var TRACKED_FORMATS = [
@@ -2577,18 +2549,21 @@ var TRACKED_FORMATS = [
2577
2549
  "code"
2578
2550
  ];
2579
2551
  function useMarkdownEditor() {
2580
- const [editor] = useLexicalComposerContext9();
2581
- const [activeFormats, setActiveFormats] = useState5(
2552
+ const [editor] = useLexicalComposerContext8();
2553
+ const [activeFormats, setActiveFormats] = useState4(
2582
2554
  /* @__PURE__ */ new Set()
2583
2555
  );
2584
- const [canUndo, setCanUndo] = useState5(false);
2585
- const [canRedo, setCanRedo] = useState5(false);
2586
- useEffect9(
2556
+ const [canUndo, setCanUndo] = useState4(false);
2557
+ const [canRedo, setCanRedo] = useState4(false);
2558
+ const [tableWidth, setTableWidthState] = useState4(null);
2559
+ useEffect8(
2587
2560
  () => mergeRegister(
2588
2561
  editor.registerUpdateListener(({ editorState }) => {
2589
2562
  editorState.read(() => {
2590
- const selection = $getSelection3();
2591
- if (!$isRangeSelection3(selection)) {
2563
+ const table = $getSelectedTable();
2564
+ setTableWidthState(table ? $getTableWidth(table) : null);
2565
+ const selection = $getSelection4();
2566
+ if (!$isRangeSelection4(selection)) {
2592
2567
  setActiveFormats(/* @__PURE__ */ new Set());
2593
2568
  return;
2594
2569
  }
@@ -2618,13 +2593,13 @@ function useMarkdownEditor() {
2618
2593
  ),
2619
2594
  [editor]
2620
2595
  );
2621
- const toggleFormat = useCallback5(
2596
+ const toggleFormat = useCallback4(
2622
2597
  (format) => {
2623
2598
  editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
2624
2599
  },
2625
2600
  [editor]
2626
2601
  );
2627
- const insertTable = useCallback5(
2602
+ const insertTable = useCallback4(
2628
2603
  ({ rows = 3, columns = 3 } = {}) => {
2629
2604
  editor.dispatchCommand(INSERT_TABLE_COMMAND, {
2630
2605
  columns: String(columns),
@@ -2634,15 +2609,24 @@ function useMarkdownEditor() {
2634
2609
  },
2635
2610
  [editor]
2636
2611
  );
2637
- const insertDrawing = useCallback5(() => {
2612
+ const insertDrawing = useCallback4(() => {
2638
2613
  editor.update(() => {
2639
2614
  $insertNodeToNearestRoot($createDrawingNode());
2640
2615
  });
2641
2616
  }, [editor]);
2642
- const undo = useCallback5(() => {
2617
+ const setTableWidth = useCallback4(
2618
+ (width) => {
2619
+ editor.update(() => {
2620
+ const table = $getSelectedTable();
2621
+ if (table) $setTableWidth(table, width);
2622
+ });
2623
+ },
2624
+ [editor]
2625
+ );
2626
+ const undo = useCallback4(() => {
2643
2627
  editor.dispatchCommand(UNDO_COMMAND, void 0);
2644
2628
  }, [editor]);
2645
- const redo = useCallback5(() => {
2629
+ const redo = useCallback4(() => {
2646
2630
  editor.dispatchCommand(REDO_COMMAND, void 0);
2647
2631
  }, [editor]);
2648
2632
  return {
@@ -2651,6 +2635,8 @@ function useMarkdownEditor() {
2651
2635
  toggleFormat,
2652
2636
  insertTable,
2653
2637
  insertDrawing,
2638
+ tableWidth,
2639
+ setTableWidth,
2654
2640
  canUndo,
2655
2641
  canRedo,
2656
2642
  undo,
@@ -2659,23 +2645,23 @@ function useMarkdownEditor() {
2659
2645
  }
2660
2646
 
2661
2647
  // src/components/Toolbar.tsx
2662
- import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
2648
+ import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
2663
2649
  function Toolbar({ children, className }) {
2664
- return /* @__PURE__ */ jsx7(
2650
+ return /* @__PURE__ */ jsx6(
2665
2651
  "div",
2666
2652
  {
2667
2653
  className: `zui-text-editor-toolbar ${className ?? ""}`,
2668
2654
  role: "toolbar",
2669
- children: children ?? /* @__PURE__ */ jsxs5(Fragment2, { children: [
2670
- /* @__PURE__ */ jsx7(FormatButtons, {}),
2671
- /* @__PURE__ */ jsx7(ToolbarDivider, {}),
2672
- /* @__PURE__ */ jsx7(InsertButtons, {})
2655
+ children: children ?? /* @__PURE__ */ jsxs4(Fragment3, { children: [
2656
+ /* @__PURE__ */ jsx6(FormatButtons, {}),
2657
+ /* @__PURE__ */ jsx6(ToolbarDivider, {}),
2658
+ /* @__PURE__ */ jsx6(InsertButtons, {})
2673
2659
  ] })
2674
2660
  }
2675
2661
  );
2676
2662
  }
2677
2663
  function ToolbarDivider() {
2678
- return /* @__PURE__ */ jsx7("div", { className: "zui-text-editor-toolbar-divider" });
2664
+ return /* @__PURE__ */ jsx6("div", { className: "zui-text-editor-toolbar-divider" });
2679
2665
  }
2680
2666
  function ToolbarButton({
2681
2667
  label,
@@ -2685,7 +2671,7 @@ function ToolbarButton({
2685
2671
  disabled = false,
2686
2672
  className
2687
2673
  }) {
2688
- return /* @__PURE__ */ jsx7(
2674
+ return /* @__PURE__ */ jsx6(
2689
2675
  "button",
2690
2676
  {
2691
2677
  type: "button",
@@ -2701,7 +2687,7 @@ function ToolbarButton({
2701
2687
  );
2702
2688
  }
2703
2689
  function Icon({ children, strokeWidth = 1.5 }) {
2704
- return /* @__PURE__ */ jsx7(
2690
+ return /* @__PURE__ */ jsx6(
2705
2691
  "svg",
2706
2692
  {
2707
2693
  viewBox: "0 0 20 20",
@@ -2720,27 +2706,27 @@ var FORMAT_BUTTONS = [
2720
2706
  {
2721
2707
  format: "bold",
2722
2708
  label: "Bold",
2723
- icon: /* @__PURE__ */ jsx7(Icon, { strokeWidth: 1.8, children: /* @__PURE__ */ jsx7("path", { d: "M6 3.5h5a3 3 0 0 1 0 6H6zm0 6h6a3 3 0 0 1 0 6H6z" }) })
2709
+ icon: /* @__PURE__ */ jsx6(Icon, { strokeWidth: 1.8, children: /* @__PURE__ */ jsx6("path", { d: "M6 3.5h5a3 3 0 0 1 0 6H6zm0 6h6a3 3 0 0 1 0 6H6z" }) })
2724
2710
  },
2725
2711
  {
2726
2712
  format: "italic",
2727
2713
  label: "Italic",
2728
- icon: /* @__PURE__ */ jsx7(Icon, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx7("path", { d: "M8.5 3.5h6M5.5 16.5h6M11.5 3.5l-3 13" }) })
2714
+ icon: /* @__PURE__ */ jsx6(Icon, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx6("path", { d: "M8.5 3.5h6M5.5 16.5h6M11.5 3.5l-3 13" }) })
2729
2715
  },
2730
2716
  {
2731
2717
  format: "strikethrough",
2732
2718
  label: "Strikethrough",
2733
- icon: /* @__PURE__ */ jsx7(Icon, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx7("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" }) })
2719
+ icon: /* @__PURE__ */ jsx6(Icon, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx6("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" }) })
2734
2720
  },
2735
2721
  {
2736
2722
  format: "code",
2737
2723
  label: "Inline code",
2738
- icon: /* @__PURE__ */ jsx7(Icon, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx7("path", { d: "M7.5 6L4 10l3.5 4M12.5 6L16 10l-3.5 4" }) })
2724
+ icon: /* @__PURE__ */ jsx6(Icon, { strokeWidth: 1.6, children: /* @__PURE__ */ jsx6("path", { d: "M7.5 6L4 10l3.5 4M12.5 6L16 10l-3.5 4" }) })
2739
2725
  }
2740
2726
  ];
2741
2727
  function FormatButtons() {
2742
2728
  const { activeFormats, toggleFormat } = useMarkdownEditor();
2743
- return /* @__PURE__ */ jsx7(Fragment2, { children: FORMAT_BUTTONS.map(({ format, label, icon }) => /* @__PURE__ */ jsx7(
2729
+ return /* @__PURE__ */ jsx6(Fragment3, { children: FORMAT_BUTTONS.map(({ format, label, icon }) => /* @__PURE__ */ jsx6(
2744
2730
  ToolbarButton,
2745
2731
  {
2746
2732
  label,
@@ -2753,38 +2739,264 @@ function FormatButtons() {
2753
2739
  }
2754
2740
  function InsertButtons() {
2755
2741
  const { insertTable, insertDrawing } = useMarkdownEditor();
2756
- return /* @__PURE__ */ jsxs5(Fragment2, { children: [
2757
- /* @__PURE__ */ jsx7(ToolbarButton, { label: "Insert table", onClick: () => insertTable(), children: /* @__PURE__ */ jsxs5(Icon, { children: [
2758
- /* @__PURE__ */ jsx7("rect", { x: "3", y: "3.5", width: "14", height: "13", rx: "1.5" }),
2759
- /* @__PURE__ */ jsx7("path", { d: "M3 8h14M8 8v8.5M13 8v8.5" })
2742
+ return /* @__PURE__ */ jsxs4(Fragment3, { children: [
2743
+ /* @__PURE__ */ jsx6(ToolbarButton, { label: "Insert table", onClick: () => insertTable(), children: /* @__PURE__ */ jsxs4(Icon, { children: [
2744
+ /* @__PURE__ */ jsx6("rect", { x: "3", y: "3.5", width: "14", height: "13", rx: "1.5" }),
2745
+ /* @__PURE__ */ jsx6("path", { d: "M3 8h14M8 8v8.5M13 8v8.5" })
2760
2746
  ] }) }),
2761
- /* @__PURE__ */ jsx7(ToolbarButton, { label: "Insert drawing", onClick: insertDrawing, children: /* @__PURE__ */ jsxs5(Icon, { children: [
2762
- /* @__PURE__ */ jsx7("rect", { x: "3", y: "5", width: "8", height: "6", rx: "1.5" }),
2763
- /* @__PURE__ */ jsx7("path", { d: "M13.5 8h3M14.5 6.5L17.5 8l-3 1.5" }),
2764
- /* @__PURE__ */ jsx7("ellipse", { cx: "13", cy: "14.5", rx: "4", ry: "2.8" })
2747
+ /* @__PURE__ */ jsx6(ToolbarButton, { label: "Insert drawing", onClick: insertDrawing, children: /* @__PURE__ */ jsxs4(Icon, { children: [
2748
+ /* @__PURE__ */ jsx6("rect", { x: "3", y: "5", width: "8", height: "6", rx: "1.5" }),
2749
+ /* @__PURE__ */ jsx6("path", { d: "M13.5 8h3M14.5 6.5L17.5 8l-3 1.5" }),
2750
+ /* @__PURE__ */ jsx6("ellipse", { cx: "13", cy: "14.5", rx: "4", ry: "2.8" })
2765
2751
  ] }) })
2766
2752
  ] });
2767
2753
  }
2768
2754
  function HistoryButtons() {
2769
2755
  const { canUndo, canRedo, undo, redo } = useMarkdownEditor();
2770
- return /* @__PURE__ */ jsxs5(Fragment2, { children: [
2771
- /* @__PURE__ */ jsx7(ToolbarButton, { label: "Undo", onClick: undo, disabled: !canUndo, children: /* @__PURE__ */ jsxs5(Icon, { children: [
2772
- /* @__PURE__ */ jsx7("path", { d: "M7 6L3.5 9.5 7 13" }),
2773
- /* @__PURE__ */ jsx7("path", { d: "M3.5 9.5H12a4 4 0 0 1 0 8h-1" })
2756
+ return /* @__PURE__ */ jsxs4(Fragment3, { children: [
2757
+ /* @__PURE__ */ jsx6(ToolbarButton, { label: "Undo", onClick: undo, disabled: !canUndo, children: /* @__PURE__ */ jsxs4(Icon, { children: [
2758
+ /* @__PURE__ */ jsx6("path", { d: "M7 6L3.5 9.5 7 13" }),
2759
+ /* @__PURE__ */ jsx6("path", { d: "M3.5 9.5H12a4 4 0 0 1 0 8h-1" })
2774
2760
  ] }) }),
2775
- /* @__PURE__ */ jsx7(ToolbarButton, { label: "Redo", onClick: redo, disabled: !canRedo, children: /* @__PURE__ */ jsxs5(Icon, { children: [
2776
- /* @__PURE__ */ jsx7("path", { d: "M13 6l3.5 3.5L13 13" }),
2777
- /* @__PURE__ */ jsx7("path", { d: "M16.5 9.5H8a4 4 0 0 0 0 8h1" })
2761
+ /* @__PURE__ */ jsx6(ToolbarButton, { label: "Redo", onClick: redo, disabled: !canRedo, children: /* @__PURE__ */ jsxs4(Icon, { children: [
2762
+ /* @__PURE__ */ jsx6("path", { d: "M13 6l3.5 3.5L13 13" }),
2763
+ /* @__PURE__ */ jsx6("path", { d: "M16.5 9.5H8a4 4 0 0 0 0 8h1" })
2778
2764
  ] }) })
2779
2765
  ] });
2780
2766
  }
2781
2767
 
2768
+ // src/plugins/TableWidthPlugin.tsx
2769
+ import { jsx as jsx7 } from "react/jsx-runtime";
2770
+ function TableWidthPlugin() {
2771
+ const [editor] = useLexicalComposerContext9();
2772
+ const isEditable = useLexicalEditable2();
2773
+ const { tableWidth, setTableWidth } = useMarkdownEditor();
2774
+ const [anchor, setAnchor] = useState5(null);
2775
+ const sync = useCallback5(() => {
2776
+ const tableKey = editor.getEditorState().read(() => $getSelectedTable()?.getKey());
2777
+ const element = tableKey ? editor.getElementByKey(tableKey) : null;
2778
+ const main = editor.getRootElement()?.parentElement;
2779
+ if (!element || !main) {
2780
+ setAnchor(null);
2781
+ return;
2782
+ }
2783
+ const rect = element.getBoundingClientRect();
2784
+ const mainRect = main.getBoundingClientRect();
2785
+ setAnchor({
2786
+ top: rect.top - mainRect.top,
2787
+ right: mainRect.right - rect.right + 8
2788
+ });
2789
+ }, [editor]);
2790
+ useEffect9(() => {
2791
+ sync();
2792
+ const unregister = editor.registerUpdateListener(sync);
2793
+ const rootElement = editor.getRootElement();
2794
+ const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(sync) : null;
2795
+ if (rootElement && observer) observer.observe(rootElement);
2796
+ return () => {
2797
+ unregister();
2798
+ observer?.disconnect();
2799
+ };
2800
+ }, [editor, sync]);
2801
+ if (!isEditable || !anchor || !tableWidth) return null;
2802
+ return /* @__PURE__ */ jsx7(
2803
+ "div",
2804
+ {
2805
+ className: "zui-table-width",
2806
+ role: "group",
2807
+ "aria-label": "Table width",
2808
+ style: { top: anchor.top, right: anchor.right },
2809
+ children: BLOCK_WIDTH_OPTIONS.map(({ width, label, icon }) => /* @__PURE__ */ jsx7(
2810
+ ToolbarButton,
2811
+ {
2812
+ label,
2813
+ active: tableWidth === width,
2814
+ onClick: () => setTableWidth(width),
2815
+ children: /* @__PURE__ */ jsx7(
2816
+ "svg",
2817
+ {
2818
+ viewBox: "0 0 20 20",
2819
+ width: "16",
2820
+ height: "16",
2821
+ fill: "none",
2822
+ stroke: "currentColor",
2823
+ strokeWidth: "1.6",
2824
+ strokeLinecap: "round",
2825
+ strokeLinejoin: "round",
2826
+ children: icon
2827
+ }
2828
+ )
2829
+ },
2830
+ width
2831
+ ))
2832
+ }
2833
+ );
2834
+ }
2835
+
2836
+ // src/EditorContent.tsx
2837
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
2838
+ function EditorContent({
2839
+ placeholder = "Start writing...",
2840
+ foldable = true,
2841
+ children
2842
+ }) {
2843
+ const { mode, readOnly, autoFocus, rawValue, onRawChange } = useEditorContext();
2844
+ if (mode === "edit-raw") {
2845
+ return /* @__PURE__ */ jsx8(
2846
+ "textarea",
2847
+ {
2848
+ className: "zui-text-editor-textarea",
2849
+ value: rawValue,
2850
+ onChange: (e) => onRawChange(e.target.value),
2851
+ placeholder,
2852
+ readOnly,
2853
+ autoFocus,
2854
+ spellCheck: false
2855
+ }
2856
+ );
2857
+ }
2858
+ return /* @__PURE__ */ jsxs5("div", { className: "zui-text-editor-body", children: [
2859
+ /* @__PURE__ */ jsxs5("div", { className: "zui-text-editor-main", children: [
2860
+ /* @__PURE__ */ jsx8(
2861
+ RichTextPlugin,
2862
+ {
2863
+ contentEditable: /* @__PURE__ */ jsx8(
2864
+ ContentEditable,
2865
+ {
2866
+ className: "zui-text-editor-content",
2867
+ "aria-placeholder": placeholder,
2868
+ placeholder: /* @__PURE__ */ jsx8("div", { className: "zui-text-editor-placeholder", children: placeholder })
2869
+ }
2870
+ ),
2871
+ ErrorBoundary: LexicalErrorBoundary
2872
+ }
2873
+ ),
2874
+ foldable && /* @__PURE__ */ jsx8(FoldingPlugin, {}),
2875
+ /* @__PURE__ */ jsx8(TableWidthPlugin, {})
2876
+ ] }),
2877
+ children
2878
+ ] });
2879
+ }
2880
+
2881
+ // src/plugins/OutlinePlugin.tsx
2882
+ import { useCallback as useCallback6, useEffect as useEffect10, useState as useState6 } from "react";
2883
+ import { useLexicalComposerContext as useLexicalComposerContext10 } from "@lexical/react/LexicalComposerContext";
2884
+ import {
2885
+ TableOfContentsPlugin
2886
+ } from "@lexical/react/LexicalTableOfContentsPlugin";
2887
+ import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
2888
+ var INDENT_PER_LEVEL = {
2889
+ h1: 0,
2890
+ h2: 1,
2891
+ h3: 2,
2892
+ h4: 3,
2893
+ h5: 4,
2894
+ h6: 5
2895
+ };
2896
+ function OutlinePlugin() {
2897
+ const [editor] = useLexicalComposerContext10();
2898
+ const [collapsed, setCollapsed] = useState6(false);
2899
+ const [activeKey, setActiveKey] = useState6(null);
2900
+ useEffect10(() => {
2901
+ const rootElement = editor.getRootElement();
2902
+ const scroller = rootElement?.closest(".zui-text-editor");
2903
+ if (!rootElement || !(scroller instanceof HTMLElement)) return;
2904
+ let frame = 0;
2905
+ const updateActive = () => {
2906
+ cancelAnimationFrame(frame);
2907
+ frame = requestAnimationFrame(() => {
2908
+ const headings = rootElement.querySelectorAll(
2909
+ "h1, h2, h3, h4, h5, h6"
2910
+ );
2911
+ const threshold = scroller.scrollTop + 80;
2912
+ let current = null;
2913
+ for (const el of headings) {
2914
+ if (el.offsetTop <= threshold) {
2915
+ current = el.getAttribute("data-outline-key");
2916
+ }
2917
+ }
2918
+ setActiveKey(current);
2919
+ });
2920
+ };
2921
+ updateActive();
2922
+ scroller.addEventListener("scroll", updateActive, { passive: true });
2923
+ const unregister = editor.registerUpdateListener(updateActive);
2924
+ return () => {
2925
+ cancelAnimationFrame(frame);
2926
+ scroller.removeEventListener("scroll", updateActive);
2927
+ unregister();
2928
+ };
2929
+ }, [editor]);
2930
+ const scrollTo = useCallback6(
2931
+ (key) => {
2932
+ editor.getEditorState().read(() => {
2933
+ const element = editor.getElementByKey(key);
2934
+ element?.scrollIntoView({ behavior: "smooth", block: "start" });
2935
+ });
2936
+ },
2937
+ [editor]
2938
+ );
2939
+ return /* @__PURE__ */ jsx9(TableOfContentsPlugin, { children: (entries) => {
2940
+ for (const [key] of entries) {
2941
+ editor.getElementByKey(key)?.setAttribute("data-outline-key", key);
2942
+ }
2943
+ return /* @__PURE__ */ jsxs6(
2944
+ "div",
2945
+ {
2946
+ className: `zui-text-editor-outline ${collapsed ? "is-collapsed" : ""}`,
2947
+ children: [
2948
+ /* @__PURE__ */ jsx9(
2949
+ "button",
2950
+ {
2951
+ type: "button",
2952
+ className: "zui-text-editor-outline-toggle",
2953
+ title: collapsed ? "Show outline" : "Hide outline",
2954
+ "aria-label": collapsed ? "Show outline" : "Hide outline",
2955
+ "aria-expanded": !collapsed,
2956
+ onClick: () => setCollapsed((c) => !c),
2957
+ children: /* @__PURE__ */ jsx9(
2958
+ "svg",
2959
+ {
2960
+ viewBox: "0 0 20 20",
2961
+ width: "14",
2962
+ height: "14",
2963
+ fill: "none",
2964
+ stroke: "currentColor",
2965
+ strokeWidth: "1.8",
2966
+ strokeLinecap: "round",
2967
+ children: /* @__PURE__ */ jsx9("path", { d: "M4 5h12M4 10h8M4 15h10" })
2968
+ }
2969
+ )
2970
+ }
2971
+ ),
2972
+ !collapsed && /* @__PURE__ */ jsxs6("nav", { className: "zui-text-editor-outline-list", "aria-label": "Table of contents", children: [
2973
+ entries.length === 0 && /* @__PURE__ */ jsx9("div", { className: "zui-text-editor-outline-empty", children: "No headings" }),
2974
+ entries.map(([key, text, tag]) => /* @__PURE__ */ jsx9(
2975
+ "button",
2976
+ {
2977
+ type: "button",
2978
+ className: `zui-text-editor-outline-item ${key === activeKey ? "is-active" : ""}`,
2979
+ style: {
2980
+ paddingLeft: `${0.5 + INDENT_PER_LEVEL[tag] * 0.75}rem`
2981
+ },
2982
+ onClick: () => scrollTo(key),
2983
+ children: text || "Untitled"
2984
+ },
2985
+ key
2986
+ ))
2987
+ ] })
2988
+ ]
2989
+ }
2990
+ );
2991
+ } });
2992
+ }
2993
+
2782
2994
  // src/MarkdownEditor.tsx
2783
- import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
2995
+ import { jsx as jsx10, jsxs as jsxs7 } from "react/jsx-runtime";
2784
2996
  var DEFAULT_ITEMS = {
2785
- format: /* @__PURE__ */ jsx8(FormatButtons, {}),
2786
- insert: /* @__PURE__ */ jsx8(InsertButtons, {}),
2787
- history: /* @__PURE__ */ jsx8(HistoryButtons, {})
2997
+ format: /* @__PURE__ */ jsx10(FormatButtons, {}),
2998
+ insert: /* @__PURE__ */ jsx10(InsertButtons, {}),
2999
+ history: /* @__PURE__ */ jsx10(HistoryButtons, {})
2788
3000
  };
2789
3001
  function EditorToolbar({
2790
3002
  children,
@@ -2792,7 +3004,7 @@ function EditorToolbar({
2792
3004
  }) {
2793
3005
  const { mode, readOnly } = useEditorContext();
2794
3006
  if (mode !== "edit-md" || readOnly) return null;
2795
- return /* @__PURE__ */ jsx8(Toolbar, { className, children });
3007
+ return /* @__PURE__ */ jsx10(Toolbar, { className, children });
2796
3008
  }
2797
3009
  function MarkdownEditor({
2798
3010
  placeholder,
@@ -2801,10 +3013,10 @@ function MarkdownEditor({
2801
3013
  foldable = true,
2802
3014
  ...rootProps
2803
3015
  }) {
2804
- return /* @__PURE__ */ jsxs6(EditorRoot, { ...rootProps, children: [
2805
- toolbar === true && /* @__PURE__ */ jsx8(EditorToolbar, {}),
3016
+ return /* @__PURE__ */ jsxs7(EditorRoot, { ...rootProps, children: [
3017
+ toolbar === true && /* @__PURE__ */ jsx10(EditorToolbar, {}),
2806
3018
  typeof toolbar === "function" && toolbar(DEFAULT_ITEMS),
2807
- /* @__PURE__ */ jsx8(EditorContent, { placeholder, foldable, children: outline && /* @__PURE__ */ jsx8(OutlinePlugin, {}) })
3019
+ /* @__PURE__ */ jsx10(EditorContent, { placeholder, foldable, children: outline && /* @__PURE__ */ jsx10(OutlinePlugin, {}) })
2808
3020
  ] });
2809
3021
  }
2810
3022
  MarkdownEditor.Root = EditorRoot;
@@ -2832,7 +3044,11 @@ var DRAWING_DATA_JSON_SCHEMA = {
2832
3044
  height: {
2833
3045
  type: "number",
2834
3046
  minimum: 80,
2835
- description: "Canvas height in pixels (width is fluid)"
3047
+ description: "Canvas height in pixels"
3048
+ },
3049
+ width: {
3050
+ enum: ["full", "content"],
3051
+ description: `Canvas width: "full" (default) spans the editor; "content" fits the shapes' horizontal extent and left-aligns with the text`
2836
3052
  },
2837
3053
  shapes: {
2838
3054
  type: "array",
@@ -2930,8 +3146,11 @@ var DRAWING_DATA_JSON_SCHEMA = {
2930
3146
  export {
2931
3147
  $createDrawingNode,
2932
3148
  $createFrontmatterNode,
3149
+ $getSelectedTable,
3150
+ $getTableWidth,
2933
3151
  $isDrawingNode,
2934
3152
  $isFrontmatterNode,
3153
+ $setTableWidth,
2935
3154
  DRAWING,
2936
3155
  DRAWING_DATA_JSON_SCHEMA,
2937
3156
  DrawingNode,
@@ -2942,6 +3161,7 @@ export {
2942
3161
  InsertButtons,
2943
3162
  MarkdownEditor_default as MarkdownEditor,
2944
3163
  TABLE,
3164
+ TABLE_WIDTH_MARKER,
2945
3165
  Toolbar,
2946
3166
  ToolbarButton,
2947
3167
  ToolbarDivider,