@zuilib/text-editor 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,10 +1,15 @@
1
- // src/MarkdownEditor.tsx
2
- import { useCallback as useCallback5, useEffect as useEffect9, useMemo, useRef as useRef4, useState as useState5 } from "react";
1
+ // src/EditorRoot.tsx
2
+ import {
3
+ createContext,
4
+ useCallback as useCallback2,
5
+ useContext,
6
+ useEffect as useEffect6,
7
+ useMemo,
8
+ useRef as useRef3,
9
+ useState as useState2
10
+ } from "react";
3
11
  import { LexicalComposer } from "@lexical/react/LexicalComposer";
4
- import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
5
- import { ContentEditable } from "@lexical/react/LexicalContentEditable";
6
12
  import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
7
- import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
8
13
  import { ListPlugin } from "@lexical/react/LexicalListPlugin";
9
14
  import { CheckListPlugin } from "@lexical/react/LexicalCheckListPlugin";
10
15
  import { LinkPlugin } from "@lexical/react/LexicalLinkPlugin";
@@ -12,7 +17,7 @@ import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPl
12
17
  import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
13
18
  import { TablePlugin } from "@lexical/react/LexicalTablePlugin";
14
19
  import { CHECK_LIST, CODE, TRANSFORMERS as TRANSFORMERS2 } from "@lexical/markdown";
15
- import { useLexicalComposerContext as useLexicalComposerContext9 } from "@lexical/react/LexicalComposerContext";
20
+ import { useLexicalComposerContext as useLexicalComposerContext6 } from "@lexical/react/LexicalComposerContext";
16
21
  import { HeadingNode, QuoteNode } from "@lexical/rich-text";
17
22
  import { ListItemNode, ListNode as ListNode2 } from "@lexical/list";
18
23
  import { CodeHighlightNode, CodeNode } from "@lexical/code";
@@ -166,146 +171,9 @@ function CodeHighlightPlugin() {
166
171
  return null;
167
172
  }
168
173
 
169
- // src/plugins/FoldingPlugin.tsx
170
- import {
171
- useCallback,
172
- useEffect as useEffect4,
173
- useRef,
174
- useState
175
- } from "react";
176
- import { $getRoot, $getSelection as $getSelection2, $isRangeSelection as $isRangeSelection2 } from "lexical";
177
- import { useLexicalComposerContext as useLexicalComposerContext4 } from "@lexical/react/LexicalComposerContext";
178
- import { $isHeadingNode } from "@lexical/rich-text";
179
- import { jsx } from "react/jsx-runtime";
180
- var HEADING_LEVELS = {
181
- h1: 1,
182
- h2: 2,
183
- h3: 3,
184
- h4: 4,
185
- h5: 5,
186
- h6: 6
187
- };
188
- function FoldingPlugin() {
189
- const [editor] = useLexicalComposerContext4();
190
- const [foldedKeys, setFoldedKeys] = useState(/* @__PURE__ */ new Set());
191
- const [buttons, setButtons] = useState([]);
192
- const foldedRef = useRef(foldedKeys);
193
- foldedRef.current = foldedKeys;
194
- const sync = useCallback(() => {
195
- editor.getEditorState().read(() => {
196
- const children = $getRoot().getChildren();
197
- const folded = foldedRef.current;
198
- const hidden = /* @__PURE__ */ new Set();
199
- const headings = [];
200
- for (let i = 0; i < children.length; i++) {
201
- const node = children[i];
202
- if (!$isHeadingNode(node)) continue;
203
- const level = HEADING_LEVELS[node.getTag()] ?? 6;
204
- const isFolded = folded.has(node.getKey());
205
- headings.push({ key: node.getKey(), folded: isFolded });
206
- if (!isFolded) continue;
207
- for (let j = i + 1; j < children.length; j++) {
208
- const sibling = children[j];
209
- if ($isHeadingNode(sibling) && (HEADING_LEVELS[sibling.getTag()] ?? 6) <= level) {
210
- break;
211
- }
212
- hidden.add(sibling.getKey());
213
- }
214
- }
215
- const selection = $getSelection2();
216
- if ($isRangeSelection2(selection)) {
217
- const topLevel = selection.anchor.getNode().getTopLevelElement();
218
- if (topLevel && hidden.has(topLevel.getKey())) {
219
- let node = topLevel.getPreviousSibling();
220
- while (node) {
221
- if ($isHeadingNode(node) && folded.has(node.getKey())) {
222
- const unfoldKey = node.getKey();
223
- setFoldedKeys((prev) => {
224
- const next = new Set(prev);
225
- next.delete(unfoldKey);
226
- return next;
227
- });
228
- return;
229
- }
230
- node = node.getPreviousSibling();
231
- }
232
- }
233
- }
234
- for (const child of children) {
235
- const element = editor.getElementByKey(child.getKey());
236
- if (!element) continue;
237
- const shouldHide = hidden.has(child.getKey());
238
- if (shouldHide) {
239
- element.style.display = "none";
240
- } else if (element.style.display === "none") {
241
- element.style.display = "";
242
- }
243
- }
244
- setButtons(
245
- headings.map(({ key, folded: isFolded }) => {
246
- const element = editor.getElementByKey(key);
247
- element?.classList.toggle("zui-heading-folded", isFolded);
248
- return {
249
- key,
250
- folded: isFolded,
251
- top: element?.offsetTop ?? 0,
252
- height: element?.offsetHeight ?? 0
253
- };
254
- })
255
- );
256
- });
257
- }, [editor]);
258
- useEffect4(() => {
259
- sync();
260
- const unregister = editor.registerUpdateListener(sync);
261
- const rootElement = editor.getRootElement();
262
- const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(sync) : null;
263
- if (rootElement && observer) observer.observe(rootElement);
264
- return () => {
265
- unregister();
266
- observer?.disconnect();
267
- };
268
- }, [editor, sync, foldedKeys]);
269
- const toggle = useCallback((key) => {
270
- setFoldedKeys((prev) => {
271
- const next = new Set(prev);
272
- if (next.has(key)) next.delete(key);
273
- else next.add(key);
274
- return next;
275
- });
276
- }, []);
277
- return /* @__PURE__ */ jsx("div", { className: "zui-text-editor-fold-gutter", children: buttons.map(({ key, folded, top, height }) => /* @__PURE__ */ jsx(
278
- "button",
279
- {
280
- type: "button",
281
- className: `zui-text-editor-fold ${folded ? "is-folded" : ""}`,
282
- style: { top: top + Math.max(0, (Math.min(height, 44) - 18) / 2) },
283
- title: folded ? "Expand section" : "Collapse section",
284
- "aria-label": folded ? "Expand section" : "Collapse section",
285
- "aria-expanded": !folded,
286
- onClick: () => toggle(key),
287
- children: /* @__PURE__ */ jsx(
288
- "svg",
289
- {
290
- viewBox: "0 0 20 20",
291
- width: "12",
292
- height: "12",
293
- fill: "none",
294
- stroke: "currentColor",
295
- strokeWidth: "2",
296
- strokeLinecap: "round",
297
- strokeLinejoin: "round",
298
- children: /* @__PURE__ */ jsx("path", { d: "M6 8l4 4 4-4" })
299
- }
300
- )
301
- },
302
- key
303
- )) });
304
- }
305
-
306
174
  // src/plugins/MarkdownSyncPlugin.tsx
307
- import { useEffect as useEffect5, useRef as useRef2 } from "react";
308
- import { useLexicalComposerContext as useLexicalComposerContext5 } from "@lexical/react/LexicalComposerContext";
175
+ import { useEffect as useEffect4, useRef } from "react";
176
+ import { useLexicalComposerContext as useLexicalComposerContext4 } from "@lexical/react/LexicalComposerContext";
309
177
  import {
310
178
  $convertFromMarkdownString,
311
179
  $convertToMarkdownString
@@ -315,11 +183,11 @@ function MarkdownSyncPlugin({
315
183
  onChange,
316
184
  transformers
317
185
  }) {
318
- const [editor] = useLexicalComposerContext5();
319
- const lastMarkdownRef = useRef2("");
320
- const onChangeRef = useRef2(onChange);
186
+ const [editor] = useLexicalComposerContext4();
187
+ const lastMarkdownRef = useRef("");
188
+ const onChangeRef = useRef(onChange);
321
189
  onChangeRef.current = onChange;
322
- useEffect5(() => {
190
+ useEffect4(() => {
323
191
  if (initialMarkdown && initialMarkdown !== lastMarkdownRef.current) {
324
192
  lastMarkdownRef.current = initialMarkdown;
325
193
  editor.update(() => {
@@ -327,7 +195,7 @@ function MarkdownSyncPlugin({
327
195
  }, { tag: "initial-load" });
328
196
  }
329
197
  }, [editor, initialMarkdown]);
330
- useEffect5(() => {
198
+ useEffect4(() => {
331
199
  return editor.registerUpdateListener(
332
200
  ({ editorState, dirtyElements, dirtyLeaves, tags }) => {
333
201
  if (dirtyElements.size === 0 && dirtyLeaves.size === 0) return;
@@ -342,145 +210,101 @@ function MarkdownSyncPlugin({
342
210
  return null;
343
211
  }
344
212
 
345
- // src/plugins/OutlinePlugin.tsx
346
- import { useCallback as useCallback2, useEffect as useEffect6, useState as useState2 } from "react";
347
- import { useLexicalComposerContext as useLexicalComposerContext6 } from "@lexical/react/LexicalComposerContext";
348
- import {
349
- TableOfContentsPlugin
350
- } from "@lexical/react/LexicalTableOfContentsPlugin";
351
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
352
- var INDENT_PER_LEVEL = {
353
- h1: 0,
354
- h2: 1,
355
- h3: 2,
356
- h4: 3,
357
- h5: 4,
358
- h6: 5
359
- };
360
- function OutlinePlugin() {
361
- const [editor] = useLexicalComposerContext6();
362
- const [collapsed, setCollapsed] = useState2(false);
363
- const [activeKey, setActiveKey] = useState2(null);
364
- useEffect6(() => {
365
- const rootElement = editor.getRootElement();
366
- const scroller = rootElement?.closest(".zui-text-editor");
367
- if (!rootElement || !(scroller instanceof HTMLElement)) return;
368
- let frame = 0;
369
- const updateActive = () => {
370
- cancelAnimationFrame(frame);
371
- frame = requestAnimationFrame(() => {
372
- const headings = rootElement.querySelectorAll(
373
- "h1, h2, h3, h4, h5, h6"
374
- );
375
- const threshold = scroller.scrollTop + 80;
376
- let current = null;
377
- for (const el of headings) {
378
- if (el.offsetTop <= threshold) {
379
- current = el.getAttribute("data-outline-key");
380
- }
381
- }
382
- setActiveKey(current);
383
- });
384
- };
385
- updateActive();
386
- scroller.addEventListener("scroll", updateActive, { passive: true });
387
- const unregister = editor.registerUpdateListener(updateActive);
388
- return () => {
389
- cancelAnimationFrame(frame);
390
- scroller.removeEventListener("scroll", updateActive);
391
- unregister();
392
- };
393
- }, [editor]);
394
- const scrollTo = useCallback2(
395
- (key) => {
396
- editor.getEditorState().read(() => {
397
- const element = editor.getElementByKey(key);
398
- element?.scrollIntoView({ behavior: "smooth", block: "start" });
399
- });
400
- },
401
- [editor]
402
- );
403
- return /* @__PURE__ */ jsx2(TableOfContentsPlugin, { children: (entries) => {
404
- for (const [key] of entries) {
405
- editor.getElementByKey(key)?.setAttribute("data-outline-key", key);
406
- }
407
- return /* @__PURE__ */ jsxs(
408
- "div",
409
- {
410
- className: `zui-text-editor-outline ${collapsed ? "is-collapsed" : ""}`,
411
- children: [
412
- /* @__PURE__ */ jsx2(
413
- "button",
414
- {
415
- type: "button",
416
- className: "zui-text-editor-outline-toggle",
417
- title: collapsed ? "Show outline" : "Hide outline",
418
- "aria-label": collapsed ? "Show outline" : "Hide outline",
419
- "aria-expanded": !collapsed,
420
- onClick: () => setCollapsed((c) => !c),
421
- children: /* @__PURE__ */ jsx2(
422
- "svg",
423
- {
424
- viewBox: "0 0 20 20",
425
- width: "14",
426
- height: "14",
427
- fill: "none",
428
- stroke: "currentColor",
429
- strokeWidth: "1.8",
430
- strokeLinecap: "round",
431
- children: /* @__PURE__ */ jsx2("path", { d: "M4 5h12M4 10h8M4 15h10" })
432
- }
433
- )
434
- }
435
- ),
436
- !collapsed && /* @__PURE__ */ jsxs("nav", { className: "zui-text-editor-outline-list", "aria-label": "Table of contents", children: [
437
- entries.length === 0 && /* @__PURE__ */ jsx2("div", { className: "zui-text-editor-outline-empty", children: "No headings" }),
438
- entries.map(([key, text, tag]) => /* @__PURE__ */ jsx2(
439
- "button",
440
- {
441
- type: "button",
442
- className: `zui-text-editor-outline-item ${key === activeKey ? "is-active" : ""}`,
443
- style: {
444
- paddingLeft: `${0.5 + INDENT_PER_LEVEL[tag] * 0.75}rem`
445
- },
446
- onClick: () => scrollTo(key),
447
- children: text || "Untitled"
448
- },
449
- key
450
- ))
451
- ] })
452
- ]
453
- }
454
- );
455
- } });
456
- }
457
-
458
- // src/plugins/ToolbarPlugin.tsx
459
- import { useCallback as useCallback4, useEffect as useEffect8, useState as useState4 } from "react";
460
- import {
461
- $getSelection as $getSelection3,
462
- $isRangeSelection as $isRangeSelection3,
463
- FORMAT_TEXT_COMMAND
464
- } from "lexical";
465
- import { useLexicalComposerContext as useLexicalComposerContext8 } from "@lexical/react/LexicalComposerContext";
466
- import { INSERT_TABLE_COMMAND } from "@lexical/table";
467
- import { $insertNodeToNearestRoot } from "@lexical/utils";
468
-
469
- // src/nodes/DrawingNode.tsx
213
+ // src/nodes/FrontmatterNode.ts
470
214
  import {
471
215
  $applyNodeReplacement,
472
- DecoratorNode
473
- } from "lexical";
474
-
216
+ $createLineBreakNode,
217
+ $createTextNode,
218
+ ElementNode
219
+ } from "lexical";
220
+ var FrontmatterNode = class _FrontmatterNode extends ElementNode {
221
+ static getType() {
222
+ return "frontmatter";
223
+ }
224
+ static clone(node) {
225
+ return new _FrontmatterNode(node.__key);
226
+ }
227
+ constructor(key) {
228
+ super(key);
229
+ }
230
+ createDOM(config) {
231
+ const dom = document.createElement("div");
232
+ const className = config.theme.frontmatter;
233
+ dom.className = typeof className === "string" ? className : "zui-frontmatter";
234
+ return dom;
235
+ }
236
+ updateDOM() {
237
+ return false;
238
+ }
239
+ static importJSON(_serializedNode) {
240
+ return $createFrontmatterNode();
241
+ }
242
+ exportJSON() {
243
+ return {
244
+ ...super.exportJSON(),
245
+ type: "frontmatter",
246
+ version: 1
247
+ };
248
+ }
249
+ isInline() {
250
+ return false;
251
+ }
252
+ canBeEmpty() {
253
+ return false;
254
+ }
255
+ canIndent() {
256
+ return false;
257
+ }
258
+ };
259
+ function $createFrontmatterNode() {
260
+ return $applyNodeReplacement(new FrontmatterNode());
261
+ }
262
+ function $isFrontmatterNode(node) {
263
+ return node instanceof FrontmatterNode;
264
+ }
265
+ var FRONTMATTER_DELIMITER = /^---\s*$/;
266
+ var FRONTMATTER = {
267
+ dependencies: [FrontmatterNode],
268
+ export: (node) => {
269
+ if (!$isFrontmatterNode(node)) return null;
270
+ const body = node.getTextContent();
271
+ return body ? `---
272
+ ${body}
273
+ ---` : "---\n---";
274
+ },
275
+ regExpStart: FRONTMATTER_DELIMITER,
276
+ regExpEnd: FRONTMATTER_DELIMITER,
277
+ replace: (rootNode, children, _startMatch, _endMatch, linesInBetween, isImport) => {
278
+ if (!isImport || children != null || linesInBetween == null) return false;
279
+ if (rootNode.getChildrenSize() !== 0) return false;
280
+ const lines = [...linesInBetween];
281
+ while (lines.length > 0 && lines[0].length === 0) lines.shift();
282
+ while (lines.length > 0 && lines[lines.length - 1].length === 0) lines.pop();
283
+ const node = $createFrontmatterNode();
284
+ lines.forEach((line, index) => {
285
+ if (index > 0) node.append($createLineBreakNode());
286
+ node.append($createTextNode(line));
287
+ });
288
+ rootNode.append(node);
289
+ },
290
+ type: "multiline-element"
291
+ };
292
+
293
+ // src/nodes/DrawingNode.tsx
294
+ import {
295
+ $applyNodeReplacement as $applyNodeReplacement2,
296
+ DecoratorNode
297
+ } from "lexical";
298
+
475
299
  // src/components/DrawingCanvas.tsx
476
300
  import {
477
- useCallback as useCallback3,
478
- useEffect as useEffect7,
479
- useRef as useRef3,
480
- useState as useState3
301
+ useCallback,
302
+ useEffect as useEffect5,
303
+ useRef as useRef2,
304
+ useState
481
305
  } from "react";
482
306
  import { $getNodeByKey as $getNodeByKey2 } from "lexical";
483
- import { useLexicalComposerContext as useLexicalComposerContext7 } from "@lexical/react/LexicalComposerContext";
307
+ import { useLexicalComposerContext as useLexicalComposerContext5 } from "@lexical/react/LexicalComposerContext";
484
308
  import { useLexicalEditable } from "@lexical/react/useLexicalEditable";
485
309
 
486
310
  // src/components/drawingTypes.ts
@@ -791,7 +615,7 @@ function resolveBindings(shapes) {
791
615
  }
792
616
 
793
617
  // src/components/DrawingCanvas.tsx
794
- import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
618
+ import { jsx, jsxs } from "react/jsx-runtime";
795
619
  import { createElement } from "react";
796
620
  var MIN_HEIGHT = 120;
797
621
  var MAX_HEIGHT = 900;
@@ -825,7 +649,7 @@ function BoxTexts({
825
649
  opacity: 0.35,
826
650
  style: { userSelect: "none", pointerEvents: "none" }
827
651
  };
828
- return /* @__PURE__ */ jsxs2("g", { children: [
652
+ return /* @__PURE__ */ jsxs("g", { children: [
829
653
  hideField !== "label" && (shape.label ? labelLines.map((line, i) => /* @__PURE__ */ createElement(
830
654
  "text",
831
655
  {
@@ -838,7 +662,7 @@ function BoxTexts({
838
662
  opacity: 0.85
839
663
  },
840
664
  line
841
- )) : showHints && /* @__PURE__ */ jsx3("text", { ...hint, x: cx, y: b.y + SMALL_FONT_SIZE + 7, fontSize: SMALL_FONT_SIZE, children: "Label" })),
665
+ )) : showHints && /* @__PURE__ */ jsx("text", { ...hint, x: cx, y: b.y + SMALL_FONT_SIZE + 7, fontSize: SMALL_FONT_SIZE, children: "Label" })),
842
666
  hideField !== "text" && (shape.text ? mainLines.map((line, i) => /* @__PURE__ */ createElement(
843
667
  "text",
844
668
  {
@@ -849,7 +673,7 @@ function BoxTexts({
849
673
  fontSize: FONT_SIZE
850
674
  },
851
675
  line
852
- )) : showHints && /* @__PURE__ */ jsx3("text", { ...hint, x: cx, y: mainStart, fontSize: FONT_SIZE, children: "Text" })),
676
+ )) : showHints && /* @__PURE__ */ jsx("text", { ...hint, x: cx, y: mainStart, fontSize: FONT_SIZE, children: "Text" })),
853
677
  hideField !== "footer" && (shape.footer ? footerLines.map((line, i) => /* @__PURE__ */ createElement(
854
678
  "text",
855
679
  {
@@ -861,7 +685,7 @@ function BoxTexts({
861
685
  opacity: 0.65
862
686
  },
863
687
  line
864
- )) : showHints && /* @__PURE__ */ jsx3("text", { ...hint, x: cx, y: b.y + b.h - 9, fontSize: SMALL_FONT_SIZE, children: "Footer" }))
688
+ )) : showHints && /* @__PURE__ */ jsx("text", { ...hint, x: cx, y: b.y + b.h - 9, fontSize: SMALL_FONT_SIZE, children: "Footer" }))
865
689
  ] });
866
690
  }
867
691
  function ShapeView({
@@ -878,8 +702,8 @@ function ShapeView({
878
702
  switch (shape.type) {
879
703
  case "rect": {
880
704
  const b = bbox(shape);
881
- return /* @__PURE__ */ jsxs2("g", { children: [
882
- /* @__PURE__ */ jsx3(
705
+ return /* @__PURE__ */ jsxs("g", { children: [
706
+ /* @__PURE__ */ jsx(
883
707
  "rect",
884
708
  {
885
709
  ...common,
@@ -891,13 +715,13 @@ function ShapeView({
891
715
  fill: shape.fill
892
716
  }
893
717
  ),
894
- /* @__PURE__ */ jsx3(BoxTexts, { shape, hideField, showHints })
718
+ /* @__PURE__ */ jsx(BoxTexts, { shape, hideField, showHints })
895
719
  ] });
896
720
  }
897
721
  case "ellipse": {
898
722
  const b = bbox(shape);
899
- return /* @__PURE__ */ jsxs2("g", { children: [
900
- /* @__PURE__ */ jsx3(
723
+ return /* @__PURE__ */ jsxs("g", { children: [
724
+ /* @__PURE__ */ jsx(
901
725
  "ellipse",
902
726
  {
903
727
  ...common,
@@ -908,13 +732,13 @@ function ShapeView({
908
732
  fill: shape.fill
909
733
  }
910
734
  ),
911
- /* @__PURE__ */ jsx3(BoxTexts, { shape, hideField, showHints })
735
+ /* @__PURE__ */ jsx(BoxTexts, { shape, hideField, showHints })
912
736
  ] });
913
737
  }
914
738
  case "triangle":
915
739
  case "pentagon":
916
- return /* @__PURE__ */ jsxs2("g", { children: [
917
- /* @__PURE__ */ jsx3(
740
+ return /* @__PURE__ */ jsxs("g", { children: [
741
+ /* @__PURE__ */ jsx(
918
742
  "polygon",
919
743
  {
920
744
  ...common,
@@ -922,12 +746,12 @@ function ShapeView({
922
746
  fill: shape.fill
923
747
  }
924
748
  ),
925
- /* @__PURE__ */ jsx3(BoxTexts, { shape, hideField, showHints })
749
+ /* @__PURE__ */ jsx(BoxTexts, { shape, hideField, showHints })
926
750
  ] });
927
751
  case "line":
928
752
  case "arrow":
929
- return /* @__PURE__ */ jsxs2("g", { children: [
930
- /* @__PURE__ */ jsx3(
753
+ return /* @__PURE__ */ jsxs("g", { children: [
754
+ /* @__PURE__ */ jsx(
931
755
  "path",
932
756
  {
933
757
  ...common,
@@ -935,10 +759,10 @@ function ShapeView({
935
759
  fill: "none"
936
760
  }
937
761
  ),
938
- shape.text && hideField !== "text" && /* @__PURE__ */ jsx3(ConnectorLabel, { shape })
762
+ shape.text && hideField !== "text" && /* @__PURE__ */ jsx(ConnectorLabel, { shape })
939
763
  ] });
940
764
  case "text":
941
- return /* @__PURE__ */ jsx3(
765
+ return /* @__PURE__ */ jsx(
942
766
  "text",
943
767
  {
944
768
  x: shape.x,
@@ -947,7 +771,7 @@ function ShapeView({
947
771
  fontSize: FONT_SIZE,
948
772
  fontFamily: "ui-sans-serif, system-ui, sans-serif",
949
773
  style: { userSelect: "none", whiteSpace: "pre" },
950
- children: (shape.text ?? "").split("\n").map((line, i) => /* @__PURE__ */ jsx3("tspan", { x: shape.x, dy: i === 0 ? 0 : FONT_SIZE * 1.35, children: line }, i))
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))
951
775
  }
952
776
  );
953
777
  }
@@ -959,8 +783,8 @@ function ConnectorLabel({ shape }) {
959
783
  const { x: midX, y: midY } = connectorMidpoint(shape);
960
784
  const lineH = CONNECTOR_FONT_SIZE * LINE_HEIGHT;
961
785
  const startY = midY - (lines.length - 1) * lineH / 2 + CONNECTOR_FONT_SIZE * 0.35;
962
- return /* @__PURE__ */ jsxs2("g", { children: [
963
- /* @__PURE__ */ jsx3(
786
+ return /* @__PURE__ */ jsxs("g", { children: [
787
+ /* @__PURE__ */ jsx(
964
788
  "rect",
965
789
  {
966
790
  x: midX - size.w / 2 - 5,
@@ -972,7 +796,7 @@ function ConnectorLabel({ shape }) {
972
796
  opacity: 0.92
973
797
  }
974
798
  ),
975
- lines.map((line, i) => /* @__PURE__ */ jsx3(
799
+ lines.map((line, i) => /* @__PURE__ */ jsx(
976
800
  "text",
977
801
  {
978
802
  x: midX,
@@ -989,20 +813,20 @@ function ConnectorLabel({ shape }) {
989
813
  ] });
990
814
  }
991
815
  var TOOL_ICONS = {
992
- select: /* @__PURE__ */ jsx3("path", { d: "M4 2l12 6.5-5.2 1.6L8 16z", fill: "currentColor", stroke: "none" }),
993
- rect: /* @__PURE__ */ jsx3("rect", { x: "3", y: "4.5", width: "14", height: "11", rx: "2" }),
994
- ellipse: /* @__PURE__ */ jsx3("ellipse", { cx: "10", cy: "10", rx: "7", ry: "5.5" }),
995
- triangle: /* @__PURE__ */ jsx3("path", { d: "M10 3.5L17 16.5H3z", strokeLinejoin: "round" }),
996
- pentagon: /* @__PURE__ */ jsx3("path", { d: "M10 3L16.8 8.1L14.2 16.2H5.8L3.2 8.1z", strokeLinejoin: "round" }),
997
- arrow: /* @__PURE__ */ jsxs2("g", { children: [
998
- /* @__PURE__ */ jsx3("path", { d: "M4 16L16 4" }),
999
- /* @__PURE__ */ jsx3("path", { d: "M9 4h7v7" })
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" })
1000
824
  ] }),
1001
- line: /* @__PURE__ */ jsx3("path", { d: "M4 16L16 4" }),
1002
- text: /* @__PURE__ */ jsxs2("g", { children: [
1003
- /* @__PURE__ */ jsx3("path", { d: "M4 5V3.5h12V5" }),
1004
- /* @__PURE__ */ jsx3("path", { d: "M10 3.5V16.5" }),
1005
- /* @__PURE__ */ jsx3("path", { d: "M7 16.5h6" })
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" })
1006
830
  ] })
1007
831
  };
1008
832
  function bindEndpoints(shape, shapes) {
@@ -1026,23 +850,23 @@ var TOOLS = [
1026
850
  { tool: "text", label: "Text" }
1027
851
  ];
1028
852
  function DrawingCanvas({ nodeKey, data }) {
1029
- const [editor] = useLexicalComposerContext7();
853
+ const [editor] = useLexicalComposerContext5();
1030
854
  const isEditable = useLexicalEditable();
1031
- const [shapes, setShapes] = useState3(data.shapes);
1032
- const [height, setHeight] = useState3(data.height);
1033
- const [tool, setTool] = useState3("select");
1034
- const [selectedId, setSelectedId] = useState3(null);
1035
- const [editingText, setEditingText] = useState3(null);
1036
- const [stroke, setStroke] = useState3(STROKE_COLORS[0]);
1037
- const [fill, setFill] = useState3(FILL_COLORS[0]);
1038
- const svgRef = useRef3(null);
1039
- const dragRef = useRef3(null);
1040
- const lastCommittedRef = useRef3(serializeDrawingData(data));
1041
- const shapesRef = useRef3(shapes);
855
+ const [shapes, setShapes] = useState(data.shapes);
856
+ const [height, setHeight] = useState(data.height);
857
+ const [tool, setTool] = useState("select");
858
+ const [selectedId, setSelectedId] = useState(null);
859
+ const [editingText, setEditingText] = useState(null);
860
+ const [stroke, setStroke] = useState(STROKE_COLORS[0]);
861
+ const [fill, setFill] = useState(FILL_COLORS[0]);
862
+ const svgRef = useRef2(null);
863
+ const dragRef = useRef2(null);
864
+ const lastCommittedRef = useRef2(serializeDrawingData(data));
865
+ const shapesRef = useRef2(shapes);
1042
866
  shapesRef.current = shapes;
1043
- const heightRef = useRef3(height);
867
+ const heightRef = useRef2(height);
1044
868
  heightRef.current = height;
1045
- useEffect7(() => {
869
+ useEffect5(() => {
1046
870
  const incoming = serializeDrawingData(data);
1047
871
  if (incoming !== lastCommittedRef.current) {
1048
872
  lastCommittedRef.current = incoming;
@@ -1052,7 +876,7 @@ function DrawingCanvas({ nodeKey, data }) {
1052
876
  setEditingText(null);
1053
877
  }
1054
878
  }, [data]);
1055
- const commit = useCallback3(
879
+ const commit = useCallback(
1056
880
  (nextShapes, nextHeight) => {
1057
881
  const payload = {
1058
882
  version: 1,
@@ -1071,7 +895,7 @@ function DrawingCanvas({ nodeKey, data }) {
1071
895
  },
1072
896
  [editor, nodeKey]
1073
897
  );
1074
- const updateShapes = useCallback3(
898
+ const updateShapes = useCallback(
1075
899
  (updater, options) => {
1076
900
  setShapes((prev) => {
1077
901
  const next = resolveBindings(updater(prev));
@@ -1081,17 +905,17 @@ function DrawingCanvas({ nodeKey, data }) {
1081
905
  },
1082
906
  [commit]
1083
907
  );
1084
- const getPoint = useCallback3((e) => {
908
+ const getPoint = useCallback((e) => {
1085
909
  const rect = svgRef.current?.getBoundingClientRect();
1086
910
  if (!rect) return { x: 0, y: 0 };
1087
911
  return { x: e.clientX - rect.left, y: e.clientY - rect.top };
1088
912
  }, []);
1089
913
  const selectedShape = shapes.find((s) => s.id === selectedId) ?? null;
1090
- const startTextEditing = useCallback3((id, field) => {
914
+ const startTextEditing = useCallback((id, field) => {
1091
915
  setEditingText({ id, field });
1092
916
  setSelectedId(id);
1093
917
  }, []);
1094
- const handleBackgroundPointerDown = useCallback3(
918
+ const handleBackgroundPointerDown = useCallback(
1095
919
  (e) => {
1096
920
  if (!isEditable || editingText) return;
1097
921
  if (e.button !== 0) return;
@@ -1151,7 +975,7 @@ function DrawingCanvas({ nodeKey, data }) {
1151
975
  startTextEditing
1152
976
  ]
1153
977
  );
1154
- const handleShapePointerDown = useCallback3(
978
+ const handleShapePointerDown = useCallback(
1155
979
  (e, shape) => {
1156
980
  if (!isEditable || tool !== "select" || editingText) return;
1157
981
  if (e.button !== 0) return;
@@ -1170,7 +994,7 @@ function DrawingCanvas({ nodeKey, data }) {
1170
994
  },
1171
995
  [isEditable, tool, editingText, getPoint, selectedId]
1172
996
  );
1173
- const handleHandlePointerDown = useCallback3(
997
+ const handleHandlePointerDown = useCallback(
1174
998
  (e, drag) => {
1175
999
  if (!isEditable) return;
1176
1000
  if (e.button !== 0) return;
@@ -1186,7 +1010,7 @@ function DrawingCanvas({ nodeKey, data }) {
1186
1010
  },
1187
1011
  [isEditable, updateShapes]
1188
1012
  );
1189
- const handlePointerMove = useCallback3(
1013
+ const handlePointerMove = useCallback(
1190
1014
  (e) => {
1191
1015
  const drag = dragRef.current;
1192
1016
  if (!drag) return;
@@ -1277,7 +1101,7 @@ function DrawingCanvas({ nodeKey, data }) {
1277
1101
  },
1278
1102
  [getPoint, updateShapes]
1279
1103
  );
1280
- const handlePointerUp = useCallback3(() => {
1104
+ const handlePointerUp = useCallback(() => {
1281
1105
  const drag = dragRef.current;
1282
1106
  dragRef.current = null;
1283
1107
  if (!drag) return;
@@ -1330,7 +1154,7 @@ function DrawingCanvas({ nodeKey, data }) {
1330
1154
  }
1331
1155
  updateShapes((prev) => prev.map(normalize), { commit: true });
1332
1156
  }, [commit, updateShapes, startTextEditing]);
1333
- const deleteSelected = useCallback3(() => {
1157
+ const deleteSelected = useCallback(() => {
1334
1158
  if (!selectedId) return;
1335
1159
  setEditingText(null);
1336
1160
  setSelectedId(null);
@@ -1338,7 +1162,7 @@ function DrawingCanvas({ nodeKey, data }) {
1338
1162
  commit: true
1339
1163
  });
1340
1164
  }, [selectedId, updateShapes]);
1341
- const handleKeyDown = useCallback3(
1165
+ const handleKeyDown = useCallback(
1342
1166
  (e) => {
1343
1167
  if (!isEditable || editingText) return;
1344
1168
  if ((e.key === "Delete" || e.key === "Backspace") && selectedId) {
@@ -1366,7 +1190,7 @@ function DrawingCanvas({ nodeKey, data }) {
1366
1190
  startTextEditing
1367
1191
  ]
1368
1192
  );
1369
- const applyStroke = useCallback3(
1193
+ const applyStroke = useCallback(
1370
1194
  (color) => {
1371
1195
  setStroke(color);
1372
1196
  if (selectedId) {
@@ -1378,7 +1202,7 @@ function DrawingCanvas({ nodeKey, data }) {
1378
1202
  },
1379
1203
  [selectedId, updateShapes]
1380
1204
  );
1381
- const applyFill = useCallback3(
1205
+ const applyFill = useCallback(
1382
1206
  (color) => {
1383
1207
  setFill(color);
1384
1208
  if (selectedId) {
@@ -1390,7 +1214,7 @@ function DrawingCanvas({ nodeKey, data }) {
1390
1214
  },
1391
1215
  [selectedId, updateShapes]
1392
1216
  );
1393
- const applyRouting = useCallback3(
1217
+ const applyRouting = useCallback(
1394
1218
  (elbow) => {
1395
1219
  if (!selectedId) return;
1396
1220
  updateShapes(
@@ -1407,7 +1231,7 @@ function DrawingCanvas({ nodeKey, data }) {
1407
1231
  },
1408
1232
  [selectedId, updateShapes]
1409
1233
  );
1410
- const addWaypoint = useCallback3(
1234
+ const addWaypoint = useCallback(
1411
1235
  (e, shapeId, segmentIndex, point) => {
1412
1236
  if (!isEditable) return;
1413
1237
  if (e.button !== 0) return;
@@ -1429,7 +1253,7 @@ function DrawingCanvas({ nodeKey, data }) {
1429
1253
  },
1430
1254
  [isEditable, updateShapes]
1431
1255
  );
1432
- const removeWaypoint = useCallback3(
1256
+ const removeWaypoint = useCallback(
1433
1257
  (shapeId, index) => {
1434
1258
  updateShapes(
1435
1259
  (prev) => prev.map((s) => {
@@ -1442,7 +1266,7 @@ function DrawingCanvas({ nodeKey, data }) {
1442
1266
  },
1443
1267
  [updateShapes]
1444
1268
  );
1445
- const applyDirection = useCallback3(
1269
+ const applyDirection = useCallback(
1446
1270
  (bidirectional) => {
1447
1271
  if (!selectedId) return;
1448
1272
  updateShapes(
@@ -1454,7 +1278,7 @@ function DrawingCanvas({ nodeKey, data }) {
1454
1278
  },
1455
1279
  [selectedId, updateShapes]
1456
1280
  );
1457
- const commitText = useCallback3(
1281
+ const commitText = useCallback(
1458
1282
  (id, field, value) => {
1459
1283
  setEditingText(null);
1460
1284
  updateShapes(
@@ -1475,15 +1299,15 @@ function DrawingCanvas({ nodeKey, data }) {
1475
1299
  const editingShape = shapes.find((s) => s.id === editingText?.id) ?? null;
1476
1300
  const showFill = selectedShape != null ? isBoxType(selectedShape.type) : tool !== "select" && isBoxType(tool);
1477
1301
  const canvasCursor = tool === "select" ? "default" : tool === "text" ? "text" : "crosshair";
1478
- return /* @__PURE__ */ jsxs2(
1302
+ return /* @__PURE__ */ jsxs(
1479
1303
  "div",
1480
1304
  {
1481
1305
  className: "zui-drawing-canvas",
1482
1306
  tabIndex: isEditable ? 0 : void 0,
1483
1307
  onKeyDown: handleKeyDown,
1484
1308
  children: [
1485
- isEditable && /* @__PURE__ */ jsxs2("div", { className: "zui-drawing-toolbar", onPointerDown: (e) => e.stopPropagation(), children: [
1486
- /* @__PURE__ */ jsx3("div", { className: "zui-drawing-toolbar-group", children: TOOLS.map(({ tool: t, label }) => /* @__PURE__ */ jsx3(
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(
1487
1311
  "button",
1488
1312
  {
1489
1313
  type: "button",
@@ -1494,7 +1318,7 @@ function DrawingCanvas({ nodeKey, data }) {
1494
1318
  setTool(t);
1495
1319
  if (t !== "select") setSelectedId(null);
1496
1320
  },
1497
- children: /* @__PURE__ */ jsx3(
1321
+ children: /* @__PURE__ */ jsx(
1498
1322
  "svg",
1499
1323
  {
1500
1324
  viewBox: "0 0 20 20",
@@ -1511,9 +1335,9 @@ function DrawingCanvas({ nodeKey, data }) {
1511
1335
  },
1512
1336
  t
1513
1337
  )) }),
1514
- /* @__PURE__ */ jsxs2("div", { className: "zui-drawing-toolbar-group", children: [
1515
- /* @__PURE__ */ jsx3("span", { className: "zui-drawing-swatch-label", children: "Stroke" }),
1516
- STROKE_COLORS.map((color) => /* @__PURE__ */ jsx3(
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(
1517
1341
  "button",
1518
1342
  {
1519
1343
  type: "button",
@@ -1526,9 +1350,9 @@ function DrawingCanvas({ nodeKey, data }) {
1526
1350
  color
1527
1351
  ))
1528
1352
  ] }),
1529
- showFill && /* @__PURE__ */ jsxs2("div", { className: "zui-drawing-toolbar-group", children: [
1530
- /* @__PURE__ */ jsx3("span", { className: "zui-drawing-swatch-label", children: "Fill" }),
1531
- FILL_COLORS.map((color) => /* @__PURE__ */ jsx3(
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(
1532
1356
  "button",
1533
1357
  {
1534
1358
  type: "button",
@@ -1541,8 +1365,8 @@ function DrawingCanvas({ nodeKey, data }) {
1541
1365
  color
1542
1366
  ))
1543
1367
  ] }),
1544
- selectedShape && isConnectorType(selectedShape.type) && /* @__PURE__ */ jsxs2("div", { className: "zui-drawing-toolbar-group", children: [
1545
- /* @__PURE__ */ jsx3(
1368
+ selectedShape && isConnectorType(selectedShape.type) && /* @__PURE__ */ jsxs("div", { className: "zui-drawing-toolbar-group", children: [
1369
+ /* @__PURE__ */ jsx(
1546
1370
  "button",
1547
1371
  {
1548
1372
  type: "button",
@@ -1550,7 +1374,7 @@ function DrawingCanvas({ nodeKey, data }) {
1550
1374
  "aria-label": "Straight connector",
1551
1375
  className: `zui-drawing-tool ${selectedShape.routing !== "elbow" ? "is-active" : ""}`,
1552
1376
  onClick: () => applyRouting(false),
1553
- children: /* @__PURE__ */ jsx3(
1377
+ children: /* @__PURE__ */ jsx(
1554
1378
  "svg",
1555
1379
  {
1556
1380
  viewBox: "0 0 20 20",
@@ -1560,12 +1384,12 @@ function DrawingCanvas({ nodeKey, data }) {
1560
1384
  stroke: "currentColor",
1561
1385
  strokeWidth: "1.6",
1562
1386
  strokeLinecap: "round",
1563
- children: /* @__PURE__ */ jsx3("path", { d: "M4 16L16 4" })
1387
+ children: /* @__PURE__ */ jsx("path", { d: "M4 16L16 4" })
1564
1388
  }
1565
1389
  )
1566
1390
  }
1567
1391
  ),
1568
- /* @__PURE__ */ jsx3(
1392
+ /* @__PURE__ */ jsx(
1569
1393
  "button",
1570
1394
  {
1571
1395
  type: "button",
@@ -1573,7 +1397,7 @@ function DrawingCanvas({ nodeKey, data }) {
1573
1397
  "aria-label": "Elbow connector",
1574
1398
  className: `zui-drawing-tool ${selectedShape.routing === "elbow" ? "is-active" : ""}`,
1575
1399
  onClick: () => applyRouting(true),
1576
- children: /* @__PURE__ */ jsx3(
1400
+ children: /* @__PURE__ */ jsx(
1577
1401
  "svg",
1578
1402
  {
1579
1403
  viewBox: "0 0 20 20",
@@ -1584,14 +1408,14 @@ function DrawingCanvas({ nodeKey, data }) {
1584
1408
  strokeWidth: "1.6",
1585
1409
  strokeLinecap: "round",
1586
1410
  strokeLinejoin: "round",
1587
- children: /* @__PURE__ */ jsx3("path", { d: "M4 16v-6h12V4" })
1411
+ children: /* @__PURE__ */ jsx("path", { d: "M4 16v-6h12V4" })
1588
1412
  }
1589
1413
  )
1590
1414
  }
1591
1415
  )
1592
1416
  ] }),
1593
- selectedShape?.type === "arrow" && /* @__PURE__ */ jsxs2("div", { className: "zui-drawing-toolbar-group", children: [
1594
- /* @__PURE__ */ jsx3(
1417
+ selectedShape?.type === "arrow" && /* @__PURE__ */ jsxs("div", { className: "zui-drawing-toolbar-group", children: [
1418
+ /* @__PURE__ */ jsx(
1595
1419
  "button",
1596
1420
  {
1597
1421
  type: "button",
@@ -1599,7 +1423,7 @@ function DrawingCanvas({ nodeKey, data }) {
1599
1423
  "aria-label": "One-way arrow",
1600
1424
  className: `zui-drawing-tool ${!selectedShape.bidirectional ? "is-active" : ""}`,
1601
1425
  onClick: () => applyDirection(false),
1602
- children: /* @__PURE__ */ jsx3(
1426
+ children: /* @__PURE__ */ jsx(
1603
1427
  "svg",
1604
1428
  {
1605
1429
  viewBox: "0 0 20 20",
@@ -1610,12 +1434,12 @@ function DrawingCanvas({ nodeKey, data }) {
1610
1434
  strokeWidth: "1.6",
1611
1435
  strokeLinecap: "round",
1612
1436
  strokeLinejoin: "round",
1613
- children: /* @__PURE__ */ jsx3("path", { d: "M3 10h13M12 5.5L16.5 10L12 14.5" })
1437
+ children: /* @__PURE__ */ jsx("path", { d: "M3 10h13M12 5.5L16.5 10L12 14.5" })
1614
1438
  }
1615
1439
  )
1616
1440
  }
1617
1441
  ),
1618
- /* @__PURE__ */ jsx3(
1442
+ /* @__PURE__ */ jsx(
1619
1443
  "button",
1620
1444
  {
1621
1445
  type: "button",
@@ -1623,7 +1447,7 @@ function DrawingCanvas({ nodeKey, data }) {
1623
1447
  "aria-label": "Two-way arrow",
1624
1448
  className: `zui-drawing-tool ${selectedShape.bidirectional ? "is-active" : ""}`,
1625
1449
  onClick: () => applyDirection(true),
1626
- children: /* @__PURE__ */ jsx3(
1450
+ children: /* @__PURE__ */ jsx(
1627
1451
  "svg",
1628
1452
  {
1629
1453
  viewBox: "0 0 20 20",
@@ -1634,13 +1458,13 @@ function DrawingCanvas({ nodeKey, data }) {
1634
1458
  strokeWidth: "1.6",
1635
1459
  strokeLinecap: "round",
1636
1460
  strokeLinejoin: "round",
1637
- children: /* @__PURE__ */ jsx3("path", { d: "M3.5 10h13M8 5.5L3.5 10L8 14.5M12 5.5L16.5 10L12 14.5" })
1461
+ children: /* @__PURE__ */ jsx("path", { d: "M3.5 10h13M8 5.5L3.5 10L8 14.5M12 5.5L16.5 10L12 14.5" })
1638
1462
  }
1639
1463
  )
1640
1464
  }
1641
1465
  )
1642
1466
  ] }),
1643
- selectedShape && /* @__PURE__ */ jsx3("div", { className: "zui-drawing-toolbar-group", children: /* @__PURE__ */ jsx3(
1467
+ selectedShape && /* @__PURE__ */ jsx("div", { className: "zui-drawing-toolbar-group", children: /* @__PURE__ */ jsx(
1644
1468
  "button",
1645
1469
  {
1646
1470
  type: "button",
@@ -1648,7 +1472,7 @@ function DrawingCanvas({ nodeKey, data }) {
1648
1472
  "aria-label": "Delete shape",
1649
1473
  className: "zui-drawing-tool zui-drawing-tool-danger",
1650
1474
  onClick: deleteSelected,
1651
- children: /* @__PURE__ */ jsx3(
1475
+ children: /* @__PURE__ */ jsx(
1652
1476
  "svg",
1653
1477
  {
1654
1478
  viewBox: "0 0 20 20",
@@ -1658,13 +1482,13 @@ function DrawingCanvas({ nodeKey, data }) {
1658
1482
  stroke: "currentColor",
1659
1483
  strokeWidth: "1.6",
1660
1484
  strokeLinecap: "round",
1661
- children: /* @__PURE__ */ jsx3("path", { d: "M4 6h12M8 6V4h4v2M6 6l1 10h6l1-10M8.5 9v4M11.5 9v4" })
1485
+ children: /* @__PURE__ */ jsx("path", { d: "M4 6h12M8 6V4h4v2M6 6l1 10h6l1-10M8.5 9v4M11.5 9v4" })
1662
1486
  }
1663
1487
  )
1664
1488
  }
1665
1489
  ) })
1666
1490
  ] }),
1667
- /* @__PURE__ */ jsxs2(
1491
+ /* @__PURE__ */ jsxs(
1668
1492
  "svg",
1669
1493
  {
1670
1494
  ref: svgRef,
@@ -1691,7 +1515,7 @@ function DrawingCanvas({ nodeKey, data }) {
1691
1515
  }
1692
1516
  },
1693
1517
  children: [
1694
- shapes.map((shape) => /* @__PURE__ */ jsxs2(
1518
+ shapes.map((shape) => /* @__PURE__ */ jsxs(
1695
1519
  "g",
1696
1520
  {
1697
1521
  "data-shape-id": shape.id,
@@ -1700,7 +1524,7 @@ function DrawingCanvas({ nodeKey, data }) {
1700
1524
  },
1701
1525
  onPointerDown: (e) => handleShapePointerDown(e, shape),
1702
1526
  children: [
1703
- isConnectorType(shape.type) && /* @__PURE__ */ jsx3(
1527
+ isConnectorType(shape.type) && /* @__PURE__ */ jsx(
1704
1528
  "path",
1705
1529
  {
1706
1530
  d: connectorPath(shape),
@@ -1709,8 +1533,8 @@ function DrawingCanvas({ nodeKey, data }) {
1709
1533
  strokeWidth: 14
1710
1534
  }
1711
1535
  ),
1712
- (isBoxType(shape.type) || shape.type === "text") && /* @__PURE__ */ jsx3(HitArea, { shape }),
1713
- shape.id === editingText?.id && shape.type === "text" ? null : /* @__PURE__ */ jsx3(
1536
+ (isBoxType(shape.type) || shape.type === "text") && /* @__PURE__ */ jsx(HitArea, { shape }),
1537
+ shape.id === editingText?.id && shape.type === "text" ? null : /* @__PURE__ */ jsx(
1714
1538
  ShapeView,
1715
1539
  {
1716
1540
  shape,
@@ -1722,7 +1546,7 @@ function DrawingCanvas({ nodeKey, data }) {
1722
1546
  },
1723
1547
  shape.id
1724
1548
  )),
1725
- selectedShape && isEditable && !editingText && /* @__PURE__ */ jsx3(
1549
+ selectedShape && isEditable && !editingText && /* @__PURE__ */ jsx(
1726
1550
  SelectionOverlay,
1727
1551
  {
1728
1552
  shape: selectedShape,
@@ -1734,7 +1558,7 @@ function DrawingCanvas({ nodeKey, data }) {
1734
1558
  ]
1735
1559
  }
1736
1560
  ),
1737
- editingShape && editingText && /* @__PURE__ */ jsx3(
1561
+ editingShape && editingText && /* @__PURE__ */ jsx(
1738
1562
  TextEditOverlay,
1739
1563
  {
1740
1564
  shape: editingShape,
@@ -1743,7 +1567,7 @@ function DrawingCanvas({ nodeKey, data }) {
1743
1567
  },
1744
1568
  `${editingShape.id}:${editingText.field}`
1745
1569
  ),
1746
- isEditable && /* @__PURE__ */ jsx3(
1570
+ isEditable && /* @__PURE__ */ jsx(
1747
1571
  "div",
1748
1572
  {
1749
1573
  className: "zui-drawing-resize",
@@ -1782,7 +1606,7 @@ function DrawingCanvas({ nodeKey, data }) {
1782
1606
  }
1783
1607
  function HitArea({ shape }) {
1784
1608
  const b = bbox(shape);
1785
- return /* @__PURE__ */ jsx3(
1609
+ return /* @__PURE__ */ jsx(
1786
1610
  "rect",
1787
1611
  {
1788
1612
  x: b.x,
@@ -1816,8 +1640,8 @@ function SelectionOverlay({
1816
1640
  if (hasElbowHandle && i === 1) return [];
1817
1641
  return [{ index: i, x: (p.x + q.x) / 2, y: (p.y + q.y) / 2 }];
1818
1642
  });
1819
- return /* @__PURE__ */ jsxs2("g", { children: [
1820
- ghosts.map(({ index, x, y }) => /* @__PURE__ */ jsx3(
1643
+ return /* @__PURE__ */ jsxs("g", { children: [
1644
+ ghosts.map(({ index, x, y }) => /* @__PURE__ */ jsx(
1821
1645
  "circle",
1822
1646
  {
1823
1647
  cx: x,
@@ -1830,11 +1654,11 @@ function SelectionOverlay({
1830
1654
  opacity: 0.6,
1831
1655
  style: { cursor: "copy" },
1832
1656
  onPointerDown: (e) => onWaypointAdd(e, shape.id, index, { x, y }),
1833
- children: /* @__PURE__ */ jsx3("title", { children: "Drag to add a point" })
1657
+ children: /* @__PURE__ */ jsx("title", { children: "Drag to add a point" })
1834
1658
  },
1835
1659
  `ghost-${index}`
1836
1660
  )),
1837
- waypoints.map((p, i) => /* @__PURE__ */ jsx3(
1661
+ waypoints.map((p, i) => /* @__PURE__ */ jsx(
1838
1662
  "rect",
1839
1663
  {
1840
1664
  x: p.x - 4,
@@ -1855,11 +1679,11 @@ function SelectionOverlay({
1855
1679
  e.stopPropagation();
1856
1680
  onWaypointRemove(shape.id, i);
1857
1681
  },
1858
- children: /* @__PURE__ */ jsx3("title", { children: "Drag to move, double-click to remove" })
1682
+ children: /* @__PURE__ */ jsx("title", { children: "Drag to move, double-click to remove" })
1859
1683
  },
1860
1684
  `wp-${i}`
1861
1685
  )),
1862
- ends.map(({ end, x, y }) => /* @__PURE__ */ jsx3(
1686
+ ends.map(({ end, x, y }) => /* @__PURE__ */ jsx(
1863
1687
  "circle",
1864
1688
  {
1865
1689
  cx: x,
@@ -1878,7 +1702,7 @@ function SelectionOverlay({
1878
1702
  },
1879
1703
  end
1880
1704
  )),
1881
- elbowMid && /* @__PURE__ */ jsx3(
1705
+ elbowMid && /* @__PURE__ */ jsx(
1882
1706
  "rect",
1883
1707
  {
1884
1708
  x: elbowMid.x - 4,
@@ -1908,8 +1732,8 @@ function SelectionOverlay({
1908
1732
  { corner: "se", x: b.x + b.w + pad, y: b.y + b.h + pad }
1909
1733
  ];
1910
1734
  const resizable = shape.type !== "text";
1911
- return /* @__PURE__ */ jsxs2("g", { children: [
1912
- /* @__PURE__ */ jsx3(
1735
+ return /* @__PURE__ */ jsxs("g", { children: [
1736
+ /* @__PURE__ */ jsx(
1913
1737
  "rect",
1914
1738
  {
1915
1739
  x: b.x - pad,
@@ -1923,7 +1747,7 @@ function SelectionOverlay({
1923
1747
  pointerEvents: "none"
1924
1748
  }
1925
1749
  ),
1926
- resizable && corners.map(({ corner, x, y }) => /* @__PURE__ */ jsx3(
1750
+ resizable && corners.map(({ corner, x, y }) => /* @__PURE__ */ jsx(
1927
1751
  "rect",
1928
1752
  {
1929
1753
  x: x - 4,
@@ -1949,9 +1773,9 @@ function TextEditOverlay({
1949
1773
  onCommit
1950
1774
  }) {
1951
1775
  const original = shape[field] ?? "";
1952
- const [value, setValue] = useState3(original);
1953
- const ref = useRef3(null);
1954
- useEffect7(() => {
1776
+ const [value, setValue] = useState(original);
1777
+ const ref = useRef2(null);
1778
+ useEffect5(() => {
1955
1779
  ref.current?.focus();
1956
1780
  ref.current?.select();
1957
1781
  }, []);
@@ -1999,7 +1823,7 @@ function TextEditOverlay({
1999
1823
  });
2000
1824
  }
2001
1825
  const placeholder = field === "label" ? "Label" : field === "footer" ? "Footer" : "Text";
2002
- return /* @__PURE__ */ jsx3(
1826
+ return /* @__PURE__ */ jsx(
2003
1827
  "textarea",
2004
1828
  {
2005
1829
  ref,
@@ -2025,7 +1849,7 @@ function TextEditOverlay({
2025
1849
  }
2026
1850
 
2027
1851
  // src/nodes/DrawingNode.tsx
2028
- import { jsx as jsx4 } from "react/jsx-runtime";
1852
+ import { jsx as jsx2 } from "react/jsx-runtime";
2029
1853
  var DrawingNode = class _DrawingNode extends DecoratorNode {
2030
1854
  static getType() {
2031
1855
  return "drawing";
@@ -2089,11 +1913,11 @@ var DrawingNode = class _DrawingNode extends DecoratorNode {
2089
1913
  return false;
2090
1914
  }
2091
1915
  decorate(_editor, _config) {
2092
- return /* @__PURE__ */ jsx4(DrawingCanvas, { nodeKey: this.getKey(), data: this.getData() });
1916
+ return /* @__PURE__ */ jsx2(DrawingCanvas, { nodeKey: this.getKey(), data: this.getData() });
2093
1917
  }
2094
1918
  };
2095
1919
  function $createDrawingNode(data = serializeDrawingData(EMPTY_DRAWING)) {
2096
- return $applyNodeReplacement(new DrawingNode(data));
1920
+ return $applyNodeReplacement2(new DrawingNode(data));
2097
1921
  }
2098
1922
  function $isDrawingNode(node) {
2099
1923
  return node instanceof DrawingNode;
@@ -2119,243 +1943,6 @@ ${node.getLatest().__data}
2119
1943
  type: "multiline-element"
2120
1944
  };
2121
1945
 
2122
- // src/plugins/ToolbarPlugin.tsx
2123
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
2124
- var FORMAT_BUTTONS = [
2125
- {
2126
- format: "bold",
2127
- label: "Bold",
2128
- icon: /* @__PURE__ */ jsx5(
2129
- "path",
2130
- {
2131
- d: "M6 3.5h5a3 3 0 0 1 0 6H6zm0 6h6a3 3 0 0 1 0 6H6z",
2132
- strokeWidth: "1.8"
2133
- }
2134
- )
2135
- },
2136
- {
2137
- format: "italic",
2138
- label: "Italic",
2139
- icon: /* @__PURE__ */ jsx5("path", { d: "M8.5 3.5h6M5.5 16.5h6M11.5 3.5l-3 13", strokeWidth: "1.6" })
2140
- },
2141
- {
2142
- format: "strikethrough",
2143
- label: "Strikethrough",
2144
- icon: /* @__PURE__ */ jsx5(
2145
- "path",
2146
- {
2147
- 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",
2148
- strokeWidth: "1.6"
2149
- }
2150
- )
2151
- },
2152
- {
2153
- format: "code",
2154
- label: "Inline code",
2155
- icon: /* @__PURE__ */ jsx5("path", { d: "M7.5 6L4 10l3.5 4M12.5 6L16 10l-3.5 4", strokeWidth: "1.6" })
2156
- }
2157
- ];
2158
- function ToolbarPlugin() {
2159
- const [editor] = useLexicalComposerContext8();
2160
- const [activeFormats, setActiveFormats] = useState4(
2161
- /* @__PURE__ */ new Set()
2162
- );
2163
- useEffect8(() => {
2164
- return editor.registerUpdateListener(({ editorState }) => {
2165
- editorState.read(() => {
2166
- const selection = $getSelection3();
2167
- if (!$isRangeSelection3(selection)) {
2168
- setActiveFormats(/* @__PURE__ */ new Set());
2169
- return;
2170
- }
2171
- const next = /* @__PURE__ */ new Set();
2172
- for (const { format } of FORMAT_BUTTONS) {
2173
- if (selection.hasFormat(format)) next.add(format);
2174
- }
2175
- setActiveFormats(next);
2176
- });
2177
- });
2178
- }, [editor]);
2179
- const insertTable = useCallback4(() => {
2180
- editor.dispatchCommand(INSERT_TABLE_COMMAND, {
2181
- columns: "3",
2182
- rows: "3",
2183
- includeHeaders: { rows: true, columns: false }
2184
- });
2185
- }, [editor]);
2186
- const insertDrawing = useCallback4(() => {
2187
- editor.update(() => {
2188
- const drawing = $createDrawingNode();
2189
- $insertNodeToNearestRoot(drawing);
2190
- });
2191
- }, [editor]);
2192
- return /* @__PURE__ */ jsxs3("div", { className: "zui-text-editor-toolbar", children: [
2193
- FORMAT_BUTTONS.map(({ format, label, icon }) => /* @__PURE__ */ jsx5(
2194
- "button",
2195
- {
2196
- type: "button",
2197
- title: label,
2198
- "aria-label": label,
2199
- "aria-pressed": activeFormats.has(format),
2200
- className: `zui-text-editor-toolbar-button ${activeFormats.has(format) ? "is-active" : ""}`,
2201
- onMouseDown: (e) => e.preventDefault(),
2202
- onClick: () => editor.dispatchCommand(FORMAT_TEXT_COMMAND, format),
2203
- children: /* @__PURE__ */ jsx5(
2204
- "svg",
2205
- {
2206
- viewBox: "0 0 20 20",
2207
- width: "16",
2208
- height: "16",
2209
- fill: "none",
2210
- stroke: "currentColor",
2211
- strokeLinecap: "round",
2212
- strokeLinejoin: "round",
2213
- children: icon
2214
- }
2215
- )
2216
- },
2217
- format
2218
- )),
2219
- /* @__PURE__ */ jsx5("div", { className: "zui-text-editor-toolbar-divider" }),
2220
- /* @__PURE__ */ jsx5(
2221
- "button",
2222
- {
2223
- type: "button",
2224
- title: "Insert table",
2225
- "aria-label": "Insert table",
2226
- className: "zui-text-editor-toolbar-button",
2227
- onMouseDown: (e) => e.preventDefault(),
2228
- onClick: insertTable,
2229
- children: /* @__PURE__ */ jsxs3(
2230
- "svg",
2231
- {
2232
- viewBox: "0 0 20 20",
2233
- width: "16",
2234
- height: "16",
2235
- fill: "none",
2236
- stroke: "currentColor",
2237
- strokeWidth: "1.5",
2238
- strokeLinecap: "round",
2239
- children: [
2240
- /* @__PURE__ */ jsx5("rect", { x: "3", y: "3.5", width: "14", height: "13", rx: "1.5" }),
2241
- /* @__PURE__ */ jsx5("path", { d: "M3 8h14M8 8v8.5M13 8v8.5" })
2242
- ]
2243
- }
2244
- )
2245
- }
2246
- ),
2247
- /* @__PURE__ */ jsx5(
2248
- "button",
2249
- {
2250
- type: "button",
2251
- title: "Insert drawing",
2252
- "aria-label": "Insert drawing",
2253
- className: "zui-text-editor-toolbar-button",
2254
- onMouseDown: (e) => e.preventDefault(),
2255
- onClick: insertDrawing,
2256
- children: /* @__PURE__ */ jsxs3(
2257
- "svg",
2258
- {
2259
- viewBox: "0 0 20 20",
2260
- width: "16",
2261
- height: "16",
2262
- fill: "none",
2263
- stroke: "currentColor",
2264
- strokeWidth: "1.5",
2265
- strokeLinecap: "round",
2266
- strokeLinejoin: "round",
2267
- children: [
2268
- /* @__PURE__ */ jsx5("rect", { x: "3", y: "5", width: "8", height: "6", rx: "1.5" }),
2269
- /* @__PURE__ */ jsx5("path", { d: "M13.5 8h3M14.5 6.5L17.5 8l-3 1.5" }),
2270
- /* @__PURE__ */ jsx5("ellipse", { cx: "13", cy: "14.5", rx: "4", ry: "2.8" })
2271
- ]
2272
- }
2273
- )
2274
- }
2275
- )
2276
- ] });
2277
- }
2278
-
2279
- // src/nodes/FrontmatterNode.ts
2280
- import {
2281
- $applyNodeReplacement as $applyNodeReplacement2,
2282
- $createLineBreakNode,
2283
- $createTextNode,
2284
- ElementNode
2285
- } from "lexical";
2286
- var FrontmatterNode = class _FrontmatterNode extends ElementNode {
2287
- static getType() {
2288
- return "frontmatter";
2289
- }
2290
- static clone(node) {
2291
- return new _FrontmatterNode(node.__key);
2292
- }
2293
- constructor(key) {
2294
- super(key);
2295
- }
2296
- createDOM(config) {
2297
- const dom = document.createElement("div");
2298
- const className = config.theme.frontmatter;
2299
- dom.className = typeof className === "string" ? className : "zui-frontmatter";
2300
- return dom;
2301
- }
2302
- updateDOM() {
2303
- return false;
2304
- }
2305
- static importJSON(_serializedNode) {
2306
- return $createFrontmatterNode();
2307
- }
2308
- exportJSON() {
2309
- return {
2310
- ...super.exportJSON(),
2311
- type: "frontmatter",
2312
- version: 1
2313
- };
2314
- }
2315
- isInline() {
2316
- return false;
2317
- }
2318
- canBeEmpty() {
2319
- return false;
2320
- }
2321
- canIndent() {
2322
- return false;
2323
- }
2324
- };
2325
- function $createFrontmatterNode() {
2326
- return $applyNodeReplacement2(new FrontmatterNode());
2327
- }
2328
- function $isFrontmatterNode(node) {
2329
- return node instanceof FrontmatterNode;
2330
- }
2331
- var FRONTMATTER_DELIMITER = /^---\s*$/;
2332
- var FRONTMATTER = {
2333
- dependencies: [FrontmatterNode],
2334
- export: (node) => {
2335
- if (!$isFrontmatterNode(node)) return null;
2336
- const body = node.getTextContent();
2337
- return body ? `---
2338
- ${body}
2339
- ---` : "---\n---";
2340
- },
2341
- regExpStart: FRONTMATTER_DELIMITER,
2342
- regExpEnd: FRONTMATTER_DELIMITER,
2343
- replace: (rootNode, children, _startMatch, _endMatch, linesInBetween, isImport) => {
2344
- if (!isImport || children != null || linesInBetween == null) return false;
2345
- if (rootNode.getChildrenSize() !== 0) return false;
2346
- const lines = [...linesInBetween];
2347
- while (lines.length > 0 && lines[0].length === 0) lines.shift();
2348
- while (lines.length > 0 && lines[lines.length - 1].length === 0) lines.pop();
2349
- const node = $createFrontmatterNode();
2350
- lines.forEach((line, index) => {
2351
- if (index > 0) node.append($createLineBreakNode());
2352
- node.append($createTextNode(line));
2353
- });
2354
- rootNode.append(node);
2355
- },
2356
- type: "multiline-element"
2357
- };
2358
-
2359
1946
  // src/transformers/tableTransformer.ts
2360
1947
  import {
2361
1948
  $isParagraphNode as $isParagraphNode2,
@@ -2551,10 +2138,20 @@ var editorTheme = {
2551
2138
  drawing: "zui-drawing"
2552
2139
  };
2553
2140
 
2554
- // src/MarkdownEditor.tsx
2555
- import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
2141
+ // src/EditorRoot.tsx
2142
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
2556
2143
  var SYNC_TRANSFORMERS = [FRONTMATTER, DRAWING, CHECK_LIST, TABLE, ...TRANSFORMERS2];
2557
2144
  var SHORTCUT_TRANSFORMERS = [TABLE, ...TRANSFORMERS2.filter((t) => t !== CODE)];
2145
+ var EditorContext = createContext(null);
2146
+ function useEditorContext() {
2147
+ const ctx = useContext(EditorContext);
2148
+ if (!ctx) {
2149
+ throw new Error(
2150
+ "@zuilib/text-editor: this component must be rendered inside <MarkdownEditor> or <MarkdownEditor.Root>"
2151
+ );
2152
+ }
2153
+ return ctx;
2154
+ }
2558
2155
  function onError(error) {
2559
2156
  console.error(error);
2560
2157
  }
@@ -2574,49 +2171,38 @@ var editorNodes = [
2574
2171
  DrawingNode
2575
2172
  ];
2576
2173
  function ReadOnlyPlugin({ readOnly }) {
2577
- const [editor] = useLexicalComposerContext9();
2578
- useEffect9(() => {
2174
+ const [editor] = useLexicalComposerContext6();
2175
+ useEffect6(() => {
2579
2176
  editor.setEditable(!readOnly);
2580
2177
  }, [editor, readOnly]);
2581
2178
  return null;
2582
2179
  }
2583
- function MarkdownEditor({
2180
+ function EditorRoot({
2584
2181
  value,
2585
2182
  onChange,
2586
- placeholder = "Start writing...",
2587
2183
  readOnly = false,
2588
2184
  className,
2589
2185
  mode = "edit-md",
2590
2186
  autoFocus = false,
2591
- toolbar = true,
2592
- outline = false,
2593
- foldable = true
2187
+ children
2594
2188
  }) {
2595
- const latestValueRef = useRef4(value ?? "");
2596
- const [mountKey, setMountKey] = useState5(0);
2597
- const [capturedMarkdown, setCapturedMarkdown] = useState5(value ?? "");
2598
- useEffect9(() => {
2189
+ const latestValueRef = useRef3(value ?? "");
2190
+ const [mountKey, setMountKey] = useState2(0);
2191
+ const [capturedMarkdown, setCapturedMarkdown] = useState2(value ?? "");
2192
+ useEffect6(() => {
2599
2193
  if (value !== void 0) {
2600
2194
  latestValueRef.current = value;
2601
2195
  }
2602
2196
  }, [value]);
2603
- const handleTextChange = useCallback5(
2604
- (e) => {
2605
- const newValue = e.target.value;
2606
- latestValueRef.current = newValue;
2607
- onChange?.(newValue);
2608
- },
2609
- [onChange]
2610
- );
2611
- const handleLexicalChange = useCallback5(
2197
+ const handleChange = useCallback2(
2612
2198
  (newValue) => {
2613
2199
  latestValueRef.current = newValue;
2614
2200
  onChange?.(newValue);
2615
2201
  },
2616
2202
  [onChange]
2617
2203
  );
2618
- const prevModeRef = useRef4(mode);
2619
- useEffect9(() => {
2204
+ const prevModeRef = useRef3(mode);
2205
+ useEffect6(() => {
2620
2206
  if (prevModeRef.current === "edit-raw" && mode !== "edit-raw") {
2621
2207
  setCapturedMarkdown(latestValueRef.current);
2622
2208
  setMountKey((k) => k + 1);
@@ -2632,63 +2218,606 @@ function MarkdownEditor({
2632
2218
  }),
2633
2219
  []
2634
2220
  );
2221
+ const context = useMemo(
2222
+ () => ({
2223
+ mode,
2224
+ readOnly,
2225
+ autoFocus,
2226
+ rawValue: value ?? "",
2227
+ onRawChange: handleChange
2228
+ }),
2229
+ [mode, readOnly, autoFocus, value, handleChange]
2230
+ );
2231
+ 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: [
2233
+ children,
2234
+ !isRaw && /* @__PURE__ */ jsxs2(Fragment, { children: [
2235
+ /* @__PURE__ */ jsx3(
2236
+ MarkdownSyncPlugin,
2237
+ {
2238
+ initialMarkdown: mode === "view" ? value ?? "" : capturedMarkdown,
2239
+ onChange: handleChange,
2240
+ transformers: SYNC_TRANSFORMERS
2241
+ }
2242
+ ),
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, {})
2254
+ ] })
2255
+ ] }) }) }, mountKey);
2256
+ }
2257
+
2258
+ // src/EditorContent.tsx
2259
+ import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
2260
+ import { ContentEditable } from "@lexical/react/LexicalContentEditable";
2261
+ import { LexicalErrorBoundary } from "@lexical/react/LexicalErrorBoundary";
2262
+
2263
+ // src/plugins/FoldingPlugin.tsx
2264
+ import {
2265
+ useCallback as useCallback3,
2266
+ useEffect as useEffect7,
2267
+ useRef as useRef4,
2268
+ useState as useState3
2269
+ } from "react";
2270
+ import { $getRoot, $getSelection as $getSelection2, $isRangeSelection as $isRangeSelection2 } from "lexical";
2271
+ import { useLexicalComposerContext as useLexicalComposerContext7 } from "@lexical/react/LexicalComposerContext";
2272
+ import { $isHeadingNode } from "@lexical/rich-text";
2273
+ import { jsx as jsx4 } from "react/jsx-runtime";
2274
+ var HEADING_LEVELS = {
2275
+ h1: 1,
2276
+ h2: 2,
2277
+ h3: 3,
2278
+ h4: 4,
2279
+ h5: 5,
2280
+ h6: 6
2281
+ };
2282
+ function FoldingPlugin() {
2283
+ const [editor] = useLexicalComposerContext7();
2284
+ const [foldedKeys, setFoldedKeys] = useState3(/* @__PURE__ */ new Set());
2285
+ const [buttons, setButtons] = useState3([]);
2286
+ const foldedRef = useRef4(foldedKeys);
2287
+ foldedRef.current = foldedKeys;
2288
+ const sync = useCallback3(() => {
2289
+ editor.getEditorState().read(() => {
2290
+ const children = $getRoot().getChildren();
2291
+ const folded = foldedRef.current;
2292
+ const hidden = /* @__PURE__ */ new Set();
2293
+ const headings = [];
2294
+ for (let i = 0; i < children.length; i++) {
2295
+ const node = children[i];
2296
+ if (!$isHeadingNode(node)) continue;
2297
+ const level = HEADING_LEVELS[node.getTag()] ?? 6;
2298
+ const isFolded = folded.has(node.getKey());
2299
+ headings.push({ key: node.getKey(), folded: isFolded });
2300
+ if (!isFolded) continue;
2301
+ for (let j = i + 1; j < children.length; j++) {
2302
+ const sibling = children[j];
2303
+ if ($isHeadingNode(sibling) && (HEADING_LEVELS[sibling.getTag()] ?? 6) <= level) {
2304
+ break;
2305
+ }
2306
+ hidden.add(sibling.getKey());
2307
+ }
2308
+ }
2309
+ const selection = $getSelection2();
2310
+ if ($isRangeSelection2(selection)) {
2311
+ const topLevel = selection.anchor.getNode().getTopLevelElement();
2312
+ if (topLevel && hidden.has(topLevel.getKey())) {
2313
+ let node = topLevel.getPreviousSibling();
2314
+ while (node) {
2315
+ if ($isHeadingNode(node) && folded.has(node.getKey())) {
2316
+ const unfoldKey = node.getKey();
2317
+ setFoldedKeys((prev) => {
2318
+ const next = new Set(prev);
2319
+ next.delete(unfoldKey);
2320
+ return next;
2321
+ });
2322
+ return;
2323
+ }
2324
+ node = node.getPreviousSibling();
2325
+ }
2326
+ }
2327
+ }
2328
+ for (const child of children) {
2329
+ const element = editor.getElementByKey(child.getKey());
2330
+ if (!element) continue;
2331
+ const shouldHide = hidden.has(child.getKey());
2332
+ if (shouldHide) {
2333
+ element.style.display = "none";
2334
+ } else if (element.style.display === "none") {
2335
+ element.style.display = "";
2336
+ }
2337
+ }
2338
+ setButtons(
2339
+ headings.map(({ key, folded: isFolded }) => {
2340
+ const element = editor.getElementByKey(key);
2341
+ element?.classList.toggle("zui-heading-folded", isFolded);
2342
+ return {
2343
+ key,
2344
+ folded: isFolded,
2345
+ top: element?.offsetTop ?? 0,
2346
+ height: element?.offsetHeight ?? 0
2347
+ };
2348
+ })
2349
+ );
2350
+ });
2351
+ }, [editor]);
2352
+ useEffect7(() => {
2353
+ sync();
2354
+ const unregister = editor.registerUpdateListener(sync);
2355
+ const rootElement = editor.getRootElement();
2356
+ const observer = typeof ResizeObserver !== "undefined" ? new ResizeObserver(sync) : null;
2357
+ if (rootElement && observer) observer.observe(rootElement);
2358
+ return () => {
2359
+ unregister();
2360
+ observer?.disconnect();
2361
+ };
2362
+ }, [editor, sync, foldedKeys]);
2363
+ const toggle = useCallback3((key) => {
2364
+ setFoldedKeys((prev) => {
2365
+ const next = new Set(prev);
2366
+ if (next.has(key)) next.delete(key);
2367
+ else next.add(key);
2368
+ return next;
2369
+ });
2370
+ }, []);
2371
+ return /* @__PURE__ */ jsx4("div", { className: "zui-text-editor-fold-gutter", children: buttons.map(({ key, folded, top, height }) => /* @__PURE__ */ jsx4(
2372
+ "button",
2373
+ {
2374
+ type: "button",
2375
+ className: `zui-text-editor-fold ${folded ? "is-folded" : ""}`,
2376
+ style: { top: top + Math.max(0, (Math.min(height, 44) - 18) / 2) },
2377
+ title: folded ? "Expand section" : "Collapse section",
2378
+ "aria-label": folded ? "Expand section" : "Collapse section",
2379
+ "aria-expanded": !folded,
2380
+ onClick: () => toggle(key),
2381
+ children: /* @__PURE__ */ jsx4(
2382
+ "svg",
2383
+ {
2384
+ viewBox: "0 0 20 20",
2385
+ width: "12",
2386
+ height: "12",
2387
+ fill: "none",
2388
+ stroke: "currentColor",
2389
+ strokeWidth: "2",
2390
+ strokeLinecap: "round",
2391
+ strokeLinejoin: "round",
2392
+ children: /* @__PURE__ */ jsx4("path", { d: "M6 8l4 4 4-4" })
2393
+ }
2394
+ )
2395
+ },
2396
+ key
2397
+ )) });
2398
+ }
2399
+
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();
2635
2408
  if (mode === "edit-raw") {
2636
- return /* @__PURE__ */ jsx6("div", { className: `zui-text-editor ${className ?? ""}`, children: /* @__PURE__ */ jsx6(
2409
+ return /* @__PURE__ */ jsx5(
2637
2410
  "textarea",
2638
2411
  {
2639
2412
  className: "zui-text-editor-textarea",
2640
- value: value ?? "",
2641
- onChange: handleTextChange,
2413
+ value: rawValue,
2414
+ onChange: (e) => onRawChange(e.target.value),
2642
2415
  placeholder,
2643
2416
  readOnly,
2644
2417
  autoFocus,
2645
2418
  spellCheck: false
2646
2419
  }
2647
- ) });
2420
+ );
2648
2421
  }
2649
- return /* @__PURE__ */ jsx6(LexicalComposer, { initialConfig, children: /* @__PURE__ */ jsxs4("div", { className: `zui-text-editor ${className ?? ""}`, children: [
2650
- toolbar && mode === "edit-md" && !readOnly && /* @__PURE__ */ jsx6(ToolbarPlugin, {}),
2651
- /* @__PURE__ */ jsxs4("div", { className: "zui-text-editor-body", children: [
2652
- /* @__PURE__ */ jsxs4("div", { className: "zui-text-editor-main", children: [
2653
- /* @__PURE__ */ jsx6(
2654
- RichTextPlugin,
2655
- {
2656
- contentEditable: /* @__PURE__ */ jsx6(
2657
- ContentEditable,
2658
- {
2659
- className: "zui-text-editor-content",
2660
- "aria-placeholder": placeholder,
2661
- placeholder: /* @__PURE__ */ jsx6("div", { className: "zui-text-editor-placeholder", children: placeholder })
2662
- }
2663
- ),
2664
- ErrorBoundary: LexicalErrorBoundary
2665
- }
2666
- ),
2667
- foldable && /* @__PURE__ */ jsx6(FoldingPlugin, {})
2668
- ] }),
2669
- outline && /* @__PURE__ */ jsx6(OutlinePlugin, {})
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, {})
2670
2439
  ] }),
2671
- /* @__PURE__ */ jsx6(
2672
- MarkdownSyncPlugin,
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",
2673
2508
  {
2674
- initialMarkdown: mode === "view" ? value ?? "" : capturedMarkdown,
2675
- onChange: handleLexicalChange,
2676
- transformers: SYNC_TRANSFORMERS
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
+ ]
2677
2552
  }
2553
+ );
2554
+ } });
2555
+ }
2556
+
2557
+ // src/useMarkdownEditor.ts
2558
+ import { useCallback as useCallback5, useEffect as useEffect9, useState as useState5 } from "react";
2559
+ import {
2560
+ $getSelection as $getSelection3,
2561
+ $isRangeSelection as $isRangeSelection3,
2562
+ CAN_REDO_COMMAND,
2563
+ CAN_UNDO_COMMAND,
2564
+ COMMAND_PRIORITY_LOW as COMMAND_PRIORITY_LOW2,
2565
+ FORMAT_TEXT_COMMAND,
2566
+ REDO_COMMAND,
2567
+ UNDO_COMMAND
2568
+ } from "lexical";
2569
+ import { useLexicalComposerContext as useLexicalComposerContext9 } from "@lexical/react/LexicalComposerContext";
2570
+ import { INSERT_TABLE_COMMAND } from "@lexical/table";
2571
+ import { $insertNodeToNearestRoot, mergeRegister } from "@lexical/utils";
2572
+ var TRACKED_FORMATS = [
2573
+ "bold",
2574
+ "italic",
2575
+ "underline",
2576
+ "strikethrough",
2577
+ "code"
2578
+ ];
2579
+ function useMarkdownEditor() {
2580
+ const [editor] = useLexicalComposerContext9();
2581
+ const [activeFormats, setActiveFormats] = useState5(
2582
+ /* @__PURE__ */ new Set()
2583
+ );
2584
+ const [canUndo, setCanUndo] = useState5(false);
2585
+ const [canRedo, setCanRedo] = useState5(false);
2586
+ useEffect9(
2587
+ () => mergeRegister(
2588
+ editor.registerUpdateListener(({ editorState }) => {
2589
+ editorState.read(() => {
2590
+ const selection = $getSelection3();
2591
+ if (!$isRangeSelection3(selection)) {
2592
+ setActiveFormats(/* @__PURE__ */ new Set());
2593
+ return;
2594
+ }
2595
+ const next = /* @__PURE__ */ new Set();
2596
+ for (const format of TRACKED_FORMATS) {
2597
+ if (selection.hasFormat(format)) next.add(format);
2598
+ }
2599
+ setActiveFormats(next);
2600
+ });
2601
+ }),
2602
+ editor.registerCommand(
2603
+ CAN_UNDO_COMMAND,
2604
+ (payload) => {
2605
+ setCanUndo(payload);
2606
+ return false;
2607
+ },
2608
+ COMMAND_PRIORITY_LOW2
2609
+ ),
2610
+ editor.registerCommand(
2611
+ CAN_REDO_COMMAND,
2612
+ (payload) => {
2613
+ setCanRedo(payload);
2614
+ return false;
2615
+ },
2616
+ COMMAND_PRIORITY_LOW2
2617
+ )
2678
2618
  ),
2679
- /* @__PURE__ */ jsx6(HistoryPlugin, {}),
2680
- /* @__PURE__ */ jsx6(ListPlugin, {}),
2681
- /* @__PURE__ */ jsx6(CheckListPlugin, {}),
2682
- /* @__PURE__ */ jsx6(ChecklistShortcutPlugin, {}),
2683
- /* @__PURE__ */ jsx6(CodeBlockShortcutPlugin, {}),
2684
- /* @__PURE__ */ jsx6(CodeHighlightPlugin, {}),
2685
- /* @__PURE__ */ jsx6(TablePlugin, {}),
2686
- /* @__PURE__ */ jsx6(LinkPlugin, {}),
2687
- /* @__PURE__ */ jsx6(MarkdownShortcutPlugin, { transformers: SHORTCUT_TRANSFORMERS }),
2688
- /* @__PURE__ */ jsx6(ReadOnlyPlugin, { readOnly: readOnly || mode === "view" }),
2689
- autoFocus && /* @__PURE__ */ jsx6(AutoFocusPlugin, {})
2690
- ] }) }, mountKey);
2619
+ [editor]
2620
+ );
2621
+ const toggleFormat = useCallback5(
2622
+ (format) => {
2623
+ editor.dispatchCommand(FORMAT_TEXT_COMMAND, format);
2624
+ },
2625
+ [editor]
2626
+ );
2627
+ const insertTable = useCallback5(
2628
+ ({ rows = 3, columns = 3 } = {}) => {
2629
+ editor.dispatchCommand(INSERT_TABLE_COMMAND, {
2630
+ columns: String(columns),
2631
+ rows: String(rows),
2632
+ includeHeaders: { rows: true, columns: false }
2633
+ });
2634
+ },
2635
+ [editor]
2636
+ );
2637
+ const insertDrawing = useCallback5(() => {
2638
+ editor.update(() => {
2639
+ $insertNodeToNearestRoot($createDrawingNode());
2640
+ });
2641
+ }, [editor]);
2642
+ const undo = useCallback5(() => {
2643
+ editor.dispatchCommand(UNDO_COMMAND, void 0);
2644
+ }, [editor]);
2645
+ const redo = useCallback5(() => {
2646
+ editor.dispatchCommand(REDO_COMMAND, void 0);
2647
+ }, [editor]);
2648
+ return {
2649
+ editor,
2650
+ activeFormats,
2651
+ toggleFormat,
2652
+ insertTable,
2653
+ insertDrawing,
2654
+ canUndo,
2655
+ canRedo,
2656
+ undo,
2657
+ redo
2658
+ };
2659
+ }
2660
+
2661
+ // src/components/Toolbar.tsx
2662
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
2663
+ function Toolbar({ children, className }) {
2664
+ return /* @__PURE__ */ jsx7(
2665
+ "div",
2666
+ {
2667
+ className: `zui-text-editor-toolbar ${className ?? ""}`,
2668
+ role: "toolbar",
2669
+ children: children ?? /* @__PURE__ */ jsxs5(Fragment2, { children: [
2670
+ /* @__PURE__ */ jsx7(FormatButtons, {}),
2671
+ /* @__PURE__ */ jsx7(ToolbarDivider, {}),
2672
+ /* @__PURE__ */ jsx7(InsertButtons, {})
2673
+ ] })
2674
+ }
2675
+ );
2676
+ }
2677
+ function ToolbarDivider() {
2678
+ return /* @__PURE__ */ jsx7("div", { className: "zui-text-editor-toolbar-divider" });
2679
+ }
2680
+ function ToolbarButton({
2681
+ label,
2682
+ onClick,
2683
+ children,
2684
+ active = false,
2685
+ disabled = false,
2686
+ className
2687
+ }) {
2688
+ return /* @__PURE__ */ jsx7(
2689
+ "button",
2690
+ {
2691
+ type: "button",
2692
+ title: label,
2693
+ "aria-label": label,
2694
+ "aria-pressed": active,
2695
+ disabled,
2696
+ className: `zui-text-editor-toolbar-button ${active ? "is-active" : ""} ${className ?? ""}`,
2697
+ onMouseDown: (e) => e.preventDefault(),
2698
+ onClick,
2699
+ children
2700
+ }
2701
+ );
2702
+ }
2703
+ function Icon({ children, strokeWidth = 1.5 }) {
2704
+ return /* @__PURE__ */ jsx7(
2705
+ "svg",
2706
+ {
2707
+ viewBox: "0 0 20 20",
2708
+ width: "16",
2709
+ height: "16",
2710
+ fill: "none",
2711
+ stroke: "currentColor",
2712
+ strokeWidth,
2713
+ strokeLinecap: "round",
2714
+ strokeLinejoin: "round",
2715
+ children
2716
+ }
2717
+ );
2718
+ }
2719
+ var FORMAT_BUTTONS = [
2720
+ {
2721
+ format: "bold",
2722
+ 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" }) })
2724
+ },
2725
+ {
2726
+ format: "italic",
2727
+ 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" }) })
2729
+ },
2730
+ {
2731
+ format: "strikethrough",
2732
+ 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" }) })
2734
+ },
2735
+ {
2736
+ format: "code",
2737
+ 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" }) })
2739
+ }
2740
+ ];
2741
+ function FormatButtons() {
2742
+ const { activeFormats, toggleFormat } = useMarkdownEditor();
2743
+ return /* @__PURE__ */ jsx7(Fragment2, { children: FORMAT_BUTTONS.map(({ format, label, icon }) => /* @__PURE__ */ jsx7(
2744
+ ToolbarButton,
2745
+ {
2746
+ label,
2747
+ active: activeFormats.has(format),
2748
+ onClick: () => toggleFormat(format),
2749
+ children: icon
2750
+ },
2751
+ format
2752
+ )) });
2753
+ }
2754
+ function InsertButtons() {
2755
+ 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" })
2760
+ ] }) }),
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" })
2765
+ ] }) })
2766
+ ] });
2767
+ }
2768
+ function HistoryButtons() {
2769
+ 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" })
2774
+ ] }) }),
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" })
2778
+ ] }) })
2779
+ ] });
2780
+ }
2781
+
2782
+ // src/MarkdownEditor.tsx
2783
+ import { jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
2784
+ var DEFAULT_ITEMS = {
2785
+ format: /* @__PURE__ */ jsx8(FormatButtons, {}),
2786
+ insert: /* @__PURE__ */ jsx8(InsertButtons, {}),
2787
+ history: /* @__PURE__ */ jsx8(HistoryButtons, {})
2788
+ };
2789
+ function EditorToolbar({
2790
+ children,
2791
+ className
2792
+ }) {
2793
+ const { mode, readOnly } = useEditorContext();
2794
+ if (mode !== "edit-md" || readOnly) return null;
2795
+ return /* @__PURE__ */ jsx8(Toolbar, { className, children });
2796
+ }
2797
+ function MarkdownEditor({
2798
+ placeholder,
2799
+ toolbar = true,
2800
+ outline = false,
2801
+ foldable = true,
2802
+ ...rootProps
2803
+ }) {
2804
+ return /* @__PURE__ */ jsxs6(EditorRoot, { ...rootProps, children: [
2805
+ toolbar === true && /* @__PURE__ */ jsx8(EditorToolbar, {}),
2806
+ typeof toolbar === "function" && toolbar(DEFAULT_ITEMS),
2807
+ /* @__PURE__ */ jsx8(EditorContent, { placeholder, foldable, children: outline && /* @__PURE__ */ jsx8(OutlinePlugin, {}) })
2808
+ ] });
2691
2809
  }
2810
+ MarkdownEditor.Root = EditorRoot;
2811
+ MarkdownEditor.Content = EditorContent;
2812
+ MarkdownEditor.Toolbar = EditorToolbar;
2813
+ MarkdownEditor.ToolbarButton = ToolbarButton;
2814
+ MarkdownEditor.ToolbarDivider = ToolbarDivider;
2815
+ MarkdownEditor.FormatButtons = FormatButtons;
2816
+ MarkdownEditor.InsertButtons = InsertButtons;
2817
+ MarkdownEditor.HistoryButtons = HistoryButtons;
2818
+ MarkdownEditor.Outline = OutlinePlugin;
2819
+ MarkdownEditor.useEditor = useMarkdownEditor;
2820
+ var MarkdownEditor_default = MarkdownEditor;
2692
2821
 
2693
2822
  // src/components/drawingSchema.ts
2694
2823
  var DRAWING_DATA_JSON_SCHEMA = {
@@ -2807,9 +2936,16 @@ export {
2807
2936
  DRAWING_DATA_JSON_SCHEMA,
2808
2937
  DrawingNode,
2809
2938
  FRONTMATTER,
2939
+ FormatButtons,
2810
2940
  FrontmatterNode,
2811
- MarkdownEditor,
2941
+ HistoryButtons,
2942
+ InsertButtons,
2943
+ MarkdownEditor_default as MarkdownEditor,
2812
2944
  TABLE,
2945
+ Toolbar,
2946
+ ToolbarButton,
2947
+ ToolbarDivider,
2813
2948
  parseDrawingData,
2814
- serializeDrawingData
2949
+ serializeDrawingData,
2950
+ useMarkdownEditor
2815
2951
  };