@elixpo/lixsketch 5.5.23 → 5.6.2

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.
Files changed (130) hide show
  1. package/README.md +85 -6
  2. package/dist/mcp/index.js +585 -0
  3. package/dist/mcp/index.js.map +7 -0
  4. package/dist/mcp/node.js +184 -0
  5. package/dist/mcp/node.js.map +7 -0
  6. package/dist/mcp/stdio.js +723 -0
  7. package/dist/mcp/stdio.js.map +7 -0
  8. package/dist/react/{CopyPaste-5OWPTCQ5.js → CopyPaste-YUDZ6DHY.js} +7 -7
  9. package/dist/react/EventDispatcher-7LAK7GQ7.js +1097 -0
  10. package/dist/react/EventDispatcher-7LAK7GQ7.js.map +7 -0
  11. package/dist/react/Frame-7D2MXCFF.js +11 -0
  12. package/dist/react/IconShape-ZADX7Y33.js +10 -0
  13. package/dist/react/ImageShape-UJQN2HI7.js +10 -0
  14. package/dist/react/Line-APEULMHE.js +10 -0
  15. package/dist/react/{SceneSerializer-RDISX4X7.js → SceneSerializer-SG6SJN5X.js} +17 -7
  16. package/dist/react/SceneSerializer-SG6SJN5X.js.map +7 -0
  17. package/dist/react/{Selection-ZL3G6IAO.js → Selection-2TSH3J6P.js} +6 -4
  18. package/dist/react/{SketchEngine-OB6ZW3B6.js → SketchEngine-UD2XV2KT.js} +50 -23
  19. package/dist/react/{SketchEngine-OB6ZW3B6.js.map → SketchEngine-UD2XV2KT.js.map} +2 -2
  20. package/dist/react/{UndoRedo-NL7KLR5B.js → UndoRedo-IN4SXDG6.js} +2 -2
  21. package/dist/react/{ZoomPan-FAWA5OPS.js → ZoomPan-RR7KUYZT.js} +34 -1
  22. package/dist/react/{ZoomPan-FAWA5OPS.js.map → ZoomPan-RR7KUYZT.js.map} +2 -2
  23. package/dist/react/{arrowTool-CNVGM6RX.js → arrowTool-OYDWJGQK.js} +3 -3
  24. package/dist/react/{chunk-U3TB4KRS.js → chunk-6GPEWDRB.js} +19 -12
  25. package/dist/react/chunk-6GPEWDRB.js.map +7 -0
  26. package/dist/react/{chunk-4BLMNGTR.js → chunk-7CM5XQDN.js} +3 -3
  27. package/dist/react/{chunk-XFQECTTF.js → chunk-APTOPAOY.js} +3 -3
  28. package/dist/react/{chunk-EDSKEM6E.js → chunk-ASBC5G35.js} +47 -8
  29. package/dist/react/chunk-ASBC5G35.js.map +7 -0
  30. package/dist/react/{chunk-4TAS67SL.js → chunk-EOURRJ55.js} +2 -2
  31. package/dist/react/{chunk-ETAAQUUV.js → chunk-GQUZPON4.js} +4 -4
  32. package/dist/react/{chunk-KVAQPCUH.js → chunk-K5BG5MHY.js} +49 -5
  33. package/dist/react/chunk-K5BG5MHY.js.map +7 -0
  34. package/dist/react/{chunk-AH4PWNEB.js → chunk-K5RY4EV7.js} +23 -3
  35. package/dist/react/chunk-K5RY4EV7.js.map +7 -0
  36. package/dist/react/{chunk-GC3KTQDA.js → chunk-LJR7EVW2.js} +3 -3
  37. package/dist/react/{chunk-SZD7DKYJ.js → chunk-LSHZYN77.js} +2 -2
  38. package/dist/react/{chunk-HFQZYCHJ.js → chunk-M6TMN76K.js} +3 -3
  39. package/dist/react/{chunk-V2QTYSBK.js → chunk-OP56XPWF.js} +2 -2
  40. package/dist/react/chunk-QZI4UIE5.js +48 -0
  41. package/dist/react/chunk-QZI4UIE5.js.map +7 -0
  42. package/dist/react/{chunk-ILGAFR56.js → chunk-RGMDWLRJ.js} +3 -3
  43. package/dist/react/{chunk-OFGJJKPH.js → chunk-XFL4R5ZF.js} +3 -3
  44. package/dist/react/{chunk-GPIYXREE.js → chunk-XOWNCYE4.js} +3 -3
  45. package/dist/react/{chunk-YF3TK7SC.js → chunk-XYUFEIZR.js} +2 -2
  46. package/dist/react/{circleTool-KICNRQCI.js → circleTool-LDKGZALF.js} +4 -4
  47. package/dist/react/{codeTool-NCQ73R6M.js → codeTool-4YZO5W7J.js} +4 -4
  48. package/dist/react/{frameTool-Y6KB67DO.js → frameTool-MXNJEXQQ.js} +4 -4
  49. package/dist/react/{freehandTool-MMULHCQ7.js → freehandTool-26D3FOOX.js} +4 -4
  50. package/dist/react/{iconTool-LSW2DYGB.js → iconTool-46O5VEUX.js} +4 -4
  51. package/dist/react/{imageTool-2DSR32RX.js → imageTool-P2RWZRHO.js} +4 -4
  52. package/dist/react/index.js +848 -614
  53. package/dist/react/index.js.map +4 -4
  54. package/dist/react/{lineTool-N5I7IGT7.js → lineTool-ZMR27U5L.js} +4 -4
  55. package/dist/react/{rectangleTool-YUT7ZK2E.js → rectangleTool-EJKK6UTX.js} +4 -4
  56. package/dist/react/{textTool-JMTX7OVT.js → textTool-S4XXZHZH.js} +5 -5
  57. package/package.json +7 -1
  58. package/src/EngineShortcuts.js +22 -0
  59. package/src/SketchEngine.js +27 -0
  60. package/src/core/EventDispatcher.js +35 -4
  61. package/src/core/SceneSerializer.js +5 -0
  62. package/src/core/Selection.js +26 -0
  63. package/src/core/UndoRedo.js +20 -16
  64. package/src/core/WebEmbedPolicy.js +41 -0
  65. package/src/core/ZoomPan.js +36 -0
  66. package/src/index.js +4 -0
  67. package/src/mcp/fileStore.js +70 -0
  68. package/src/mcp/index.js +5 -0
  69. package/src/mcp/node.js +2 -0
  70. package/src/mcp/preview.js +39 -0
  71. package/src/mcp/scene.js +275 -0
  72. package/src/mcp/server.js +195 -0
  73. package/src/mcp/stdio.js +41 -0
  74. package/src/mcp/stdioTransport.js +46 -0
  75. package/src/mcp/store.js +23 -0
  76. package/src/mcp/templates.js +51 -0
  77. package/src/react/LixSketchCanvas.jsx +4 -0
  78. package/src/react/components/Toolbar.jsx +84 -7
  79. package/src/react/components/modals/CommandPalette.jsx +8 -0
  80. package/src/react/components/modals/WebEmbedModal.jsx +40 -0
  81. package/src/react/components/sidebars/PaintBucketSidebar.jsx +49 -0
  82. package/src/react/components/sidebars/PaintbrushSidebar.jsx +1 -1
  83. package/src/react/store/useSketchStore.js +13 -0
  84. package/src/react/toolsEnum.js +4 -0
  85. package/src/shapes/Frame.js +47 -4
  86. package/src/shapes/ImageShape.js +49 -6
  87. package/src/tools/lassoTool.js +84 -0
  88. package/src/tools/paintBucketTool.js +50 -0
  89. package/src/tools/shapeRecognitionTool.js +431 -0
  90. package/src/tools/webEmbedTool.js +61 -0
  91. package/dist/react/EventDispatcher-GKNO2KSL.js +0 -464
  92. package/dist/react/EventDispatcher-GKNO2KSL.js.map +0 -7
  93. package/dist/react/Frame-RLSMJJSK.js +0 -11
  94. package/dist/react/IconShape-7OPXAKLK.js +0 -10
  95. package/dist/react/ImageShape-T7UEHP4A.js +0 -10
  96. package/dist/react/Line-WWQFBNX5.js +0 -10
  97. package/dist/react/SceneSerializer-RDISX4X7.js.map +0 -7
  98. package/dist/react/chunk-AH4PWNEB.js.map +0 -7
  99. package/dist/react/chunk-EDSKEM6E.js.map +0 -7
  100. package/dist/react/chunk-KVAQPCUH.js.map +0 -7
  101. package/dist/react/chunk-U3TB4KRS.js.map +0 -7
  102. /package/dist/react/{CopyPaste-5OWPTCQ5.js.map → CopyPaste-YUDZ6DHY.js.map} +0 -0
  103. /package/dist/react/{Frame-RLSMJJSK.js.map → Frame-7D2MXCFF.js.map} +0 -0
  104. /package/dist/react/{IconShape-7OPXAKLK.js.map → IconShape-ZADX7Y33.js.map} +0 -0
  105. /package/dist/react/{ImageShape-T7UEHP4A.js.map → ImageShape-UJQN2HI7.js.map} +0 -0
  106. /package/dist/react/{Line-WWQFBNX5.js.map → Line-APEULMHE.js.map} +0 -0
  107. /package/dist/react/{Selection-ZL3G6IAO.js.map → Selection-2TSH3J6P.js.map} +0 -0
  108. /package/dist/react/{UndoRedo-NL7KLR5B.js.map → UndoRedo-IN4SXDG6.js.map} +0 -0
  109. /package/dist/react/{arrowTool-CNVGM6RX.js.map → arrowTool-OYDWJGQK.js.map} +0 -0
  110. /package/dist/react/{chunk-4BLMNGTR.js.map → chunk-7CM5XQDN.js.map} +0 -0
  111. /package/dist/react/{chunk-XFQECTTF.js.map → chunk-APTOPAOY.js.map} +0 -0
  112. /package/dist/react/{chunk-4TAS67SL.js.map → chunk-EOURRJ55.js.map} +0 -0
  113. /package/dist/react/{chunk-ETAAQUUV.js.map → chunk-GQUZPON4.js.map} +0 -0
  114. /package/dist/react/{chunk-GC3KTQDA.js.map → chunk-LJR7EVW2.js.map} +0 -0
  115. /package/dist/react/{chunk-SZD7DKYJ.js.map → chunk-LSHZYN77.js.map} +0 -0
  116. /package/dist/react/{chunk-HFQZYCHJ.js.map → chunk-M6TMN76K.js.map} +0 -0
  117. /package/dist/react/{chunk-V2QTYSBK.js.map → chunk-OP56XPWF.js.map} +0 -0
  118. /package/dist/react/{chunk-ILGAFR56.js.map → chunk-RGMDWLRJ.js.map} +0 -0
  119. /package/dist/react/{chunk-OFGJJKPH.js.map → chunk-XFL4R5ZF.js.map} +0 -0
  120. /package/dist/react/{chunk-GPIYXREE.js.map → chunk-XOWNCYE4.js.map} +0 -0
  121. /package/dist/react/{chunk-YF3TK7SC.js.map → chunk-XYUFEIZR.js.map} +0 -0
  122. /package/dist/react/{circleTool-KICNRQCI.js.map → circleTool-LDKGZALF.js.map} +0 -0
  123. /package/dist/react/{codeTool-NCQ73R6M.js.map → codeTool-4YZO5W7J.js.map} +0 -0
  124. /package/dist/react/{frameTool-Y6KB67DO.js.map → frameTool-MXNJEXQQ.js.map} +0 -0
  125. /package/dist/react/{freehandTool-MMULHCQ7.js.map → freehandTool-26D3FOOX.js.map} +0 -0
  126. /package/dist/react/{iconTool-LSW2DYGB.js.map → iconTool-46O5VEUX.js.map} +0 -0
  127. /package/dist/react/{imageTool-2DSR32RX.js.map → imageTool-P2RWZRHO.js.map} +0 -0
  128. /package/dist/react/{lineTool-N5I7IGT7.js.map → lineTool-ZMR27U5L.js.map} +0 -0
  129. /package/dist/react/{rectangleTool-YUT7ZK2E.js.map → rectangleTool-EJKK6UTX.js.map} +0 -0
  130. /package/dist/react/{textTool-JMTX7OVT.js.map → textTool-S4XXZHZH.js.map} +0 -0
@@ -1,4 +1,7 @@
1
1
  "use client";
2
+ import {
3
+ normalizeWebEmbedUrl
4
+ } from "./chunk-QZI4UIE5.js";
2
5
  import {
3
6
  ALLOWED_IMAGE_EXTENSIONS,
4
7
  ALLOWED_IMAGE_MIME_TYPES,
@@ -9,7 +12,7 @@ import {
9
12
  } from "./chunk-DNAG7ML6.js";
10
13
 
11
14
  // src/react/LixSketchCanvas.jsx
12
- import { useCallback as useCallback16, useEffect as useEffect17, useRef as useRef12, useState as useState20 } from "react";
15
+ import { useCallback as useCallback17, useEffect as useEffect20, useRef as useRef14, useState as useState23 } from "react";
13
16
 
14
17
  // src/react/store/useSketchStore.js
15
18
  import { create } from "zustand";
@@ -29,7 +32,11 @@ var TOOLS = {
29
32
  LASER: "laser",
30
33
  IMAGE: "image",
31
34
  FRAME: "frame",
32
- ICON: "icon"
35
+ ICON: "icon",
36
+ DRAW_SHAPE: "draw-shape",
37
+ PAINT_BUCKET: "paint-bucket",
38
+ LASSO: "lasso",
39
+ WEB_EMBED: "web-embed"
33
40
  };
34
41
  var TOOL_CURSORS = {
35
42
  [TOOLS.SELECT]: "default",
@@ -44,7 +51,11 @@ var TOOL_CURSORS = {
44
51
  [TOOLS.LASER]: "crosshair",
45
52
  [TOOLS.IMAGE]: "crosshair",
46
53
  [TOOLS.FRAME]: "crosshair",
47
- [TOOLS.ICON]: "crosshair"
54
+ [TOOLS.ICON]: "crosshair",
55
+ [TOOLS.DRAW_SHAPE]: "crosshair",
56
+ [TOOLS.PAINT_BUCKET]: "cell",
57
+ [TOOLS.LASSO]: "crosshair",
58
+ [TOOLS.WEB_EMBED]: "crosshair"
48
59
  };
49
60
  var TOOL_SIDEBARS = {
50
61
  [TOOLS.FREEHAND]: "paintbrush",
@@ -54,7 +65,8 @@ var TOOL_SIDEBARS = {
54
65
  [TOOLS.ARROW]: "arrow",
55
66
  [TOOLS.TEXT]: "text",
56
67
  [TOOLS.CODE]: "text",
57
- [TOOLS.FRAME]: "frame"
68
+ [TOOLS.FRAME]: "frame",
69
+ [TOOLS.DRAW_SHAPE]: "paintbrush"
58
70
  };
59
71
  var SHORTCUT_MAP = {
60
72
  h: TOOLS.PAN,
@@ -77,7 +89,11 @@ var SHORTCUT_MAP = {
77
89
  0: TOOLS.ERASER,
78
90
  i: TOOLS.ICON,
79
91
  f: TOOLS.FRAME,
80
- k: TOOLS.LASER
92
+ k: TOOLS.LASER,
93
+ d: TOOLS.DRAW_SHAPE,
94
+ b: TOOLS.PAINT_BUCKET,
95
+ s: TOOLS.LASSO,
96
+ w: TOOLS.WEB_EMBED
81
97
  };
82
98
  var useSketchStore = create((set, get) => ({
83
99
  // --- Active tool (replaces 15 boolean flags) ---
@@ -528,7 +544,7 @@ function useSketchEngine(svgRef, ready = true) {
528
544
  setZoom: (zoom) => useSketchStore_default.setState({ zoom }),
529
545
  getState: () => useSketchStore_default.getState()
530
546
  };
531
- const { SketchEngine } = await import("./SketchEngine-OB6ZW3B6.js");
547
+ const { SketchEngine } = await import("./SketchEngine-UD2XV2KT.js");
532
548
  if (cancelled) return;
533
549
  const engine = new SketchEngine(svgRef.current);
534
550
  await engine.init();
@@ -826,12 +842,23 @@ function SVGCanvas() {
826
842
  }
827
843
 
828
844
  // src/react/components/Toolbar.jsx
845
+ import { useEffect as useEffect4, useRef as useRef3, useState as useState3 } from "react";
829
846
  import { Fragment as Fragment3, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
830
847
  function getViewModeItems() {
831
848
  return [
832
849
  { tool: TOOLS.PAN, icon: "bxs-hand", title: "Pan (H)", key: "H" }
833
850
  ];
834
851
  }
852
+ function getMoreToolItems() {
853
+ return [
854
+ { tool: TOOLS.DRAW_SHAPE, icon: "draw-shape", title: "Draw to shape", key: "D" },
855
+ { tool: TOOLS.PAINT_BUCKET, icon: "bxs-color-fill", title: "Paint bucket", key: "B" },
856
+ { tool: TOOLS.FRAME, icon: "bx-crop", title: "Frame", key: "F" },
857
+ { tool: TOOLS.LASER, icon: "bxs-magic-wand", title: "Laser", key: "K" },
858
+ { tool: TOOLS.LASSO, icon: "bx-shape-polygon", title: "Lasso selection", key: "S" },
859
+ { tool: TOOLS.WEB_EMBED, icon: "bx-globe", title: "Web embed", key: "W" }
860
+ ];
861
+ }
835
862
  function getToolItems() {
836
863
  return [
837
864
  { tool: TOOLS.PAN, icon: "bxs-hand", title: "Pan (H)", key: "H" },
@@ -846,14 +873,23 @@ function getToolItems() {
846
873
  { tool: TOOLS.IMAGE, icon: "bx-image-alt", title: "Image (9)", key: "9" },
847
874
  { tool: TOOLS.ICON, icon: "bx-wink-smile", title: "Icon (I)", key: "I" },
848
875
  "spacer",
849
- { tool: TOOLS.FRAME, icon: "bx-crop", title: "Frame (F)", key: "F" },
850
- { tool: TOOLS.LASER, icon: "bxs-magic-wand", title: "Laser (K)", key: "K" },
851
- { tool: TOOLS.ERASER, icon: "bxs-eraser", title: "Eraser (E)", key: "E" }
876
+ { tool: TOOLS.ERASER, icon: "bxs-eraser", title: "Eraser (E)", key: "E" },
877
+ "more"
852
878
  // AI tool entry removed while the assistant is coming-soon.
853
879
  // Restore `{ tool: 'ai', icon: null, title: 'AI', isAI: true }` here
854
880
  // when the modal becomes a real feature again.
855
881
  ];
856
882
  }
883
+ function ToolIcon({ item, className = "h-5 w-5" }) {
884
+ if (item.icon === "draw-shape") {
885
+ return /* @__PURE__ */ jsxs3("svg", { className, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
886
+ /* @__PURE__ */ jsx3("path", { d: "M2.5 16.5c2.2-5.8 4.5 3.5 7-2.5 1.1-2.7 2.2-3.8 3.4-3.9" }),
887
+ /* @__PURE__ */ jsx3("path", { d: "M15 4.5h6v6h-6z" }),
888
+ /* @__PURE__ */ jsx3("path", { d: "m12.5 8 2.5-.5" })
889
+ ] });
890
+ }
891
+ return /* @__PURE__ */ jsx3("i", { className: `bx ${item.icon} text-xl` });
892
+ }
857
893
  function Toolbar() {
858
894
  const activeTool = useSketchStore_default((s) => s.activeTool);
859
895
  const setActiveTool = useSketchStore_default((s) => s.setActiveTool);
@@ -861,9 +897,31 @@ function Toolbar() {
861
897
  const toolLock = useSketchStore_default((s) => s.toolLock);
862
898
  const toggleToolLock = useSketchStore_default((s) => s.toggleToolLock);
863
899
  const toggleAIModal = useUIStore_default((s) => s.toggleAIModal);
900
+ const [moreOpen, setMoreOpen] = useState3(false);
901
+ const [lastMoreItem, setLastMoreItem] = useState3(null);
902
+ const moreRef = useRef3(null);
864
903
  const items = viewMode ? getViewModeItems() : getToolItems();
904
+ const moreItems = getMoreToolItems();
905
+ const activeMoreItem = moreItems.find((item) => item.tool === activeTool);
906
+ const moreActive = Boolean(activeMoreItem);
907
+ const shownMoreItem = activeMoreItem || lastMoreItem;
908
+ useEffect4(() => {
909
+ if (!moreOpen) return void 0;
910
+ const close = (event) => {
911
+ if (event.key === "Escape" || event.type === "pointerdown" && !moreRef.current?.contains(event.target)) setMoreOpen(false);
912
+ };
913
+ document.addEventListener("pointerdown", close);
914
+ document.addEventListener("keydown", close);
915
+ return () => {
916
+ document.removeEventListener("pointerdown", close);
917
+ document.removeEventListener("keydown", close);
918
+ };
919
+ }, [moreOpen]);
920
+ useEffect4(() => {
921
+ setMoreOpen(false);
922
+ }, [activeTool, viewMode]);
865
923
  return /* @__PURE__ */ jsxs3(Fragment3, { children: [
866
- /* @__PURE__ */ jsxs3("div", { "data-canvas-toolbar": true, className: `absolute left-2.5 top-1/2 -translate-y-1/2 w-[46px] rounded-xl bg-surface z-[1000] flex flex-col items-center py-1.5 gap-0.5 font-[lixFont] max-h-[calc(100vh-120px)] overflow-y-auto no-scrollbar`, children: [
924
+ /* @__PURE__ */ jsxs3("div", { "data-canvas-toolbar": true, className: `absolute left-2.5 top-1/2 -translate-y-1/2 w-[46px] rounded-xl bg-surface z-[1000] flex flex-col items-center py-1.5 gap-0.5 font-[lixFont] max-h-[calc(100vh-120px)] overflow-visible`, children: [
867
925
  !viewMode && /* @__PURE__ */ jsxs3(Fragment3, { children: [
868
926
  /* @__PURE__ */ jsxs3(
869
927
  "button",
@@ -889,6 +947,37 @@ function Toolbar() {
889
947
  `spacer-${idx}`
890
948
  );
891
949
  }
950
+ if (item === "more") {
951
+ return /* @__PURE__ */ jsxs3("div", { ref: moreRef, className: "relative", children: [
952
+ /* @__PURE__ */ jsx3(
953
+ "button",
954
+ {
955
+ type: "button",
956
+ title: shownMoreItem ? `${shownMoreItem.title} \u2014 More tools` : "More tools",
957
+ "aria-label": "More tools",
958
+ "aria-expanded": moreOpen,
959
+ onClick: () => setMoreOpen((open) => !open),
960
+ className: `relative flex h-[31px] w-[33px] cursor-pointer items-center justify-center rounded-lg transition-all duration-200 ${moreOpen || moreActive ? "bg-accent/20 text-accent" : "text-text-muted hover:bg-surface-hover hover:text-text-primary"}`,
961
+ children: shownMoreItem ? /* @__PURE__ */ jsx3(ToolIcon, { item: shownMoreItem, className: "h-[18px] w-[18px]" }) : /* @__PURE__ */ jsx3("i", { className: "bx bx-dots-horizontal-rounded text-xl" })
962
+ }
963
+ ),
964
+ moreOpen && /* @__PURE__ */ jsxs3("div", { className: "absolute left-[calc(100%+10px)] top-1/2 z-[1100] w-[190px] -translate-y-1/2 rounded-xl border border-border-light bg-surface-card/95 p-1.5 shadow-xl shadow-black/25 backdrop-blur-lg", children: [
965
+ /* @__PURE__ */ jsx3("p", { className: "px-2 py-1 text-[10px] uppercase tracking-[0.14em] text-text-dim", children: "More tools" }),
966
+ moreItems.map((moreItem) => {
967
+ const selected = activeTool === moreItem.tool;
968
+ return /* @__PURE__ */ jsxs3("button", { type: "button", title: `${moreItem.title} (${moreItem.key})`, onClick: () => {
969
+ setLastMoreItem(moreItem);
970
+ setActiveTool(moreItem.tool);
971
+ setMoreOpen(false);
972
+ }, className: `flex w-full cursor-pointer items-center gap-3 rounded-lg px-2.5 py-2 text-left text-xs transition ${selected ? "bg-accent/20 text-accent" : "text-text-muted hover:bg-surface-hover hover:text-text-primary"}`, children: [
973
+ /* @__PURE__ */ jsx3("span", { className: "flex h-5 w-5 items-center justify-center", children: /* @__PURE__ */ jsx3(ToolIcon, { item: moreItem, className: "h-[18px] w-[18px]" }) }),
974
+ /* @__PURE__ */ jsx3("span", { className: "flex-1", children: moreItem.title }),
975
+ /* @__PURE__ */ jsx3("span", { className: "text-[10px] text-text-dim", children: moreItem.key })
976
+ ] }, moreItem.tool);
977
+ })
978
+ ] })
979
+ ] }, "more");
980
+ }
892
981
  const isActive = activeTool === item.tool;
893
982
  if (item.isAI) {
894
983
  return /* @__PURE__ */ jsx3(
@@ -925,13 +1014,7 @@ function Toolbar() {
925
1014
  onClick: () => setActiveTool(item.tool),
926
1015
  className: `relative w-[33px] h-[31px] flex items-center justify-center rounded-lg transition-all duration-200 ${isActive ? "bg-accent-blue/20 text-accent-blue" : "text-text-muted hover:text-text-primary hover:bg-surface-hover"}`,
927
1016
  children: [
928
- /* @__PURE__ */ jsx3(
929
- "i",
930
- {
931
- className: `bx ${item.icon} text-xl`,
932
- style: item.rotate ? { transform: "rotate(-45deg)" } : void 0
933
- }
934
- ),
1017
+ /* @__PURE__ */ jsx3("span", { style: item.rotate ? { transform: "rotate(-45deg)" } : void 0, children: /* @__PURE__ */ jsx3(ToolIcon, { item }) }),
935
1018
  item.key && /* @__PURE__ */ jsx3("span", { className: `absolute bottom-0.5 right-[-1px] text-[10px] leading-none ${isActive ? "opacity-60" : "opacity-35"}`, children: item.key })
936
1019
  ]
937
1020
  },
@@ -1048,7 +1131,7 @@ function Footer() {
1048
1131
  }
1049
1132
 
1050
1133
  // src/react/components/AppMenu.jsx
1051
- import { useEffect as useEffect4, useRef as useRef3, useState as useState3 } from "react";
1134
+ import { useEffect as useEffect5, useRef as useRef4, useState as useState4 } from "react";
1052
1135
  import { createPortal } from "react-dom";
1053
1136
 
1054
1137
  // src/react/hooks/useTranslation.js
@@ -1142,7 +1225,7 @@ var CANVAS_BACKGROUNDS_DARK = [
1142
1225
  { color: "#1B1615", label: "menu.canvasBg.darkBrown" }
1143
1226
  ];
1144
1227
  function DangerWarningDialog({ action, workspaceName, onCancel, onConfirm }) {
1145
- useEffect4(() => {
1228
+ useEffect5(() => {
1146
1229
  if (!action) return void 0;
1147
1230
  const closeOnEscape = (event) => {
1148
1231
  if (event.key === "Escape") onCancel();
@@ -1254,12 +1337,12 @@ function AppMenu() {
1254
1337
  const authUser = useAuthStore((s) => s.user);
1255
1338
  const login = useAuthStore((s) => s.login);
1256
1339
  const logout = useAuthStore((s) => s.logout);
1257
- const [prefsOpen, setPrefsOpen] = useState3(false);
1258
- const [actionsOpen, setActionsOpen] = useState3(false);
1259
- const [actionsFlyoutPosition, setActionsFlyoutPosition] = useState3({ top: 0, left: 0 });
1260
- const actionsButtonRef = useRef3(null);
1261
- const [dangerAction, setDangerAction] = useState3(null);
1262
- useEffect4(() => {
1340
+ const [prefsOpen, setPrefsOpen] = useState4(false);
1341
+ const [actionsOpen, setActionsOpen] = useState4(false);
1342
+ const [actionsFlyoutPosition, setActionsFlyoutPosition] = useState4({ top: 0, left: 0 });
1343
+ const actionsButtonRef = useRef4(null);
1344
+ const [dangerAction, setDangerAction] = useState4(null);
1345
+ useEffect5(() => {
1263
1346
  if (menuOpen) return;
1264
1347
  setActionsOpen(false);
1265
1348
  setPrefsOpen(false);
@@ -1605,12 +1688,12 @@ function AppMenu() {
1605
1688
  }
1606
1689
 
1607
1690
  // src/react/components/sidebars/ShapeSidebar.jsx
1608
- import { useState as useState4, useRef as useRef4, useEffect as useEffect5 } from "react";
1691
+ import { useState as useState5, useRef as useRef5, useEffect as useEffect6 } from "react";
1609
1692
  import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
1610
1693
  function ToolbarButton({ icon, preview, children, tooltip }) {
1611
- const [open, setOpen] = useState4(false);
1612
- const ref = useRef4(null);
1613
- useEffect5(() => {
1694
+ const [open, setOpen] = useState5(false);
1695
+ const ref = useRef5(null);
1696
+ useEffect6(() => {
1614
1697
  if (!open) return;
1615
1698
  const handler = (e) => {
1616
1699
  if (ref.current && !ref.current.contains(e.target)) setOpen(false);
@@ -1699,7 +1782,7 @@ function LayerControls() {
1699
1782
  }
1700
1783
 
1701
1784
  // src/react/components/sidebars/RectangleSidebar.jsx
1702
- import { useState as useState5, useCallback as useCallback2 } from "react";
1785
+ import { useState as useState6, useCallback as useCallback2 } from "react";
1703
1786
  import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
1704
1787
  var STROKE_COLORS = ["#1a1a20", "#ffffff", "#FF8383", "#3A994C", "#56A2E8", "#FFD700", "#FF69B4", "#A855F7"];
1705
1788
  var BG_COLORS = ["transparent", "#f0f0f0", "#ffcccb", "#90ee90", "#add8e6", "#FFE4B5", "#DDA0DD", "#2d2d2d"];
@@ -1729,11 +1812,11 @@ function RectangleSidebar() {
1729
1812
  const { t } = useTranslation();
1730
1813
  const activeTool = useSketchStore_default((s) => s.activeTool);
1731
1814
  const selectedShapeSidebar = useSketchStore_default((s) => s.selectedShapeSidebar);
1732
- const [strokeColor, setStrokeColor] = useState5("#fff");
1733
- const [bgColor, setBgColor] = useState5("transparent");
1734
- const [thickness, setThickness] = useState5(2);
1735
- const [lineStyle, setLineStyle] = useState5("solid");
1736
- const [fillStyle, setFillStyle] = useState5("hachure");
1815
+ const [strokeColor, setStrokeColor] = useState6("#fff");
1816
+ const [bgColor, setBgColor] = useState6("transparent");
1817
+ const [thickness, setThickness] = useState6(2);
1818
+ const [lineStyle, setLineStyle] = useState6("solid");
1819
+ const [fillStyle, setFillStyle] = useState6("hachure");
1737
1820
  const update = useCallback2((changes, localSetters) => {
1738
1821
  Object.entries(localSetters).forEach(([, fn]) => fn());
1739
1822
  if (window.updateSelectedRectStyle) window.updateSelectedRectStyle(changes);
@@ -1834,7 +1917,7 @@ function RectangleSidebar() {
1834
1917
  }
1835
1918
 
1836
1919
  // src/react/components/sidebars/CircleSidebar.jsx
1837
- import { useState as useState6, useCallback as useCallback3 } from "react";
1920
+ import { useState as useState7, useCallback as useCallback3 } from "react";
1838
1921
  import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
1839
1922
  var STROKE_COLORS2 = ["#1a1a20", "#ffffff", "#FF8383", "#3A994C", "#56A2E8", "#FFD700", "#FF69B4", "#A855F7"];
1840
1923
  var BG_COLORS2 = ["transparent", "#f0f0f0", "#ffcccb", "#90ee90", "#add8e6", "#FFE4B5", "#DDA0DD", "#2d2d2d"];
@@ -1864,11 +1947,11 @@ function CircleSidebar() {
1864
1947
  const { t } = useTranslation();
1865
1948
  const activeTool = useSketchStore_default((s) => s.activeTool);
1866
1949
  const selectedShapeSidebar = useSketchStore_default((s) => s.selectedShapeSidebar);
1867
- const [strokeColor, setStrokeColor] = useState6("#fff");
1868
- const [bgColor, setBgColor] = useState6("transparent");
1869
- const [thickness, setThickness] = useState6(2);
1870
- const [lineStyle, setLineStyle] = useState6("solid");
1871
- const [fillStyle, setFillStyle] = useState6("hachure");
1950
+ const [strokeColor, setStrokeColor] = useState7("#fff");
1951
+ const [bgColor, setBgColor] = useState7("transparent");
1952
+ const [thickness, setThickness] = useState7(2);
1953
+ const [lineStyle, setLineStyle] = useState7("solid");
1954
+ const [fillStyle, setFillStyle] = useState7("hachure");
1872
1955
  const updateStroke = useCallback3((v) => {
1873
1956
  setStrokeColor(v);
1874
1957
  if (window.updateSelectedCircleStyle) window.updateSelectedCircleStyle({ stroke: v });
@@ -1960,12 +2043,54 @@ function CircleSidebar() {
1960
2043
  ] });
1961
2044
  }
1962
2045
 
1963
- // src/react/components/sidebars/LineSidebar.jsx
1964
- import { useState as useState7, useCallback as useCallback4 } from "react";
2046
+ // src/react/components/sidebars/PaintBucketSidebar.jsx
2047
+ import { useCallback as useCallback4, useEffect as useEffect7, useState as useState8 } from "react";
1965
2048
  import { jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
2049
+ var COLORS = ["#f0f0f0", "#ffcccb", "#90ee90", "#add8e6", "#FFE4B5", "#DDA0DD", "#A98DEB", "#2d2d2d"];
2050
+ var FILLS3 = [
2051
+ { value: "solid", label: "Solid" },
2052
+ { value: "hachure", label: "Hachure" },
2053
+ { value: "cross-hatch", label: "Cross-hatch" },
2054
+ { value: "dots", label: "Dots" },
2055
+ { value: "none", label: "Clear fill" }
2056
+ ];
2057
+ function PaintBucketSidebar() {
2058
+ const activeTool = useSketchStore_default((state) => state.activeTool);
2059
+ const [fillColor, setFillColor] = useState8("#A98DEB");
2060
+ const [fillStyle, setFillStyle] = useState8("solid");
2061
+ const sync = useCallback4((color, style) => {
2062
+ window.paintBucketSettings = window.paintBucketSettings || {};
2063
+ window.paintBucketSettings.fillColor = color;
2064
+ window.paintBucketSettings.fillStyle = style;
2065
+ }, []);
2066
+ useEffect7(() => sync(fillColor, fillStyle), [fillColor, fillStyle, sync]);
2067
+ return /* @__PURE__ */ jsxs9(ShapeSidebar, { visible: activeTool === TOOLS.PAINT_BUCKET, children: [
2068
+ /* @__PURE__ */ jsxs9(ToolbarButton, { tooltip: "Fill color", preview: /* @__PURE__ */ jsx9("span", { className: "h-4 w-4 rounded-md border border-border-light", style: { backgroundColor: fillColor } }), children: [
2069
+ /* @__PURE__ */ jsx9("p", { className: "mb-2 text-xs uppercase tracking-wider text-text-muted", children: "Fill color" }),
2070
+ /* @__PURE__ */ jsx9("div", { className: "grid grid-cols-4 gap-1.5", children: COLORS.map((color) => /* @__PURE__ */ jsx9("button", { type: "button", "aria-label": `Use ${color}`, onClick: () => setFillColor(color), className: `h-7 w-7 cursor-pointer rounded-md border-[1.5px] transition ${fillColor === color ? "scale-110 border-accent" : "border-border-light hover:border-text-dim"}`, style: { backgroundColor: color } }, color)) }),
2071
+ /* @__PURE__ */ jsxs9("label", { className: "mt-2 flex cursor-pointer items-center gap-2 text-xs text-text-muted", children: [
2072
+ /* @__PURE__ */ jsx9("input", { type: "color", value: fillColor, onChange: (event) => setFillColor(event.target.value), className: "h-7 w-9 cursor-pointer rounded border-0 bg-transparent" }),
2073
+ "Custom color"
2074
+ ] })
2075
+ ] }),
2076
+ /* @__PURE__ */ jsx9(Divider, {}),
2077
+ /* @__PURE__ */ jsxs9(ToolbarButton, { icon: "bxs-brush", tooltip: "Fill style", children: [
2078
+ /* @__PURE__ */ jsx9("p", { className: "mb-2 text-xs uppercase tracking-wider text-text-muted", children: "Fill style" }),
2079
+ /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-0.5", children: FILLS3.map((fill) => /* @__PURE__ */ jsxs9("button", { type: "button", onClick: () => setFillStyle(fill.value), className: `flex cursor-pointer items-center gap-2 rounded-lg px-2.5 py-1.5 text-xs transition ${fillStyle === fill.value ? "bg-accent text-white" : "text-text-secondary hover:bg-surface-hover"}`, children: [
2080
+ /* @__PURE__ */ jsx9("span", { className: "h-1.5 w-1.5 rounded-full bg-current" }),
2081
+ fill.label
2082
+ ] }, fill.value)) })
2083
+ ] }),
2084
+ /* @__PURE__ */ jsx9("div", { className: "max-w-[185px] px-2 text-[10px] leading-4 text-text-dim", children: "Click a rectangle or circle to apply the selected fill." })
2085
+ ] });
2086
+ }
2087
+
2088
+ // src/react/components/sidebars/LineSidebar.jsx
2089
+ import { useState as useState9, useCallback as useCallback5 } from "react";
2090
+ import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
1966
2091
  var STROKE_COLORS3 = ["#1a1a20", "#ffffff", "#FF8383", "#3A994C", "#56A2E8", "#FFD700", "#FF69B4", "#A855F7"];
1967
2092
  function ColorGrid3({ colors, selected, onSelect }) {
1968
- return /* @__PURE__ */ jsx9("div", { className: "grid grid-cols-4 gap-1.5", children: colors.map((c) => /* @__PURE__ */ jsx9(
2093
+ return /* @__PURE__ */ jsx10("div", { className: "grid grid-cols-4 gap-1.5", children: colors.map((c) => /* @__PURE__ */ jsx10(
1969
2094
  "button",
1970
2095
  {
1971
2096
  onClick: () => onSelect(c),
@@ -1979,73 +2104,73 @@ function LineSidebar() {
1979
2104
  const { t } = useTranslation();
1980
2105
  const activeTool = useSketchStore_default((s) => s.activeTool);
1981
2106
  const selectedShapeSidebar = useSketchStore_default((s) => s.selectedShapeSidebar);
1982
- const [strokeColor, setStrokeColor] = useState7("#fff");
1983
- const [thickness, setThickness] = useState7(2);
1984
- const [lineStyle, setLineStyle] = useState7("solid");
1985
- const [sloppiness, setSloppiness] = useState7(0);
1986
- const [edge, setEdge] = useState7("smooth");
1987
- const updateStroke = useCallback4((v) => {
2107
+ const [strokeColor, setStrokeColor] = useState9("#fff");
2108
+ const [thickness, setThickness] = useState9(2);
2109
+ const [lineStyle, setLineStyle] = useState9("solid");
2110
+ const [sloppiness, setSloppiness] = useState9(0);
2111
+ const [edge, setEdge] = useState9("smooth");
2112
+ const updateStroke = useCallback5((v) => {
1988
2113
  setStrokeColor(v);
1989
2114
  if (window.updateSelectedLineStyle) window.updateSelectedLineStyle({ stroke: v });
1990
2115
  }, []);
1991
- const updateThickness = useCallback4((v) => {
2116
+ const updateThickness = useCallback5((v) => {
1992
2117
  setThickness(v);
1993
2118
  if (window.updateSelectedLineStyle) window.updateSelectedLineStyle({ strokeWidth: v });
1994
2119
  }, []);
1995
- const updateStyle = useCallback4((v) => {
2120
+ const updateStyle = useCallback5((v) => {
1996
2121
  setLineStyle(v);
1997
2122
  if (window.updateSelectedLineStyle) window.updateSelectedLineStyle({ strokeStyle: v });
1998
2123
  }, []);
1999
- const updateSloppiness = useCallback4((v) => {
2124
+ const updateSloppiness = useCallback5((v) => {
2000
2125
  setSloppiness(v);
2001
2126
  if (window.updateSelectedLineStyle) window.updateSelectedLineStyle({ sloppiness: v });
2002
2127
  }, []);
2003
- const updateEdge = useCallback4((v) => {
2128
+ const updateEdge = useCallback5((v) => {
2004
2129
  setEdge(v);
2005
2130
  if (window.updateSelectedLineStyle) window.updateSelectedLineStyle({ edge: v === "smooth" ? 1 : 5 });
2006
2131
  }, []);
2007
- return /* @__PURE__ */ jsxs9(ShapeSidebar, { visible: activeTool === TOOLS.LINE || selectedShapeSidebar === "line", children: [
2008
- /* @__PURE__ */ jsxs9(
2132
+ return /* @__PURE__ */ jsxs10(ShapeSidebar, { visible: activeTool === TOOLS.LINE || selectedShapeSidebar === "line", children: [
2133
+ /* @__PURE__ */ jsxs10(
2009
2134
  ToolbarButton,
2010
2135
  {
2011
2136
  tooltip: t("sidebar.strokeColor"),
2012
- preview: /* @__PURE__ */ jsx9("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: strokeColor } }),
2137
+ preview: /* @__PURE__ */ jsx10("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: strokeColor } }),
2013
2138
  children: [
2014
- /* @__PURE__ */ jsx9("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.stroke") }),
2015
- /* @__PURE__ */ jsx9(ColorGrid3, { colors: STROKE_COLORS3, selected: strokeColor, onSelect: updateStroke })
2139
+ /* @__PURE__ */ jsx10("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.stroke") }),
2140
+ /* @__PURE__ */ jsx10(ColorGrid3, { colors: STROKE_COLORS3, selected: strokeColor, onSelect: updateStroke })
2016
2141
  ]
2017
2142
  }
2018
2143
  ),
2019
- /* @__PURE__ */ jsx9(Divider, {}),
2020
- /* @__PURE__ */ jsxs9(ToolbarButton, { icon: "bxs-edit-alt", tooltip: t("sidebar.strokeWidth"), children: [
2021
- /* @__PURE__ */ jsx9("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.width") }),
2022
- /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-1", children: [1, 2, 4, 7].map((w) => /* @__PURE__ */ jsx9(
2144
+ /* @__PURE__ */ jsx10(Divider, {}),
2145
+ /* @__PURE__ */ jsxs10(ToolbarButton, { icon: "bxs-edit-alt", tooltip: t("sidebar.strokeWidth"), children: [
2146
+ /* @__PURE__ */ jsx10("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.width") }),
2147
+ /* @__PURE__ */ jsx10("div", { className: "flex items-center gap-1", children: [1, 2, 4, 7].map((w) => /* @__PURE__ */ jsx10(
2023
2148
  "button",
2024
2149
  {
2025
2150
  onClick: () => updateThickness(w),
2026
2151
  className: `w-9 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${thickness === w ? "bg-[#7667a8]/20 text-[#7667a8]" : "text-text-muted hover:bg-white/[0.06]"}`,
2027
- children: /* @__PURE__ */ jsx9("div", { className: "w-5 rounded-full bg-current", style: { height: Math.max(1, w) } })
2152
+ children: /* @__PURE__ */ jsx10("div", { className: "w-5 rounded-full bg-current", style: { height: Math.max(1, w) } })
2028
2153
  },
2029
2154
  w
2030
2155
  )) })
2031
2156
  ] }),
2032
- /* @__PURE__ */ jsx9(Divider, {}),
2033
- /* @__PURE__ */ jsxs9(ToolbarButton, { icon: "bxs-minus-circle", tooltip: "Stroke style", children: [
2034
- /* @__PURE__ */ jsx9("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.style") }),
2035
- /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-1", children: [{ v: "solid", d: "" }, { v: "dashed", d: "6 4" }, { v: "dotted", d: "2 3" }].map((s) => /* @__PURE__ */ jsx9(
2157
+ /* @__PURE__ */ jsx10(Divider, {}),
2158
+ /* @__PURE__ */ jsxs10(ToolbarButton, { icon: "bxs-minus-circle", tooltip: "Stroke style", children: [
2159
+ /* @__PURE__ */ jsx10("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.style") }),
2160
+ /* @__PURE__ */ jsx10("div", { className: "flex items-center gap-1", children: [{ v: "solid", d: "" }, { v: "dashed", d: "6 4" }, { v: "dotted", d: "2 3" }].map((s) => /* @__PURE__ */ jsx10(
2036
2161
  "button",
2037
2162
  {
2038
2163
  onClick: () => updateStyle(s.v),
2039
2164
  className: `w-11 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${lineStyle === s.v ? "bg-[#7667a8]/20" : "hover:bg-white/[0.06]"}`,
2040
- children: /* @__PURE__ */ jsx9("svg", { width: "28", height: "4", viewBox: "0 0 28 4", children: /* @__PURE__ */ jsx9("line", { x1: "0", y1: "2", x2: "28", y2: "2", stroke: "#fff", strokeWidth: "2", strokeDasharray: s.d, strokeLinecap: "round" }) })
2165
+ children: /* @__PURE__ */ jsx10("svg", { width: "28", height: "4", viewBox: "0 0 28 4", children: /* @__PURE__ */ jsx10("line", { x1: "0", y1: "2", x2: "28", y2: "2", stroke: "#fff", strokeWidth: "2", strokeDasharray: s.d, strokeLinecap: "round" }) })
2041
2166
  },
2042
2167
  s.v
2043
2168
  )) })
2044
2169
  ] }),
2045
- /* @__PURE__ */ jsx9(Divider, {}),
2046
- /* @__PURE__ */ jsxs9(ToolbarButton, { icon: "bxs-shape-polygon", tooltip: "Sloppiness", children: [
2047
- /* @__PURE__ */ jsx9("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.sloppiness") }),
2048
- /* @__PURE__ */ jsx9("div", { className: "flex items-center gap-1", children: [{ v: 0, l: "0" }, { v: 2, l: "2" }, { v: 4, l: "4" }].map((s) => /* @__PURE__ */ jsx9(
2170
+ /* @__PURE__ */ jsx10(Divider, {}),
2171
+ /* @__PURE__ */ jsxs10(ToolbarButton, { icon: "bxs-shape-polygon", tooltip: "Sloppiness", children: [
2172
+ /* @__PURE__ */ jsx10("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.sloppiness") }),
2173
+ /* @__PURE__ */ jsx10("div", { className: "flex items-center gap-1", children: [{ v: 0, l: "0" }, { v: 2, l: "2" }, { v: 4, l: "4" }].map((s) => /* @__PURE__ */ jsx10(
2049
2174
  "button",
2050
2175
  {
2051
2176
  onClick: () => updateSloppiness(s.v),
@@ -2055,16 +2180,16 @@ function LineSidebar() {
2055
2180
  s.v
2056
2181
  )) })
2057
2182
  ] }),
2058
- /* @__PURE__ */ jsx9(Divider, {}),
2059
- /* @__PURE__ */ jsxs9(ToolbarButton, { icon: "bxs-landscape", tooltip: "Edge", children: [
2060
- /* @__PURE__ */ jsx9("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.edge") }),
2061
- /* @__PURE__ */ jsx9("div", { className: "flex flex-col gap-0.5", children: [{ v: "smooth", i: "bxs-droplet", l: "Smooth" }, { v: "rough", i: "bxs-bolt", l: "Rough" }].map((e) => /* @__PURE__ */ jsxs9(
2183
+ /* @__PURE__ */ jsx10(Divider, {}),
2184
+ /* @__PURE__ */ jsxs10(ToolbarButton, { icon: "bxs-landscape", tooltip: "Edge", children: [
2185
+ /* @__PURE__ */ jsx10("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.edge") }),
2186
+ /* @__PURE__ */ jsx10("div", { className: "flex flex-col gap-0.5", children: [{ v: "smooth", i: "bxs-droplet", l: "Smooth" }, { v: "rough", i: "bxs-bolt", l: "Rough" }].map((e) => /* @__PURE__ */ jsxs10(
2062
2187
  "button",
2063
2188
  {
2064
2189
  onClick: () => updateEdge(e.v),
2065
2190
  className: `flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${edge === e.v ? "bg-accent-blue text-white" : "text-text-secondary hover:bg-white/6"}`,
2066
2191
  children: [
2067
- /* @__PURE__ */ jsx9("i", { className: `bx ${e.i} text-sm` }),
2192
+ /* @__PURE__ */ jsx10("i", { className: `bx ${e.i} text-sm` }),
2068
2193
  " ",
2069
2194
  e.l
2070
2195
  ]
@@ -2072,14 +2197,14 @@ function LineSidebar() {
2072
2197
  e.v
2073
2198
  )) })
2074
2199
  ] }),
2075
- /* @__PURE__ */ jsx9(Divider, {}),
2076
- /* @__PURE__ */ jsx9(LayerControls, {})
2200
+ /* @__PURE__ */ jsx10(Divider, {}),
2201
+ /* @__PURE__ */ jsx10(LayerControls, {})
2077
2202
  ] });
2078
2203
  }
2079
2204
 
2080
2205
  // src/react/components/sidebars/ArrowSidebar.jsx
2081
- import { useState as useState8, useCallback as useCallback5 } from "react";
2082
- import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
2206
+ import { useState as useState10, useCallback as useCallback6 } from "react";
2207
+ import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
2083
2208
  var STROKE_COLORS4 = ["#1a1a20", "#ffffff", "#FF8383", "#3A994C", "#56A2E8", "#FFD700", "#FF69B4", "#A855F7"];
2084
2209
  var HEAD_STYLES = [
2085
2210
  { value: "default", svg: '<svg width="22" height="12" viewBox="0 0 24 14"><line x1="2" y1="7" x2="16" y2="7" stroke="#fff" stroke-width="2"/><polyline points="13,2 19,7 13,12" fill="none" stroke="#fff" stroke-width="2" stroke-linejoin="round"/></svg>' },
@@ -2088,10 +2213,10 @@ var HEAD_STYLES = [
2088
2213
  { value: "solid", svg: '<svg width="22" height="12" viewBox="0 0 24 14"><line x1="2" y1="7" x2="13" y2="7" stroke="#fff" stroke-width="2"/><polygon points="13,2 21,7 13,12" fill="#fff"/></svg>' }
2089
2214
  ];
2090
2215
  function SvgIcon({ svg }) {
2091
- return /* @__PURE__ */ jsx10("span", { dangerouslySetInnerHTML: { __html: svg } });
2216
+ return /* @__PURE__ */ jsx11("span", { dangerouslySetInnerHTML: { __html: svg } });
2092
2217
  }
2093
2218
  function ColorGrid4({ colors, selected, onSelect }) {
2094
- return /* @__PURE__ */ jsx10("div", { className: "grid grid-cols-4 gap-1.5", children: colors.map((c) => /* @__PURE__ */ jsx10(
2219
+ return /* @__PURE__ */ jsx11("div", { className: "grid grid-cols-4 gap-1.5", children: colors.map((c) => /* @__PURE__ */ jsx11(
2095
2220
  "button",
2096
2221
  {
2097
2222
  onClick: () => onSelect(c),
@@ -2105,118 +2230,118 @@ function ArrowSidebar() {
2105
2230
  const { t } = useTranslation();
2106
2231
  const activeTool = useSketchStore_default((s) => s.activeTool);
2107
2232
  const selectedShapeSidebar = useSketchStore_default((s) => s.selectedShapeSidebar);
2108
- const [headStyle, setHeadStyle] = useState8("default");
2109
- const [strokeColor, setStrokeColor] = useState8("#fff");
2110
- const [thickness, setThickness] = useState8(2);
2111
- const [outlineStyle, setOutlineStyle] = useState8("solid");
2112
- const [arrowType, setArrowType] = useState8("straight");
2113
- const [curvature, setCurvature] = useState8(20);
2114
- const updateHead = useCallback5((v) => {
2233
+ const [headStyle, setHeadStyle] = useState10("default");
2234
+ const [strokeColor, setStrokeColor] = useState10("#fff");
2235
+ const [thickness, setThickness] = useState10(2);
2236
+ const [outlineStyle, setOutlineStyle] = useState10("solid");
2237
+ const [arrowType, setArrowType] = useState10("straight");
2238
+ const [curvature, setCurvature] = useState10(20);
2239
+ const updateHead = useCallback6((v) => {
2115
2240
  setHeadStyle(v);
2116
2241
  if (window.arrowToolSettings) window.arrowToolSettings.headStyle = v;
2117
2242
  if (window.updateSelectedArrowStyle) window.updateSelectedArrowStyle({ arrowHeadStyle: v });
2118
2243
  }, []);
2119
- const updateStroke = useCallback5((v) => {
2244
+ const updateStroke = useCallback6((v) => {
2120
2245
  setStrokeColor(v);
2121
2246
  if (window.arrowToolSettings) window.arrowToolSettings.strokeColor = v;
2122
2247
  if (window.updateSelectedArrowStyle) window.updateSelectedArrowStyle({ stroke: v });
2123
2248
  }, []);
2124
- const updateThickness = useCallback5((v) => {
2249
+ const updateThickness = useCallback6((v) => {
2125
2250
  setThickness(v);
2126
2251
  if (window.arrowToolSettings) window.arrowToolSettings.strokeWidth = v;
2127
2252
  if (window.updateSelectedArrowStyle) window.updateSelectedArrowStyle({ strokeWidth: v });
2128
2253
  }, []);
2129
- const updateOutline = useCallback5((v) => {
2254
+ const updateOutline = useCallback6((v) => {
2130
2255
  setOutlineStyle(v);
2131
2256
  if (window.arrowToolSettings) window.arrowToolSettings.outlineStyle = v;
2132
2257
  if (window.updateSelectedArrowStyle) window.updateSelectedArrowStyle({ arrowOutlineStyle: v });
2133
2258
  }, []);
2134
- const updateType = useCallback5((v) => {
2259
+ const updateType = useCallback6((v) => {
2135
2260
  setArrowType(v);
2136
2261
  if (window.arrowToolSettings) window.arrowToolSettings.arrowCurved = v;
2137
2262
  if (window.updateSelectedArrowStyle) window.updateSelectedArrowStyle({ arrowCurved: v });
2138
2263
  }, []);
2139
- const updateCurvature = useCallback5((v) => {
2264
+ const updateCurvature = useCallback6((v) => {
2140
2265
  setCurvature(v);
2141
2266
  if (window.arrowToolSettings) window.arrowToolSettings.curveAmount = v;
2142
2267
  if (window.updateSelectedArrowStyle) window.updateSelectedArrowStyle({ arrowCurveAmount: v });
2143
2268
  }, []);
2144
- return /* @__PURE__ */ jsxs10(ShapeSidebar, { visible: activeTool === TOOLS.ARROW || selectedShapeSidebar === "arrow", children: [
2145
- /* @__PURE__ */ jsxs10(ToolbarButton, { icon: "bxs-right-arrow", tooltip: "Arrow head", children: [
2146
- /* @__PURE__ */ jsx10("p", { className: "text-xs text-text-secondary uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.head") }),
2147
- /* @__PURE__ */ jsx10("div", { className: "flex items-center gap-1", children: HEAD_STYLES.map((h) => /* @__PURE__ */ jsx10(
2269
+ return /* @__PURE__ */ jsxs11(ShapeSidebar, { visible: activeTool === TOOLS.ARROW || selectedShapeSidebar === "arrow", children: [
2270
+ /* @__PURE__ */ jsxs11(ToolbarButton, { icon: "bxs-right-arrow", tooltip: "Arrow head", children: [
2271
+ /* @__PURE__ */ jsx11("p", { className: "text-xs text-text-secondary uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.head") }),
2272
+ /* @__PURE__ */ jsx11("div", { className: "flex items-center gap-1", children: HEAD_STYLES.map((h) => /* @__PURE__ */ jsx11(
2148
2273
  "button",
2149
2274
  {
2150
2275
  onClick: () => updateHead(h.value),
2151
2276
  className: `w-10 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${headStyle === h.value ? "bg-[#7667a8]/20 text-[#7667a8]" : "text-text-secondary hover:bg-white/[0.06]"}`,
2152
- children: /* @__PURE__ */ jsx10(SvgIcon, { svg: h.svg })
2277
+ children: /* @__PURE__ */ jsx11(SvgIcon, { svg: h.svg })
2153
2278
  },
2154
2279
  h.value
2155
2280
  )) })
2156
2281
  ] }),
2157
- /* @__PURE__ */ jsx10(Divider, {}),
2158
- /* @__PURE__ */ jsxs10(
2282
+ /* @__PURE__ */ jsx11(Divider, {}),
2283
+ /* @__PURE__ */ jsxs11(
2159
2284
  ToolbarButton,
2160
2285
  {
2161
2286
  tooltip: t("sidebar.strokeColor"),
2162
- preview: /* @__PURE__ */ jsx10("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: strokeColor } }),
2287
+ preview: /* @__PURE__ */ jsx11("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: strokeColor } }),
2163
2288
  children: [
2164
- /* @__PURE__ */ jsx10("p", { className: "text-xs text-text-secondary uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.stroke") }),
2165
- /* @__PURE__ */ jsx10(ColorGrid4, { colors: STROKE_COLORS4, selected: strokeColor, onSelect: updateStroke })
2289
+ /* @__PURE__ */ jsx11("p", { className: "text-xs text-text-secondary uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.stroke") }),
2290
+ /* @__PURE__ */ jsx11(ColorGrid4, { colors: STROKE_COLORS4, selected: strokeColor, onSelect: updateStroke })
2166
2291
  ]
2167
2292
  }
2168
2293
  ),
2169
- /* @__PURE__ */ jsx10(Divider, {}),
2170
- /* @__PURE__ */ jsxs10(ToolbarButton, { icon: "bxs-edit-alt", tooltip: t("sidebar.strokeWidth"), children: [
2171
- /* @__PURE__ */ jsx10("p", { className: "text-xs text-text-secondary uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.width") }),
2172
- /* @__PURE__ */ jsx10("div", { className: "flex items-center gap-1", children: [1, 2, 4, 7].map((w) => /* @__PURE__ */ jsx10(
2294
+ /* @__PURE__ */ jsx11(Divider, {}),
2295
+ /* @__PURE__ */ jsxs11(ToolbarButton, { icon: "bxs-edit-alt", tooltip: t("sidebar.strokeWidth"), children: [
2296
+ /* @__PURE__ */ jsx11("p", { className: "text-xs text-text-secondary uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.width") }),
2297
+ /* @__PURE__ */ jsx11("div", { className: "flex items-center gap-1", children: [1, 2, 4, 7].map((w) => /* @__PURE__ */ jsx11(
2173
2298
  "button",
2174
2299
  {
2175
2300
  onClick: () => updateThickness(w),
2176
2301
  className: `w-9 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${thickness === w ? "bg-[#7667a8]/20 text-[#7667a8]" : "text-text-secondary hover:bg-white/[0.06]"}`,
2177
- children: /* @__PURE__ */ jsx10("div", { className: "w-5 rounded-full bg-current", style: { height: Math.max(1, w) } })
2302
+ children: /* @__PURE__ */ jsx11("div", { className: "w-5 rounded-full bg-current", style: { height: Math.max(1, w) } })
2178
2303
  },
2179
2304
  w
2180
2305
  )) })
2181
2306
  ] }),
2182
- /* @__PURE__ */ jsx10(Divider, {}),
2183
- /* @__PURE__ */ jsxs10(ToolbarButton, { icon: "bxs-minus-circle", tooltip: "Stroke style", children: [
2184
- /* @__PURE__ */ jsx10("p", { className: "text-xs text-text-secondary uppercase tracking-wider mb-2", children: t("sidebar.style") }),
2185
- /* @__PURE__ */ jsx10("div", { className: "flex items-center gap-1", children: [{ v: "solid", d: "" }, { v: "dashed", d: "6 4" }, { v: "dotted", d: "2 3" }].map((s) => /* @__PURE__ */ jsx10(
2307
+ /* @__PURE__ */ jsx11(Divider, {}),
2308
+ /* @__PURE__ */ jsxs11(ToolbarButton, { icon: "bxs-minus-circle", tooltip: "Stroke style", children: [
2309
+ /* @__PURE__ */ jsx11("p", { className: "text-xs text-text-secondary uppercase tracking-wider mb-2", children: t("sidebar.style") }),
2310
+ /* @__PURE__ */ jsx11("div", { className: "flex items-center gap-1", children: [{ v: "solid", d: "" }, { v: "dashed", d: "6 4" }, { v: "dotted", d: "2 3" }].map((s) => /* @__PURE__ */ jsx11(
2186
2311
  "button",
2187
2312
  {
2188
2313
  onClick: () => updateOutline(s.v),
2189
2314
  className: `w-11 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${outlineStyle === s.v ? "bg-[#7667a8]/20" : "hover:bg-white/[0.06]"}`,
2190
- children: /* @__PURE__ */ jsx10("svg", { width: "28", height: "4", viewBox: "0 0 28 4", children: /* @__PURE__ */ jsx10("line", { x1: "0", y1: "2", x2: "28", y2: "2", stroke: "#fff", strokeWidth: "2", strokeDasharray: s.d, strokeLinecap: "round" }) })
2315
+ children: /* @__PURE__ */ jsx11("svg", { width: "28", height: "4", viewBox: "0 0 28 4", children: /* @__PURE__ */ jsx11("line", { x1: "0", y1: "2", x2: "28", y2: "2", stroke: "#fff", strokeWidth: "2", strokeDasharray: s.d, strokeLinecap: "round" }) })
2191
2316
  },
2192
2317
  s.v
2193
2318
  )) })
2194
2319
  ] }),
2195
- /* @__PURE__ */ jsx10(Divider, {}),
2196
- /* @__PURE__ */ jsxs10(ToolbarButton, { icon: "bxs-share-alt", tooltip: "Arrow type", children: [
2197
- /* @__PURE__ */ jsx10("p", { className: "text-xs text-text-secondary uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.type") }),
2198
- /* @__PURE__ */ jsxs10("div", { className: "flex flex-col gap-0.5", children: [
2320
+ /* @__PURE__ */ jsx11(Divider, {}),
2321
+ /* @__PURE__ */ jsxs11(ToolbarButton, { icon: "bxs-share-alt", tooltip: "Arrow type", children: [
2322
+ /* @__PURE__ */ jsx11("p", { className: "text-xs text-text-secondary uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.type") }),
2323
+ /* @__PURE__ */ jsxs11("div", { className: "flex flex-col gap-0.5", children: [
2199
2324
  [
2200
2325
  { v: "straight", i: "bxs-right-arrow-alt", l: "Straight" },
2201
2326
  { v: "curved", i: "bxs-analyse", l: "Curved" },
2202
2327
  { v: "elbow", i: "bxs-network-chart", l: "Elbow" }
2203
- ].map((a) => /* @__PURE__ */ jsxs10(
2328
+ ].map((a) => /* @__PURE__ */ jsxs11(
2204
2329
  "button",
2205
2330
  {
2206
2331
  onClick: () => updateType(a.v),
2207
2332
  className: `flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${arrowType === a.v ? "bg-[#7667a8] text-white" : "text-text-secondary hover:bg-white/[0.06]"}`,
2208
2333
  children: [
2209
- /* @__PURE__ */ jsx10("i", { className: `bx ${a.i} text-sm` }),
2334
+ /* @__PURE__ */ jsx11("i", { className: `bx ${a.i} text-sm` }),
2210
2335
  " ",
2211
2336
  a.l
2212
2337
  ]
2213
2338
  },
2214
2339
  a.v
2215
2340
  )),
2216
- arrowType === "curved" && /* @__PURE__ */ jsxs10(Fragment5, { children: [
2217
- /* @__PURE__ */ jsx10("div", { className: "w-full h-px bg-white/[0.08] my-1" }),
2218
- /* @__PURE__ */ jsx10("p", { className: "text-[9px] text-text-dim uppercase tracking-wider mb-1", children: "Curvature" }),
2219
- /* @__PURE__ */ jsx10("div", { className: "flex items-center gap-1", children: [{ v: 8, l: "Lo" }, { v: 20, l: "Md" }, { v: 40, l: "Hi" }].map((c) => /* @__PURE__ */ jsx10(
2341
+ arrowType === "curved" && /* @__PURE__ */ jsxs11(Fragment5, { children: [
2342
+ /* @__PURE__ */ jsx11("div", { className: "w-full h-px bg-white/[0.08] my-1" }),
2343
+ /* @__PURE__ */ jsx11("p", { className: "text-[9px] text-text-dim uppercase tracking-wider mb-1", children: "Curvature" }),
2344
+ /* @__PURE__ */ jsx11("div", { className: "flex items-center gap-1", children: [{ v: 8, l: "Lo" }, { v: 20, l: "Md" }, { v: 40, l: "Hi" }].map((c) => /* @__PURE__ */ jsx11(
2220
2345
  "button",
2221
2346
  {
2222
2347
  onClick: () => updateCurvature(c.v),
@@ -2228,18 +2353,18 @@ function ArrowSidebar() {
2228
2353
  ] })
2229
2354
  ] })
2230
2355
  ] }),
2231
- /* @__PURE__ */ jsx10(Divider, {}),
2232
- /* @__PURE__ */ jsx10(LayerControls, {})
2356
+ /* @__PURE__ */ jsx11(Divider, {}),
2357
+ /* @__PURE__ */ jsx11(LayerControls, {})
2233
2358
  ] });
2234
2359
  }
2235
2360
 
2236
2361
  // src/react/components/sidebars/PaintbrushSidebar.jsx
2237
- import { useState as useState9, useCallback as useCallback6 } from "react";
2238
- import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
2362
+ import { useState as useState11, useCallback as useCallback7 } from "react";
2363
+ import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
2239
2364
  var STROKE_COLORS5 = ["#1a1a20", "#ffffff", "#FF8383", "#3A994C", "#56A2E8", "#FFD700", "#FF69B4", "#A855F7"];
2240
2365
  var TAPER_MAP = { uniform: 0, pen: 0.5, brush: 0.8 };
2241
2366
  function ColorGrid5({ colors, selected, onSelect }) {
2242
- return /* @__PURE__ */ jsx11("div", { className: "grid grid-cols-4 gap-1.5", children: colors.map((c) => /* @__PURE__ */ jsx11(
2367
+ return /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-4 gap-1.5", children: colors.map((c) => /* @__PURE__ */ jsx12(
2243
2368
  "button",
2244
2369
  {
2245
2370
  onClick: () => onSelect(c),
@@ -2253,71 +2378,71 @@ function PaintbrushSidebar() {
2253
2378
  const { t } = useTranslation();
2254
2379
  const activeTool = useSketchStore_default((s) => s.activeTool);
2255
2380
  const selectedShapeSidebar = useSketchStore_default((s) => s.selectedShapeSidebar);
2256
- const [strokeColor, setStrokeColor] = useState9("#fff");
2257
- const [thickness, setThickness] = useState9(2);
2258
- const [lineStyle, setLineStyle] = useState9("solid");
2259
- const [taper, setTaper] = useState9("uniform");
2260
- const [roughness, setRoughness] = useState9("smooth");
2261
- const [opacity, setOpacity] = useState9(1);
2262
- const updateStroke = useCallback6((v) => {
2381
+ const [strokeColor, setStrokeColor] = useState11("#fff");
2382
+ const [thickness, setThickness] = useState11(2);
2383
+ const [lineStyle, setLineStyle] = useState11("solid");
2384
+ const [taper, setTaper] = useState11("uniform");
2385
+ const [roughness, setRoughness] = useState11("smooth");
2386
+ const [opacity, setOpacity] = useState11(1);
2387
+ const updateStroke = useCallback7((v) => {
2263
2388
  setStrokeColor(v);
2264
2389
  if (window.updateSelectedFreehandStyle) window.updateSelectedFreehandStyle({ stroke: v });
2265
2390
  }, []);
2266
- const updateThickness = useCallback6((v) => {
2391
+ const updateThickness = useCallback7((v) => {
2267
2392
  setThickness(v);
2268
2393
  if (window.updateSelectedFreehandStyle) window.updateSelectedFreehandStyle({ strokeWidth: v });
2269
2394
  }, []);
2270
- const updateTaper = useCallback6((v) => {
2395
+ const updateTaper = useCallback7((v) => {
2271
2396
  setTaper(v);
2272
2397
  if (window.updateSelectedFreehandStyle) window.updateSelectedFreehandStyle({ thinning: TAPER_MAP[v] });
2273
2398
  }, []);
2274
- const updateRoughness = useCallback6((v) => {
2399
+ const updateRoughness = useCallback7((v) => {
2275
2400
  setRoughness(v);
2276
2401
  if (window.updateSelectedFreehandStyle) window.updateSelectedFreehandStyle({ roughness: v });
2277
2402
  }, []);
2278
- const updateOpacity = useCallback6((v) => {
2403
+ const updateOpacity = useCallback7((v) => {
2279
2404
  setOpacity(v);
2280
2405
  if (window.updateSelectedFreehandStyle) window.updateSelectedFreehandStyle({ opacity: v });
2281
2406
  }, []);
2282
- return /* @__PURE__ */ jsxs11(ShapeSidebar, { visible: activeTool === TOOLS.FREEHAND || selectedShapeSidebar === "paintbrush", children: [
2283
- /* @__PURE__ */ jsxs11(
2407
+ return /* @__PURE__ */ jsxs12(ShapeSidebar, { visible: activeTool === TOOLS.FREEHAND || activeTool === TOOLS.DRAW_SHAPE || selectedShapeSidebar === "paintbrush", children: [
2408
+ /* @__PURE__ */ jsxs12(
2284
2409
  ToolbarButton,
2285
2410
  {
2286
2411
  tooltip: t("sidebar.strokeColor"),
2287
- preview: /* @__PURE__ */ jsx11("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: strokeColor } }),
2412
+ preview: /* @__PURE__ */ jsx12("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: strokeColor } }),
2288
2413
  children: [
2289
- /* @__PURE__ */ jsx11("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.stroke") }),
2290
- /* @__PURE__ */ jsx11(ColorGrid5, { colors: STROKE_COLORS5, selected: strokeColor, onSelect: updateStroke })
2414
+ /* @__PURE__ */ jsx12("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.stroke") }),
2415
+ /* @__PURE__ */ jsx12(ColorGrid5, { colors: STROKE_COLORS5, selected: strokeColor, onSelect: updateStroke })
2291
2416
  ]
2292
2417
  }
2293
2418
  ),
2294
- /* @__PURE__ */ jsx11(Divider, {}),
2295
- /* @__PURE__ */ jsxs11(ToolbarButton, { icon: "bxs-edit-alt", tooltip: t("sidebar.strokeWidth"), children: [
2296
- /* @__PURE__ */ jsx11("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.width") }),
2297
- /* @__PURE__ */ jsx11("div", { className: "flex items-center gap-1", children: [1, 2, 4, 7].map((w) => /* @__PURE__ */ jsx11(
2419
+ /* @__PURE__ */ jsx12(Divider, {}),
2420
+ /* @__PURE__ */ jsxs12(ToolbarButton, { icon: "bxs-edit-alt", tooltip: t("sidebar.strokeWidth"), children: [
2421
+ /* @__PURE__ */ jsx12("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.width") }),
2422
+ /* @__PURE__ */ jsx12("div", { className: "flex items-center gap-1", children: [1, 2, 4, 7].map((w) => /* @__PURE__ */ jsx12(
2298
2423
  "button",
2299
2424
  {
2300
2425
  onClick: () => updateThickness(w),
2301
2426
  className: `w-9 h-8 flex items-center justify-center rounded-lg transition-all duration-100 ${thickness === w ? "bg-[#7667a8]/20 text-[#7667a8]" : "text-text-muted hover:bg-white/[0.06]"}`,
2302
- children: /* @__PURE__ */ jsx11("div", { className: "w-5 rounded-full bg-current", style: { height: Math.max(1, w) } })
2427
+ children: /* @__PURE__ */ jsx12("div", { className: "w-5 rounded-full bg-current", style: { height: Math.max(1, w) } })
2303
2428
  },
2304
2429
  w
2305
2430
  )) })
2306
2431
  ] }),
2307
- /* @__PURE__ */ jsx11(Divider, {}),
2308
- /* @__PURE__ */ jsxs11(ToolbarButton, { icon: "bxs-pen", tooltip: "Taper", children: [
2309
- /* @__PURE__ */ jsx11("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.taper") }),
2310
- /* @__PURE__ */ jsx11("div", { className: "flex flex-col gap-0.5", children: [
2432
+ /* @__PURE__ */ jsx12(Divider, {}),
2433
+ /* @__PURE__ */ jsxs12(ToolbarButton, { icon: "bxs-pen", tooltip: "Taper", children: [
2434
+ /* @__PURE__ */ jsx12("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.taper") }),
2435
+ /* @__PURE__ */ jsx12("div", { className: "flex flex-col gap-0.5", children: [
2311
2436
  { v: "uniform", i: "bxs-minus-circle", l: "Uniform" },
2312
2437
  { v: "pen", i: "bxs-pen", l: "Pen" },
2313
2438
  { v: "brush", i: "bxs-brush", l: "Brush" }
2314
- ].map((t2) => /* @__PURE__ */ jsxs11(
2439
+ ].map((t2) => /* @__PURE__ */ jsxs12(
2315
2440
  "button",
2316
2441
  {
2317
2442
  onClick: () => updateTaper(t2.v),
2318
2443
  className: `flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${taper === t2.v ? "bg-[#7667a8] text-white" : "text-text-secondary hover:bg-white/[0.06]"}`,
2319
2444
  children: [
2320
- /* @__PURE__ */ jsx11("i", { className: `bx ${t2.i} text-sm` }),
2445
+ /* @__PURE__ */ jsx12("i", { className: `bx ${t2.i} text-sm` }),
2321
2446
  " ",
2322
2447
  t2.l
2323
2448
  ]
@@ -2325,20 +2450,20 @@ function PaintbrushSidebar() {
2325
2450
  t2.v
2326
2451
  )) })
2327
2452
  ] }),
2328
- /* @__PURE__ */ jsx11(Divider, {}),
2329
- /* @__PURE__ */ jsxs11(ToolbarButton, { icon: "bxs-shape-polygon", tooltip: "Roughness", children: [
2330
- /* @__PURE__ */ jsx11("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.roughness") }),
2331
- /* @__PURE__ */ jsx11("div", { className: "flex flex-col gap-0.5", children: [
2453
+ /* @__PURE__ */ jsx12(Divider, {}),
2454
+ /* @__PURE__ */ jsxs12(ToolbarButton, { icon: "bxs-shape-polygon", tooltip: "Roughness", children: [
2455
+ /* @__PURE__ */ jsx12("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.roughness") }),
2456
+ /* @__PURE__ */ jsx12("div", { className: "flex flex-col gap-0.5", children: [
2332
2457
  { v: "smooth", i: "bxs-droplet", l: "Smooth" },
2333
2458
  { v: "medium", i: "bxs-leaf", l: "Medium" },
2334
2459
  { v: "rough", i: "bxs-bolt", l: "Rough" }
2335
- ].map((r) => /* @__PURE__ */ jsxs11(
2460
+ ].map((r) => /* @__PURE__ */ jsxs12(
2336
2461
  "button",
2337
2462
  {
2338
2463
  onClick: () => updateRoughness(r.v),
2339
2464
  className: `flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${roughness === r.v ? "bg-[#7667a8] text-white" : "text-text-secondary hover:bg-white/[0.06]"}`,
2340
2465
  children: [
2341
- /* @__PURE__ */ jsx11("i", { className: `bx ${r.i} text-sm` }),
2466
+ /* @__PURE__ */ jsx12("i", { className: `bx ${r.i} text-sm` }),
2342
2467
  " ",
2343
2468
  r.l
2344
2469
  ]
@@ -2346,14 +2471,14 @@ function PaintbrushSidebar() {
2346
2471
  r.v
2347
2472
  )) })
2348
2473
  ] }),
2349
- /* @__PURE__ */ jsx11(Divider, {}),
2350
- /* @__PURE__ */ jsxs11(ToolbarButton, { icon: "bxs-sun", tooltip: t("sidebar.opacity"), children: [
2351
- /* @__PURE__ */ jsxs11("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: [
2474
+ /* @__PURE__ */ jsx12(Divider, {}),
2475
+ /* @__PURE__ */ jsxs12(ToolbarButton, { icon: "bxs-sun", tooltip: t("sidebar.opacity"), children: [
2476
+ /* @__PURE__ */ jsxs12("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: [
2352
2477
  "Opacity ",
2353
2478
  Math.round(opacity * 100),
2354
2479
  "%"
2355
2480
  ] }),
2356
- /* @__PURE__ */ jsx11(
2481
+ /* @__PURE__ */ jsx12(
2357
2482
  "input",
2358
2483
  {
2359
2484
  type: "range",
@@ -2366,14 +2491,14 @@ function PaintbrushSidebar() {
2366
2491
  }
2367
2492
  )
2368
2493
  ] }),
2369
- /* @__PURE__ */ jsx11(Divider, {}),
2370
- /* @__PURE__ */ jsx11(LayerControls, {})
2494
+ /* @__PURE__ */ jsx12(Divider, {}),
2495
+ /* @__PURE__ */ jsx12(LayerControls, {})
2371
2496
  ] });
2372
2497
  }
2373
2498
 
2374
2499
  // src/react/components/sidebars/TextSidebar.jsx
2375
- import { useState as useState10, useCallback as useCallback7, useEffect as useEffect6 } from "react";
2376
- import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
2500
+ import { useState as useState12, useCallback as useCallback8, useEffect as useEffect8 } from "react";
2501
+ import { Fragment as Fragment6, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
2377
2502
  var TEXT_COLORS = ["#1a1a20", "#ffffff", "#FF8383", "#3A994C", "#56A2E8", "#FFD700", "#FF69B4", "#A855F7"];
2378
2503
  var FONTS = [
2379
2504
  { value: "lixFont", label: "Lix" },
@@ -2408,12 +2533,12 @@ function TextSidebar() {
2408
2533
  const { t } = useTranslation();
2409
2534
  const activeTool = useSketchStore_default((s) => s.activeTool);
2410
2535
  const selectedShapeSidebar = useSketchStore_default((s) => s.selectedShapeSidebar);
2411
- const [textColor, setTextColor] = useState10("#fff");
2412
- const [fontSize, setFontSize] = useState10("S");
2413
- const [font, setFont] = useState10("lixFont");
2414
- const [codeMode, setCodeMode] = useState10(false);
2415
- const [language, setLanguage] = useState10("javascript");
2416
- useEffect6(() => {
2536
+ const [textColor, setTextColor] = useState12("#fff");
2537
+ const [fontSize, setFontSize] = useState12("S");
2538
+ const [font, setFont] = useState12("lixFont");
2539
+ const [codeMode, setCodeMode] = useState12(false);
2540
+ const [language, setLanguage] = useState12("javascript");
2541
+ useEffect8(() => {
2417
2542
  window.__onCodeModeChanged = (isCode) => {
2418
2543
  setCodeMode(isCode);
2419
2544
  window.isTextInCodeMode = isCode;
@@ -2422,19 +2547,19 @@ function TextSidebar() {
2422
2547
  window.__onCodeModeChanged = null;
2423
2548
  };
2424
2549
  }, []);
2425
- const updateColor = useCallback7((c) => {
2550
+ const updateColor = useCallback8((c) => {
2426
2551
  setTextColor(c);
2427
2552
  if (window.updateSelectedTextStyle) window.updateSelectedTextStyle({ color: c });
2428
2553
  }, []);
2429
- const updateFont = useCallback7((f) => {
2554
+ const updateFont = useCallback8((f) => {
2430
2555
  setFont(f);
2431
2556
  if (window.updateSelectedTextStyle) window.updateSelectedTextStyle({ font: f });
2432
2557
  }, []);
2433
- const updateSize = useCallback7((s) => {
2558
+ const updateSize = useCallback8((s) => {
2434
2559
  setFontSize(s);
2435
2560
  if (window.updateSelectedTextStyle) window.updateSelectedTextStyle({ fontSize: SIZE_MAP[s] });
2436
2561
  }, []);
2437
- const toggleCodeMode = useCallback7(() => {
2562
+ const toggleCodeMode = useCallback8(() => {
2438
2563
  const next = !codeMode;
2439
2564
  setCodeMode(next);
2440
2565
  window.isTextInCodeMode = next;
@@ -2444,21 +2569,21 @@ function TextSidebar() {
2444
2569
  if (window.__convertCodeToText) window.__convertCodeToText();
2445
2570
  }
2446
2571
  }, [codeMode]);
2447
- const updateLanguage = useCallback7((lang) => {
2572
+ const updateLanguage = useCallback8((lang) => {
2448
2573
  setLanguage(lang);
2449
2574
  if (window.__setCodeLanguage) window.__setCodeLanguage(lang);
2450
2575
  }, []);
2451
2576
  const visible = activeTool === TOOLS.TEXT || activeTool === TOOLS.CODE || selectedShapeSidebar === "text";
2452
- return /* @__PURE__ */ jsxs12(Fragment6, { children: [
2453
- /* @__PURE__ */ jsxs12(ShapeSidebar, { visible, children: [
2454
- /* @__PURE__ */ jsxs12(
2577
+ return /* @__PURE__ */ jsxs13(Fragment6, { children: [
2578
+ /* @__PURE__ */ jsxs13(ShapeSidebar, { visible, children: [
2579
+ /* @__PURE__ */ jsxs13(
2455
2580
  ToolbarButton,
2456
2581
  {
2457
2582
  tooltip: t("sidebar.textColor"),
2458
- preview: /* @__PURE__ */ jsx12("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: textColor } }),
2583
+ preview: /* @__PURE__ */ jsx13("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: textColor } }),
2459
2584
  children: [
2460
- /* @__PURE__ */ jsx12("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.color") }),
2461
- /* @__PURE__ */ jsx12("div", { className: "grid grid-cols-4 gap-1.5", children: TEXT_COLORS.map((c) => /* @__PURE__ */ jsx12(
2585
+ /* @__PURE__ */ jsx13("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.color") }),
2586
+ /* @__PURE__ */ jsx13("div", { className: "grid grid-cols-4 gap-1.5", children: TEXT_COLORS.map((c) => /* @__PURE__ */ jsx13(
2462
2587
  "button",
2463
2588
  {
2464
2589
  onClick: () => updateColor(c),
@@ -2470,11 +2595,11 @@ function TextSidebar() {
2470
2595
  ]
2471
2596
  }
2472
2597
  ),
2473
- !codeMode && /* @__PURE__ */ jsxs12(Fragment6, { children: [
2474
- /* @__PURE__ */ jsx12(Divider, {}),
2475
- /* @__PURE__ */ jsxs12(ToolbarButton, { icon: "bxs-font-family", tooltip: t("sidebar.font"), children: [
2476
- /* @__PURE__ */ jsx12("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.font") }),
2477
- /* @__PURE__ */ jsx12("div", { className: "flex flex-col gap-0.5", children: FONTS.map((f) => /* @__PURE__ */ jsx12(
2598
+ !codeMode && /* @__PURE__ */ jsxs13(Fragment6, { children: [
2599
+ /* @__PURE__ */ jsx13(Divider, {}),
2600
+ /* @__PURE__ */ jsxs13(ToolbarButton, { icon: "bxs-font-family", tooltip: t("sidebar.font"), children: [
2601
+ /* @__PURE__ */ jsx13("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.font") }),
2602
+ /* @__PURE__ */ jsx13("div", { className: "flex flex-col gap-0.5", children: FONTS.map((f) => /* @__PURE__ */ jsx13(
2478
2603
  "button",
2479
2604
  {
2480
2605
  onClick: () => updateFont(f.value),
@@ -2486,10 +2611,10 @@ function TextSidebar() {
2486
2611
  )) })
2487
2612
  ] })
2488
2613
  ] }),
2489
- /* @__PURE__ */ jsx12(Divider, {}),
2490
- /* @__PURE__ */ jsxs12(ToolbarButton, { icon: "bxs-chevrons-up", tooltip: t("sidebar.size"), children: [
2491
- /* @__PURE__ */ jsx12("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.size") }),
2492
- /* @__PURE__ */ jsx12("div", { className: "flex items-center gap-1", children: ["S", "M", "L", "XL"].map((s) => /* @__PURE__ */ jsx12(
2614
+ /* @__PURE__ */ jsx13(Divider, {}),
2615
+ /* @__PURE__ */ jsxs13(ToolbarButton, { icon: "bxs-chevrons-up", tooltip: t("sidebar.size"), children: [
2616
+ /* @__PURE__ */ jsx13("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.size") }),
2617
+ /* @__PURE__ */ jsx13("div", { className: "flex items-center gap-1", children: ["S", "M", "L", "XL"].map((s) => /* @__PURE__ */ jsx13(
2493
2618
  "button",
2494
2619
  {
2495
2620
  onClick: () => updateSize(s),
@@ -2499,22 +2624,22 @@ function TextSidebar() {
2499
2624
  s
2500
2625
  )) })
2501
2626
  ] }),
2502
- /* @__PURE__ */ jsx12(Divider, {}),
2503
- /* @__PURE__ */ jsxs12(ToolbarButton, { icon: "bxs-terminal", tooltip: t("sidebar.codeMode"), children: [
2504
- /* @__PURE__ */ jsx12("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.code") }),
2505
- /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-2", children: [
2506
- /* @__PURE__ */ jsxs12(
2627
+ /* @__PURE__ */ jsx13(Divider, {}),
2628
+ /* @__PURE__ */ jsxs13(ToolbarButton, { icon: "bxs-terminal", tooltip: t("sidebar.codeMode"), children: [
2629
+ /* @__PURE__ */ jsx13("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.code") }),
2630
+ /* @__PURE__ */ jsxs13("div", { className: "flex flex-col gap-2", children: [
2631
+ /* @__PURE__ */ jsxs13(
2507
2632
  "button",
2508
2633
  {
2509
2634
  onClick: toggleCodeMode,
2510
2635
  className: `flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${codeMode ? "bg-[#7667a8] text-white" : "text-text-secondary hover:bg-white/[0.06]"}`,
2511
2636
  children: [
2512
- /* @__PURE__ */ jsx12("div", { className: `w-6 h-3 rounded-full transition-all duration-150 relative ${codeMode ? "bg-white/30" : "bg-white/10"}`, children: /* @__PURE__ */ jsx12("div", { className: `absolute top-0.5 w-2 h-2 rounded-full bg-white transition-all duration-150 ${codeMode ? "left-3.5" : "left-0.5"}` }) }),
2637
+ /* @__PURE__ */ jsx13("div", { className: `w-6 h-3 rounded-full transition-all duration-150 relative ${codeMode ? "bg-white/30" : "bg-white/10"}`, children: /* @__PURE__ */ jsx13("div", { className: `absolute top-0.5 w-2 h-2 rounded-full bg-white transition-all duration-150 ${codeMode ? "left-3.5" : "left-0.5"}` }) }),
2513
2638
  codeMode ? t("sidebar.on") : t("sidebar.off")
2514
2639
  ]
2515
2640
  }
2516
2641
  ),
2517
- codeMode && /* @__PURE__ */ jsx12("div", { className: "flex flex-wrap gap-1 max-w-[180px]", children: LANGUAGES.map((lang) => /* @__PURE__ */ jsx12(
2642
+ codeMode && /* @__PURE__ */ jsx13("div", { className: "flex flex-wrap gap-1 max-w-[180px]", children: LANGUAGES.map((lang) => /* @__PURE__ */ jsx13(
2518
2643
  "button",
2519
2644
  {
2520
2645
  onClick: () => updateLanguage(lang),
@@ -2525,21 +2650,21 @@ function TextSidebar() {
2525
2650
  )) })
2526
2651
  ] })
2527
2652
  ] }),
2528
- /* @__PURE__ */ jsx12(Divider, {}),
2529
- /* @__PURE__ */ jsx12(LayerControls, {})
2653
+ /* @__PURE__ */ jsx13(Divider, {}),
2654
+ /* @__PURE__ */ jsx13(LayerControls, {})
2530
2655
  ] }),
2531
- /* @__PURE__ */ jsx12(
2656
+ /* @__PURE__ */ jsx13(
2532
2657
  "div",
2533
2658
  {
2534
2659
  className: `absolute bottom-7 left-1/2 -translate-x-1/2 z-[998] font-[lixFont] transition-all duration-200 ${visible ? "opacity-100 translate-y-0" : "opacity-0 pointer-events-none translate-y-2"}`,
2535
- children: /* @__PURE__ */ jsxs12("p", { className: "text-[10px] text-white/30 leading-relaxed text-center whitespace-nowrap", children: [
2536
- /* @__PURE__ */ jsx12("span", { className: "text-white/50", children: "Ctrl+Enter" }),
2660
+ children: /* @__PURE__ */ jsxs13("p", { className: "text-[10px] text-white/30 leading-relaxed text-center whitespace-nowrap", children: [
2661
+ /* @__PURE__ */ jsx13("span", { className: "text-white/50", children: "Ctrl+Enter" }),
2537
2662
  " / ",
2538
- /* @__PURE__ */ jsx12("span", { className: "text-white/50", children: "Enter" }),
2663
+ /* @__PURE__ */ jsx13("span", { className: "text-white/50", children: "Enter" }),
2539
2664
  " \u2014 ",
2540
2665
  t("sidebar.renderText"),
2541
2666
  " \xA0\xA0",
2542
- /* @__PURE__ */ jsx12("span", { className: "text-white/50", children: "Shift+Enter" }),
2667
+ /* @__PURE__ */ jsx13("span", { className: "text-white/50", children: "Shift+Enter" }),
2543
2668
  " \u2014 ",
2544
2669
  t("sidebar.newLine")
2545
2670
  ] })
@@ -2549,8 +2674,8 @@ function TextSidebar() {
2549
2674
  }
2550
2675
 
2551
2676
  // src/react/components/sidebars/FrameSidebar.jsx
2552
- import { useState as useState11, useCallback as useCallback8, useEffect as useEffect7 } from "react";
2553
- import { Fragment as Fragment7, jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
2677
+ import { useState as useState13, useCallback as useCallback9, useEffect as useEffect9 } from "react";
2678
+ import { Fragment as Fragment7, jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
2554
2679
  var FILL_STYLES = [
2555
2680
  { id: "transparent", label: "None", icon: "bx-x" },
2556
2681
  { id: "solid", label: "Solid", icon: "bxs-square" },
@@ -2569,11 +2694,11 @@ function FrameSidebar() {
2569
2694
  const activeTool = useSketchStore_default((s) => s.activeTool);
2570
2695
  const selectedShapeSidebar = useSketchStore_default((s) => s.selectedShapeSidebar);
2571
2696
  const toggleAIModal = useUIStore_default((s) => s.toggleAIModal);
2572
- const [frameName, setFrameName] = useState11("Frame 1");
2573
- const [isGraph, setIsGraph] = useState11(false);
2574
- const [fillStyle, setFillStyle] = useState11("transparent");
2575
- const [fillColor, setFillColor] = useState11("#1e1e28");
2576
- useEffect7(() => {
2697
+ const [frameName, setFrameName] = useState13("Frame 1");
2698
+ const [isGraph, setIsGraph] = useState13(false);
2699
+ const [fillStyle, setFillStyle] = useState13("transparent");
2700
+ const [fillColor, setFillColor] = useState13("#1e1e28");
2701
+ useEffect9(() => {
2577
2702
  if (selectedShapeSidebar === "frame" || activeTool === TOOLS.FRAME) {
2578
2703
  const shape = typeof window !== "undefined" ? window.currentShape : null;
2579
2704
  if (shape && shape.shapeName === "frame") {
@@ -2588,7 +2713,7 @@ function FrameSidebar() {
2588
2713
  }
2589
2714
  }
2590
2715
  }, [selectedShapeSidebar, activeTool]);
2591
- const updateName = useCallback8((e) => {
2716
+ const updateName = useCallback9((e) => {
2592
2717
  const name = e.target.value;
2593
2718
  setFrameName(name);
2594
2719
  const shape = window.currentShape;
@@ -2597,7 +2722,7 @@ function FrameSidebar() {
2597
2722
  shape.draw();
2598
2723
  }
2599
2724
  }, []);
2600
- const updateFillStyle = useCallback8((style) => {
2725
+ const updateFillStyle = useCallback9((style) => {
2601
2726
  setFillStyle(style);
2602
2727
  const shape = window.currentShape;
2603
2728
  if (shape && shape.shapeName === "frame") {
@@ -2605,7 +2730,7 @@ function FrameSidebar() {
2605
2730
  shape.draw();
2606
2731
  }
2607
2732
  }, []);
2608
- const updateFillColor = useCallback8((color) => {
2733
+ const updateFillColor = useCallback9((color) => {
2609
2734
  setFillColor(color);
2610
2735
  const shape = window.currentShape;
2611
2736
  if (shape && shape.shapeName === "frame") {
@@ -2613,23 +2738,23 @@ function FrameSidebar() {
2613
2738
  shape.draw();
2614
2739
  }
2615
2740
  }, []);
2616
- const resizeToFit = useCallback8(() => {
2741
+ const resizeToFit = useCallback9(() => {
2617
2742
  const shape = window.currentShape;
2618
2743
  if (shape && shape.shapeName === "frame" && typeof shape.resizeToFitContents === "function") {
2619
2744
  shape.resizeToFitContents();
2620
2745
  }
2621
2746
  }, []);
2622
- const handleAIEdit = useCallback8(() => {
2747
+ const handleAIEdit = useCallback9(() => {
2623
2748
  const shape = window.currentShape;
2624
2749
  if (shape && shape.shapeName === "frame") {
2625
2750
  window.__aiEditTargetFrame = shape;
2626
2751
  toggleAIModal();
2627
2752
  }
2628
2753
  }, [toggleAIModal]);
2629
- return /* @__PURE__ */ jsxs13(ShapeSidebar, { visible: activeTool === TOOLS.FRAME || selectedShapeSidebar === "frame", children: [
2630
- /* @__PURE__ */ jsxs13(ToolbarButton, { icon: "bxs-rename", tooltip: "Frame name", children: [
2631
- /* @__PURE__ */ jsx13("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.name") }),
2632
- /* @__PURE__ */ jsx13(
2754
+ return /* @__PURE__ */ jsxs14(ShapeSidebar, { visible: activeTool === TOOLS.FRAME || selectedShapeSidebar === "frame", children: [
2755
+ /* @__PURE__ */ jsxs14(ToolbarButton, { icon: "bxs-rename", tooltip: "Frame name", children: [
2756
+ /* @__PURE__ */ jsx14("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.name") }),
2757
+ /* @__PURE__ */ jsx14(
2633
2758
  "input",
2634
2759
  {
2635
2760
  type: "text",
@@ -2640,26 +2765,26 @@ function FrameSidebar() {
2640
2765
  }
2641
2766
  )
2642
2767
  ] }),
2643
- /* @__PURE__ */ jsx13(Divider, {}),
2644
- /* @__PURE__ */ jsxs13(ToolbarButton, { icon: "bxs-palette", tooltip: "Fill style", children: [
2645
- /* @__PURE__ */ jsx13("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.background") }),
2646
- /* @__PURE__ */ jsx13("div", { className: "flex gap-1 mb-2.5", children: FILL_STYLES.map((s) => /* @__PURE__ */ jsxs13(
2768
+ /* @__PURE__ */ jsx14(Divider, {}),
2769
+ /* @__PURE__ */ jsxs14(ToolbarButton, { icon: "bxs-palette", tooltip: "Fill style", children: [
2770
+ /* @__PURE__ */ jsx14("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.background") }),
2771
+ /* @__PURE__ */ jsx14("div", { className: "flex gap-1 mb-2.5", children: FILL_STYLES.map((s) => /* @__PURE__ */ jsxs14(
2647
2772
  "button",
2648
2773
  {
2649
2774
  onClick: () => updateFillStyle(s.id),
2650
2775
  title: s.label,
2651
2776
  className: `flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-xs transition-all duration-100 ${fillStyle === s.id ? "bg-white/[0.12] text-white" : "text-text-muted hover:text-white hover:bg-white/[0.06]"}`,
2652
2777
  children: [
2653
- /* @__PURE__ */ jsx13("i", { className: `bx ${s.icon} text-sm` }),
2778
+ /* @__PURE__ */ jsx14("i", { className: `bx ${s.icon} text-sm` }),
2654
2779
  s.label
2655
2780
  ]
2656
2781
  },
2657
2782
  s.id
2658
2783
  )) }),
2659
- fillStyle !== "transparent" && /* @__PURE__ */ jsxs13(Fragment7, { children: [
2660
- /* @__PURE__ */ jsx13("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-1.5", children: t("sidebar.sectionHeader.color") }),
2661
- /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1.5", children: [
2662
- FILL_COLORS.map((c) => /* @__PURE__ */ jsx13(
2784
+ fillStyle !== "transparent" && /* @__PURE__ */ jsxs14(Fragment7, { children: [
2785
+ /* @__PURE__ */ jsx14("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-1.5", children: t("sidebar.sectionHeader.color") }),
2786
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-1.5", children: [
2787
+ FILL_COLORS.map((c) => /* @__PURE__ */ jsx14(
2663
2788
  "button",
2664
2789
  {
2665
2790
  onClick: () => updateFillColor(c),
@@ -2669,8 +2794,8 @@ function FrameSidebar() {
2669
2794
  },
2670
2795
  c
2671
2796
  )),
2672
- /* @__PURE__ */ jsxs13("label", { className: "w-6 h-6 rounded-md border-2 border-white/10 hover:border-white/30 cursor-pointer overflow-hidden relative transition-all duration-100", title: "Custom color", children: [
2673
- /* @__PURE__ */ jsx13(
2797
+ /* @__PURE__ */ jsxs14("label", { className: "w-6 h-6 rounded-md border-2 border-white/10 hover:border-white/30 cursor-pointer overflow-hidden relative transition-all duration-100", title: "Custom color", children: [
2798
+ /* @__PURE__ */ jsx14(
2674
2799
  "input",
2675
2800
  {
2676
2801
  type: "color",
@@ -2679,16 +2804,16 @@ function FrameSidebar() {
2679
2804
  className: "absolute inset-0 opacity-0 cursor-pointer"
2680
2805
  }
2681
2806
  ),
2682
- /* @__PURE__ */ jsx13("i", { className: "bx bx-palette text-xs text-text-muted absolute inset-0 flex items-center justify-center" })
2807
+ /* @__PURE__ */ jsx14("i", { className: "bx bx-palette text-xs text-text-muted absolute inset-0 flex items-center justify-center" })
2683
2808
  ] })
2684
2809
  ] })
2685
2810
  ] })
2686
2811
  ] }),
2687
- /* @__PURE__ */ jsx13(Divider, {}),
2688
- /* @__PURE__ */ jsxs13(ToolbarButton, { icon: "bx-image-alt", tooltip: "Background image", children: [
2689
- /* @__PURE__ */ jsx13("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.backgroundImage") }),
2690
- /* @__PURE__ */ jsxs13("div", { className: "flex gap-1.5 mb-2", children: [
2691
- /* @__PURE__ */ jsxs13(
2812
+ /* @__PURE__ */ jsx14(Divider, {}),
2813
+ /* @__PURE__ */ jsxs14(ToolbarButton, { icon: "bx-image-alt", tooltip: "Background image", children: [
2814
+ /* @__PURE__ */ jsx14("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-2", children: t("sidebar.sectionHeader.backgroundImage") }),
2815
+ /* @__PURE__ */ jsxs14("div", { className: "flex gap-1.5 mb-2", children: [
2816
+ /* @__PURE__ */ jsxs14(
2692
2817
  "button",
2693
2818
  {
2694
2819
  onClick: () => {
@@ -2719,12 +2844,12 @@ function FrameSidebar() {
2719
2844
  },
2720
2845
  className: "flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-text-secondary text-xs hover:bg-white/[0.06] hover:text-white transition-all duration-100",
2721
2846
  children: [
2722
- /* @__PURE__ */ jsx13("i", { className: "bx bx-upload text-sm" }),
2847
+ /* @__PURE__ */ jsx14("i", { className: "bx bx-upload text-sm" }),
2723
2848
  "Set Image"
2724
2849
  ]
2725
2850
  }
2726
2851
  ),
2727
- /* @__PURE__ */ jsxs13(
2852
+ /* @__PURE__ */ jsxs14(
2728
2853
  "button",
2729
2854
  {
2730
2855
  onClick: () => {
@@ -2736,7 +2861,7 @@ function FrameSidebar() {
2736
2861
  },
2737
2862
  className: "flex items-center gap-1.5 px-2.5 py-1.5 rounded-lg text-text-secondary text-xs hover:bg-white/[0.06] hover:text-red-400 transition-all duration-100",
2738
2863
  children: [
2739
- /* @__PURE__ */ jsx13("i", { className: "bx bx-x text-sm" }),
2864
+ /* @__PURE__ */ jsx14("i", { className: "bx bx-x text-sm" }),
2740
2865
  "Remove"
2741
2866
  ]
2742
2867
  }
@@ -2745,13 +2870,13 @@ function FrameSidebar() {
2745
2870
  (() => {
2746
2871
  const shape = typeof window !== "undefined" ? window.currentShape : null;
2747
2872
  if (!shape?.shapeName === "frame" || !shape?._frameImageURL) return null;
2748
- return /* @__PURE__ */ jsxs13(Fragment7, { children: [
2749
- /* @__PURE__ */ jsx13("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-1.5", children: t("sidebar.sectionHeader.fit") }),
2750
- /* @__PURE__ */ jsx13("div", { className: "flex gap-1", children: [
2873
+ return /* @__PURE__ */ jsxs14(Fragment7, { children: [
2874
+ /* @__PURE__ */ jsx14("p", { className: "text-xs text-text-muted uppercase tracking-wider mb-1.5", children: t("sidebar.sectionHeader.fit") }),
2875
+ /* @__PURE__ */ jsx14("div", { className: "flex gap-1", children: [
2751
2876
  { id: "cover", label: "Cover" },
2752
2877
  { id: "contain", label: "Contain" },
2753
2878
  { id: "fill", label: "Stretch" }
2754
- ].map((f) => /* @__PURE__ */ jsx13(
2879
+ ].map((f) => /* @__PURE__ */ jsx14(
2755
2880
  "button",
2756
2881
  {
2757
2882
  onClick: () => {
@@ -2768,19 +2893,19 @@ function FrameSidebar() {
2768
2893
  ] });
2769
2894
  })()
2770
2895
  ] }),
2771
- /* @__PURE__ */ jsx13(Divider, {}),
2772
- /* @__PURE__ */ jsx13(ToolbarButton, { icon: "bxs-expand", tooltip: "Actions", children: /* @__PURE__ */ jsxs13("button", { onClick: resizeToFit, className: "flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-text-secondary text-xs hover:bg-white/[0.06] hover:text-white transition-all duration-100", children: [
2773
- /* @__PURE__ */ jsx13("i", { className: "bx bxs-expand text-sm" }),
2896
+ /* @__PURE__ */ jsx14(Divider, {}),
2897
+ /* @__PURE__ */ jsx14(ToolbarButton, { icon: "bxs-expand", tooltip: "Actions", children: /* @__PURE__ */ jsxs14("button", { onClick: resizeToFit, className: "flex items-center gap-2 px-2.5 py-1.5 rounded-lg text-text-secondary text-xs hover:bg-white/[0.06] hover:text-white transition-all duration-100", children: [
2898
+ /* @__PURE__ */ jsx14("i", { className: "bx bxs-expand text-sm" }),
2774
2899
  "Resize to Fit"
2775
2900
  ] }) }),
2776
- /* @__PURE__ */ jsx13(Divider, {}),
2777
- /* @__PURE__ */ jsx13(LayerControls, {})
2901
+ /* @__PURE__ */ jsx14(Divider, {}),
2902
+ /* @__PURE__ */ jsx14(LayerControls, {})
2778
2903
  ] });
2779
2904
  }
2780
2905
 
2781
2906
  // src/react/components/sidebars/IconSidebar.jsx
2782
- import { useState as useState12, useEffect as useEffect8, useCallback as useCallback9, useRef as useRef5 } from "react";
2783
- import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
2907
+ import { useState as useState14, useEffect as useEffect10, useCallback as useCallback10, useRef as useRef6 } from "react";
2908
+ import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
2784
2909
  var DEFAULT_ICONS_ORIGIN = "https://sketch.elixpo.com";
2785
2910
  function getIconsBaseUrl() {
2786
2911
  if (typeof window === "undefined") return "";
@@ -2817,20 +2942,20 @@ function normalizeSvg(raw) {
2817
2942
  function IconCell({ icon, onClick }) {
2818
2943
  const name = icon.filename?.replace(".svg", "").replace(/_/g, " ") || "";
2819
2944
  const normalizedSvg = typeof document !== "undefined" && icon.svg ? normalizeSvg(icon.svg) : icon.svg;
2820
- return /* @__PURE__ */ jsx14(
2945
+ return /* @__PURE__ */ jsx15(
2821
2946
  "button",
2822
2947
  {
2823
2948
  onClick,
2824
2949
  title: name,
2825
2950
  style: { width: "44px", height: "44px", overflow: "hidden", flexShrink: 0, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "8px", cursor: "pointer", background: "transparent", border: "none", padding: 0 },
2826
2951
  className: "hover:bg-surface-hover transition-colors duration-100",
2827
- children: normalizedSvg ? /* @__PURE__ */ jsx14(
2952
+ children: normalizedSvg ? /* @__PURE__ */ jsx15(
2828
2953
  "div",
2829
2954
  {
2830
2955
  style: { width: "24px", height: "24px", overflow: "visible", flexShrink: 0, pointerEvents: "none", filter: "var(--lix-icon-filter, brightness(0) invert(1))" },
2831
2956
  dangerouslySetInnerHTML: { __html: normalizedSvg }
2832
2957
  }
2833
- ) : /* @__PURE__ */ jsx14(
2958
+ ) : /* @__PURE__ */ jsx15(
2834
2959
  "img",
2835
2960
  {
2836
2961
  src: `/icons/${encodeURIComponent(icon.filename)}`,
@@ -2847,19 +2972,19 @@ function IconSidebar() {
2847
2972
  const activeTool = useSketchStore_default((s) => s.activeTool);
2848
2973
  const setActiveTool = useSketchStore_default((s) => s.setActiveTool);
2849
2974
  const visible = activeTool === TOOLS.ICON;
2850
- const [query, setQuery] = useState12("");
2851
- const [category, setCategory] = useState12(null);
2852
- const [icons, setIcons] = useState12([]);
2853
- const [loading, setLoading] = useState12(false);
2854
- const debounceRef = useRef5(null);
2855
- const searchInputRef = useRef5(null);
2856
- const requestSequenceRef = useRef5(0);
2857
- useEffect8(() => {
2975
+ const [query, setQuery] = useState14("");
2976
+ const [category, setCategory] = useState14(null);
2977
+ const [icons, setIcons] = useState14([]);
2978
+ const [loading, setLoading] = useState14(false);
2979
+ const debounceRef = useRef6(null);
2980
+ const searchInputRef = useRef6(null);
2981
+ const requestSequenceRef = useRef6(0);
2982
+ useEffect10(() => {
2858
2983
  if (!visible) return;
2859
2984
  const frame = requestAnimationFrame(() => searchInputRef.current?.focus());
2860
2985
  return () => cancelAnimationFrame(frame);
2861
2986
  }, [visible]);
2862
- useEffect8(() => {
2987
+ useEffect10(() => {
2863
2988
  if (!visible) return;
2864
2989
  const handler = (e) => {
2865
2990
  if (e.key === "Escape") {
@@ -2870,7 +2995,7 @@ function IconSidebar() {
2870
2995
  document.addEventListener("keydown", handler, true);
2871
2996
  return () => document.removeEventListener("keydown", handler, true);
2872
2997
  }, [visible, setActiveTool]);
2873
- useEffect8(() => {
2998
+ useEffect10(() => {
2874
2999
  if (!visible) return;
2875
3000
  const svgEl = document.getElementById("freehand-canvas");
2876
3001
  if (!svgEl) return;
@@ -2878,7 +3003,7 @@ function IconSidebar() {
2878
3003
  svgEl.addEventListener("mousedown", handleCanvasClick);
2879
3004
  return () => svgEl.removeEventListener("mousedown", handleCanvasClick);
2880
3005
  }, [visible, setActiveTool]);
2881
- const fetchIcons = useCallback9(async (searchQuery, cat) => {
3006
+ const fetchIcons = useCallback10(async (searchQuery, cat) => {
2882
3007
  const requestSequence = ++requestSequenceRef.current;
2883
3008
  const params = new URLSearchParams();
2884
3009
  if (searchQuery) params.set("q", searchQuery);
@@ -2904,7 +3029,7 @@ function IconSidebar() {
2904
3029
  }
2905
3030
  if (requestSequence === requestSequenceRef.current) setLoading(false);
2906
3031
  }, []);
2907
- useEffect8(() => {
3032
+ useEffect10(() => {
2908
3033
  if (!visible) return;
2909
3034
  if (debounceRef.current) clearTimeout(debounceRef.current);
2910
3035
  debounceRef.current = setTimeout(() => {
@@ -2912,7 +3037,7 @@ function IconSidebar() {
2912
3037
  }, query ? 80 : 0);
2913
3038
  return () => clearTimeout(debounceRef.current);
2914
3039
  }, [query, visible, category, fetchIcons]);
2915
- const handleIconClick = useCallback9((icon) => {
3040
+ const handleIconClick = useCallback10((icon) => {
2916
3041
  if (typeof window === "undefined") return;
2917
3042
  const place = (svgContent) => {
2918
3043
  if (window.prepareIconPlacement) {
@@ -2928,27 +3053,27 @@ function IconSidebar() {
2928
3053
  });
2929
3054
  }
2930
3055
  }, []);
2931
- return /* @__PURE__ */ jsxs14(
3056
+ return /* @__PURE__ */ jsxs15(
2932
3057
  "div",
2933
3058
  {
2934
3059
  className: `absolute top-[60px] right-2 bottom-[112px] w-[300px] bg-surface border border-border-light rounded-2xl z-[999] font-[lixFont] flex flex-col transition-transform duration-200 ${visible ? "translate-x-0" : "translate-x-full"}`,
2935
3060
  children: [
2936
- /* @__PURE__ */ jsxs14("div", { className: "px-3.5 pt-3.5 pb-2 shrink-0", children: [
2937
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between mb-2.5", children: [
2938
- /* @__PURE__ */ jsx14("h3", { className: "text-text-primary text-sm font-medium", children: "Icons" }),
2939
- /* @__PURE__ */ jsx14(
3061
+ /* @__PURE__ */ jsxs15("div", { className: "px-3.5 pt-3.5 pb-2 shrink-0", children: [
3062
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between mb-2.5", children: [
3063
+ /* @__PURE__ */ jsx15("h3", { className: "text-text-primary text-sm font-medium", children: "Icons" }),
3064
+ /* @__PURE__ */ jsx15(
2940
3065
  "button",
2941
3066
  {
2942
3067
  onClick: () => setActiveTool(TOOLS.SELECT),
2943
3068
  className: "w-6 h-6 flex items-center justify-center rounded-md text-text-muted hover:text-text-primary hover:bg-surface-hover transition-colors duration-100 cursor-pointer",
2944
3069
  title: "Close (Esc)",
2945
- children: /* @__PURE__ */ jsx14("i", { className: "bx bx-x text-lg" })
3070
+ children: /* @__PURE__ */ jsx15("i", { className: "bx bx-x text-lg" })
2946
3071
  }
2947
3072
  )
2948
3073
  ] }),
2949
- /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2 bg-surface-hover border border-border-light rounded-lg px-2.5 py-2", children: [
2950
- /* @__PURE__ */ jsx14("i", { className: "bx bxs-search text-text-muted text-sm" }),
2951
- /* @__PURE__ */ jsx14(
3074
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2 bg-surface-hover border border-border-light rounded-lg px-2.5 py-2", children: [
3075
+ /* @__PURE__ */ jsx15("i", { className: "bx bxs-search text-text-muted text-sm" }),
3076
+ /* @__PURE__ */ jsx15(
2952
3077
  "input",
2953
3078
  {
2954
3079
  ref: searchInputRef,
@@ -2961,25 +3086,25 @@ function IconSidebar() {
2961
3086
  spellCheck: false
2962
3087
  }
2963
3088
  ),
2964
- query && /* @__PURE__ */ jsx14(
3089
+ query && /* @__PURE__ */ jsx15(
2965
3090
  "button",
2966
3091
  {
2967
3092
  onClick: () => setQuery(""),
2968
3093
  className: "text-text-dim hover:text-text-secondary cursor-pointer",
2969
3094
  title: "Clear search",
2970
3095
  "aria-label": "Clear icon search",
2971
- children: /* @__PURE__ */ jsx14("i", { className: "bx bxs-x-circle text-sm" })
3096
+ children: /* @__PURE__ */ jsx15("i", { className: "bx bxs-x-circle text-sm" })
2972
3097
  }
2973
3098
  )
2974
3099
  ] })
2975
3100
  ] }),
2976
- /* @__PURE__ */ jsx14(
3101
+ /* @__PURE__ */ jsx15(
2977
3102
  "div",
2978
3103
  {
2979
3104
  className: "grid grid-cols-4 gap-1.5 px-3.5 pb-3 shrink-0",
2980
3105
  role: "group",
2981
3106
  "aria-label": "Filter icons by category",
2982
- children: CATEGORIES.map((cat) => /* @__PURE__ */ jsxs14(
3107
+ children: CATEGORIES.map((cat) => /* @__PURE__ */ jsxs15(
2983
3108
  "button",
2984
3109
  {
2985
3110
  onClick: () => setCategory(cat.value),
@@ -2987,19 +3112,19 @@ function IconSidebar() {
2987
3112
  title: `Show ${cat.label.toLowerCase()} icons`,
2988
3113
  className: `h-8 min-w-0 flex items-center justify-center gap-1 rounded-lg border px-1.5 text-[10.5px] whitespace-nowrap transition-all duration-150 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-blue/50 ${category === cat.value ? "border-accent-blue/50 bg-accent-blue/20 text-accent-blue shadow-sm" : "border-border-light bg-surface/40 text-text-muted hover:border-accent-blue/30 hover:bg-surface-hover hover:text-text-primary"}`,
2989
3114
  children: [
2990
- /* @__PURE__ */ jsx14("i", { className: `bx ${cat.icon} shrink-0 text-xs` }),
2991
- /* @__PURE__ */ jsx14("span", { className: "min-w-0 truncate", children: cat.label })
3115
+ /* @__PURE__ */ jsx15("i", { className: `bx ${cat.icon} shrink-0 text-xs` }),
3116
+ /* @__PURE__ */ jsx15("span", { className: "min-w-0 truncate", children: cat.label })
2992
3117
  ]
2993
3118
  },
2994
3119
  cat.value || "all"
2995
3120
  ))
2996
3121
  }
2997
3122
  ),
2998
- /* @__PURE__ */ jsx14("div", { className: "h-px bg-surface-hover mx-3.5 shrink-0" }),
2999
- /* @__PURE__ */ jsx14("div", { className: "flex-1 overflow-y-auto no-scrollbar px-3 py-2.5", id: "iconsContainer", children: loading ? /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-center py-12 text-text-muted text-sm", children: [
3000
- /* @__PURE__ */ jsx14("i", { className: "bx bxs-hourglass bx-spin text-lg mr-2" }),
3123
+ /* @__PURE__ */ jsx15("div", { className: "h-px bg-surface-hover mx-3.5 shrink-0" }),
3124
+ /* @__PURE__ */ jsx15("div", { className: "flex-1 overflow-y-auto no-scrollbar px-3 py-2.5", id: "iconsContainer", children: loading ? /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-center py-12 text-text-muted text-sm", children: [
3125
+ /* @__PURE__ */ jsx15("i", { className: "bx bxs-hourglass bx-spin text-lg mr-2" }),
3001
3126
  "Loading..."
3002
- ] }) : icons.length === 0 ? /* @__PURE__ */ jsx14("div", { className: "flex items-center justify-center py-12 text-text-muted text-sm", children: "No icons found" }) : /* @__PURE__ */ jsx14("div", { style: { display: "grid", gridTemplateColumns: "repeat(6, minmax(0, 1fr))", gap: "2px" }, children: icons.map((icon, i) => /* @__PURE__ */ jsx14(
3127
+ ] }) : icons.length === 0 ? /* @__PURE__ */ jsx15("div", { className: "flex items-center justify-center py-12 text-text-muted text-sm", children: "No icons found" }) : /* @__PURE__ */ jsx15("div", { style: { display: "grid", gridTemplateColumns: "repeat(6, minmax(0, 1fr))", gap: "2px" }, children: icons.map((icon, i) => /* @__PURE__ */ jsx15(
3003
3128
  IconCell,
3004
3129
  {
3005
3130
  icon,
@@ -3013,21 +3138,21 @@ function IconSidebar() {
3013
3138
  }
3014
3139
 
3015
3140
  // src/react/components/sidebars/ImageSidebar.jsx
3016
- import { useCallback as useCallback10 } from "react";
3017
- import { Fragment as Fragment8, jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
3141
+ import { useCallback as useCallback11 } from "react";
3142
+ import { Fragment as Fragment8, jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
3018
3143
  function ImageSidebar() {
3019
3144
  const { t } = useTranslation();
3020
3145
  const selectedShapeSidebar = useSketchStore_default((s) => s.selectedShapeSidebar);
3021
3146
  const toggleImageGenerateModal = useUIStore_default((s) => s.toggleImageGenerateModal);
3022
3147
  const toggleAIModal = useUIStore_default((s) => s.toggleAIModal);
3023
3148
  const isGraph = typeof window !== "undefined" && window.currentShape?._frameType === "graph";
3024
- const handleEditGraph = useCallback10(() => {
3149
+ const handleEditGraph = useCallback11(() => {
3025
3150
  const shape = window.currentShape;
3026
3151
  if (!shape || shape._frameType !== "graph") return;
3027
3152
  window.__aiEditTargetFrame = shape;
3028
3153
  toggleAIModal();
3029
3154
  }, [toggleAIModal]);
3030
- const handleEditWithAI = useCallback10(() => {
3155
+ const handleEditWithAI = useCallback11(() => {
3031
3156
  const shape = window.currentShape;
3032
3157
  if (!shape || shape.shapeName !== "image") return;
3033
3158
  const el = shape.element;
@@ -3037,62 +3162,62 @@ function ImageSidebar() {
3037
3162
  window.__editImageRef = { imageUrl: href, width: w, height: h, shape };
3038
3163
  toggleImageGenerateModal();
3039
3164
  }, [toggleImageGenerateModal]);
3040
- const handleReplace = useCallback10(() => {
3165
+ const handleReplace = useCallback11(() => {
3041
3166
  if (window.openImageFilePicker) {
3042
3167
  window.__replaceImageShape = window.currentShape;
3043
3168
  window.openImageFilePicker();
3044
3169
  }
3045
3170
  }, []);
3046
- return /* @__PURE__ */ jsxs15(ShapeSidebar, { visible: selectedShapeSidebar === "image", children: [
3047
- isGraph && /* @__PURE__ */ jsxs15(Fragment8, { children: [
3048
- /* @__PURE__ */ jsxs15(
3171
+ return /* @__PURE__ */ jsxs16(ShapeSidebar, { visible: selectedShapeSidebar === "image", children: [
3172
+ isGraph && /* @__PURE__ */ jsxs16(Fragment8, { children: [
3173
+ /* @__PURE__ */ jsxs16(
3049
3174
  "button",
3050
3175
  {
3051
3176
  onClick: handleEditGraph,
3052
3177
  title: "Edit graph",
3053
3178
  className: "h-9 flex cursor-pointer items-center gap-1.5 px-3 rounded-lg text-text-muted hover:text-accent hover:bg-accent/10 transition-all duration-100",
3054
3179
  children: [
3055
- /* @__PURE__ */ jsx15("i", { className: "bx bx-line-chart text-base" }),
3056
- /* @__PURE__ */ jsx15("span", { className: "text-xs", children: "Edit graph" })
3180
+ /* @__PURE__ */ jsx16("i", { className: "bx bx-line-chart text-base" }),
3181
+ /* @__PURE__ */ jsx16("span", { className: "text-xs", children: "Edit graph" })
3057
3182
  ]
3058
3183
  }
3059
3184
  ),
3060
- /* @__PURE__ */ jsx15(Divider, {})
3185
+ /* @__PURE__ */ jsx16(Divider, {})
3061
3186
  ] }),
3062
- !isGraph && /* @__PURE__ */ jsxs15(Fragment8, { children: [
3063
- /* @__PURE__ */ jsxs15(
3187
+ !isGraph && /* @__PURE__ */ jsxs16(Fragment8, { children: [
3188
+ /* @__PURE__ */ jsxs16(
3064
3189
  "button",
3065
3190
  {
3066
3191
  onClick: handleEditWithAI,
3067
3192
  title: "Edit with AI",
3068
3193
  className: "h-9 flex items-center gap-1.5 px-3 rounded-lg text-text-muted hover:text-purple-400 hover:bg-purple-500/10 transition-all duration-100",
3069
3194
  children: [
3070
- /* @__PURE__ */ jsx15("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", stroke: "none", children: /* @__PURE__ */ jsx15("path", { d: "M12 2l2.4 7.2L22 12l-7.6 2.8L12 22l-2.4-7.2L2 12l7.6-2.8L12 2z" }) }),
3071
- /* @__PURE__ */ jsx15("span", { className: "text-xs", children: "AI Edit" })
3195
+ /* @__PURE__ */ jsx16("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", stroke: "none", children: /* @__PURE__ */ jsx16("path", { d: "M12 2l2.4 7.2L22 12l-7.6 2.8L12 22l-2.4-7.2L2 12l7.6-2.8L12 2z" }) }),
3196
+ /* @__PURE__ */ jsx16("span", { className: "text-xs", children: "AI Edit" })
3072
3197
  ]
3073
3198
  }
3074
3199
  ),
3075
- /* @__PURE__ */ jsx15(Divider, {}),
3076
- /* @__PURE__ */ jsxs15(
3200
+ /* @__PURE__ */ jsx16(Divider, {}),
3201
+ /* @__PURE__ */ jsxs16(
3077
3202
  "button",
3078
3203
  {
3079
3204
  onClick: handleReplace,
3080
3205
  title: "Replace image",
3081
3206
  className: "h-9 flex items-center gap-1.5 px-3 rounded-lg text-text-muted hover:text-white hover:bg-white/[0.06] transition-all duration-100",
3082
3207
  children: [
3083
- /* @__PURE__ */ jsx15("i", { className: "bx bx-upload text-base" }),
3084
- /* @__PURE__ */ jsx15("span", { className: "text-xs", children: "Replace" })
3208
+ /* @__PURE__ */ jsx16("i", { className: "bx bx-upload text-base" }),
3209
+ /* @__PURE__ */ jsx16("span", { className: "text-xs", children: "Replace" })
3085
3210
  ]
3086
3211
  }
3087
3212
  ),
3088
- /* @__PURE__ */ jsx15(Divider, {})
3213
+ /* @__PURE__ */ jsx16(Divider, {})
3089
3214
  ] }),
3090
- /* @__PURE__ */ jsx15(LayerControls, {})
3215
+ /* @__PURE__ */ jsx16(LayerControls, {})
3091
3216
  ] });
3092
3217
  }
3093
3218
 
3094
3219
  // src/react/components/canvas/MultiSelectActions.jsx
3095
- import { useState as useState13, useEffect as useEffect9 } from "react";
3220
+ import { useState as useState15, useEffect as useEffect11 } from "react";
3096
3221
 
3097
3222
  // src/react/utils/toast.js
3098
3223
  function showToast(message, options = {}) {
@@ -3118,12 +3243,12 @@ function showToast(message, options = {}) {
3118
3243
  }
3119
3244
 
3120
3245
  // src/react/components/canvas/MultiSelectActions.jsx
3121
- import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
3246
+ import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
3122
3247
  function MultiSelectActions() {
3123
- const [count, setCount] = useState13(0);
3124
- const [groupState, setGroupState] = useState13("none");
3125
- const [frameEligible, setFrameEligible] = useState13(false);
3126
- useEffect9(() => {
3248
+ const [count, setCount] = useState15(0);
3249
+ const [groupState, setGroupState] = useState15("none");
3250
+ const [frameEligible, setFrameEligible] = useState15(false);
3251
+ useEffect11(() => {
3127
3252
  const interval = setInterval(() => {
3128
3253
  const ms = window.multiSelection;
3129
3254
  const sel = ms?.selectedShapes;
@@ -3187,44 +3312,44 @@ function MultiSelectActions() {
3187
3312
  showToast(`Ungrouped ${cleared} shapes`, { tone: "success" });
3188
3313
  };
3189
3314
  const grouped = groupState === "all";
3190
- return /* @__PURE__ */ jsx16("div", { className: "absolute top-14 left-1/2 -translate-x-1/2 z-[1000] font-[lixFont]", children: /* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 bg-surface/90 backdrop-blur-lg border border-border-light rounded-xl px-3 py-1.5 shadow-lg", children: [
3191
- /* @__PURE__ */ jsxs16("span", { className: "text-text-muted text-xs", children: [
3315
+ return /* @__PURE__ */ jsx17("div", { className: "absolute top-14 left-1/2 -translate-x-1/2 z-[1000] font-[lixFont]", children: /* @__PURE__ */ jsxs17("div", { className: "flex items-center gap-2 bg-surface/90 backdrop-blur-lg border border-border-light rounded-xl px-3 py-1.5 shadow-lg", children: [
3316
+ /* @__PURE__ */ jsxs17("span", { className: "text-text-muted text-xs", children: [
3192
3317
  count,
3193
3318
  " selected",
3194
- grouped && /* @__PURE__ */ jsx16("span", { className: "ml-1 text-accent-blue", children: "\xB7 grouped" })
3319
+ grouped && /* @__PURE__ */ jsx17("span", { className: "ml-1 text-accent-blue", children: "\xB7 grouped" })
3195
3320
  ] }),
3196
- /* @__PURE__ */ jsx16("div", { className: "w-px h-4 bg-border-light" }),
3197
- !grouped && frameEligible && /* @__PURE__ */ jsxs16(
3321
+ /* @__PURE__ */ jsx17("div", { className: "w-px h-4 bg-border-light" }),
3322
+ !grouped && frameEligible && /* @__PURE__ */ jsxs17(
3198
3323
  "button",
3199
3324
  {
3200
3325
  onClick: handleFrame,
3201
3326
  className: "flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs text-accent-blue hover:bg-accent-blue/10 transition-all duration-150",
3202
3327
  title: "Wrap selection in a frame",
3203
3328
  children: [
3204
- /* @__PURE__ */ jsx16("i", { className: "bx bx-crop text-sm" }),
3329
+ /* @__PURE__ */ jsx17("i", { className: "bx bx-crop text-sm" }),
3205
3330
  "Frame it"
3206
3331
  ]
3207
3332
  }
3208
3333
  ),
3209
- grouped ? /* @__PURE__ */ jsxs16(
3334
+ grouped ? /* @__PURE__ */ jsxs17(
3210
3335
  "button",
3211
3336
  {
3212
3337
  onClick: handleUngroup,
3213
3338
  className: "flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs text-yellow-400 hover:bg-yellow-500/10 transition-all duration-150",
3214
3339
  title: "Ungroup (Ctrl+Shift+G)",
3215
3340
  children: [
3216
- /* @__PURE__ */ jsx16("i", { className: "bx bx-unlink text-sm" }),
3341
+ /* @__PURE__ */ jsx17("i", { className: "bx bx-unlink text-sm" }),
3217
3342
  "Ungroup"
3218
3343
  ]
3219
3344
  }
3220
- ) : /* @__PURE__ */ jsxs16(
3345
+ ) : /* @__PURE__ */ jsxs17(
3221
3346
  "button",
3222
3347
  {
3223
3348
  onClick: handleGroup,
3224
3349
  className: "flex items-center gap-1.5 px-2.5 py-1 rounded-lg text-xs text-text-secondary hover:bg-surface-hover transition-all duration-150",
3225
3350
  title: "Group (Ctrl+G)",
3226
3351
  children: [
3227
- /* @__PURE__ */ jsx16("i", { className: "bx bx-link text-sm" }),
3352
+ /* @__PURE__ */ jsx17("i", { className: "bx bx-link text-sm" }),
3228
3353
  "Group"
3229
3354
  ]
3230
3355
  }
@@ -3233,8 +3358,8 @@ function MultiSelectActions() {
3233
3358
  }
3234
3359
 
3235
3360
  // src/react/components/canvas/ContextMenu.jsx
3236
- import { useState as useState14, useEffect as useEffect10, useCallback as useCallback11, useRef as useRef6 } from "react";
3237
- import { Fragment as Fragment9, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
3361
+ import { useState as useState16, useEffect as useEffect12, useCallback as useCallback12, useRef as useRef7 } from "react";
3362
+ import { Fragment as Fragment9, jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
3238
3363
  function getCleanSVG() {
3239
3364
  const svgEl = window.svg;
3240
3365
  if (!svgEl) return null;
@@ -3287,53 +3412,53 @@ function getShapeAtPoint(x, y) {
3287
3412
  return null;
3288
3413
  }
3289
3414
  function MenuItem({ label, shortcut, onClick, disabled, danger }) {
3290
- return /* @__PURE__ */ jsxs17(
3415
+ return /* @__PURE__ */ jsxs18(
3291
3416
  "button",
3292
3417
  {
3293
3418
  onClick,
3294
3419
  disabled,
3295
3420
  className: `w-full flex items-center justify-between px-3 py-1.5 text-xs transition-colors duration-100 ${disabled ? "text-text-dim cursor-default" : danger ? "text-red-400 hover:bg-red-500/15 cursor-pointer" : "text-text-secondary hover:bg-surface-hover cursor-pointer"}`,
3296
3421
  children: [
3297
- /* @__PURE__ */ jsx17("span", { children: label }),
3298
- shortcut && /* @__PURE__ */ jsx17("span", { className: "text-text-dim text-[10px] ml-6", children: shortcut })
3422
+ /* @__PURE__ */ jsx18("span", { children: label }),
3423
+ shortcut && /* @__PURE__ */ jsx18("span", { className: "text-text-dim text-[10px] ml-6", children: shortcut })
3299
3424
  ]
3300
3425
  }
3301
3426
  );
3302
3427
  }
3303
3428
  function CheckMenuItem({ label, shortcut, checked, onClick }) {
3304
- return /* @__PURE__ */ jsxs17(
3429
+ return /* @__PURE__ */ jsxs18(
3305
3430
  "button",
3306
3431
  {
3307
3432
  onClick,
3308
3433
  className: "w-full flex items-center justify-between px-3 py-1.5 text-xs text-text-secondary hover:bg-surface-hover cursor-pointer transition-colors duration-100",
3309
3434
  children: [
3310
- /* @__PURE__ */ jsxs17("span", { className: "flex items-center gap-2", children: [
3311
- checked && /* @__PURE__ */ jsx17("i", { className: "bx bx-check text-sm text-accent-blue -ml-0.5" }),
3312
- !checked && /* @__PURE__ */ jsx17("span", { className: "w-[14px]" }),
3435
+ /* @__PURE__ */ jsxs18("span", { className: "flex items-center gap-2", children: [
3436
+ checked && /* @__PURE__ */ jsx18("i", { className: "bx bx-check text-sm text-accent-blue -ml-0.5" }),
3437
+ !checked && /* @__PURE__ */ jsx18("span", { className: "w-[14px]" }),
3313
3438
  label
3314
3439
  ] }),
3315
- shortcut && /* @__PURE__ */ jsx17("span", { className: "text-text-dim text-[10px] ml-6", children: shortcut })
3440
+ shortcut && /* @__PURE__ */ jsx18("span", { className: "text-text-dim text-[10px] ml-6", children: shortcut })
3316
3441
  ]
3317
3442
  }
3318
3443
  );
3319
3444
  }
3320
3445
  function Separator() {
3321
- return /* @__PURE__ */ jsx17("hr", { className: "border-border-light my-1" });
3446
+ return /* @__PURE__ */ jsx18("hr", { className: "border-border-light my-1" });
3322
3447
  }
3323
3448
  function ContextMenu() {
3324
- const [visible, setVisible] = useState14(false);
3325
- const [position, setPosition] = useState14({ x: 0, y: 0 });
3326
- const [targetShape, setTargetShape] = useState14(null);
3327
- const menuRef = useRef6(null);
3449
+ const [visible, setVisible] = useState16(false);
3450
+ const [position, setPosition] = useState16({ x: 0, y: 0 });
3451
+ const [targetShape, setTargetShape] = useState16(null);
3452
+ const menuRef = useRef7(null);
3328
3453
  const gridEnabled = useSketchStore_default((s) => s.gridEnabled);
3329
3454
  const snapToObjects = useSketchStore_default((s) => s.snapToObjects);
3330
3455
  const zenMode = useSketchStore_default((s) => s.zenMode);
3331
3456
  const viewMode = useSketchStore_default((s) => s.viewMode);
3332
- const close = useCallback11(() => {
3457
+ const close = useCallback12(() => {
3333
3458
  setVisible(false);
3334
3459
  setTargetShape(null);
3335
3460
  }, []);
3336
- useEffect10(() => {
3461
+ useEffect12(() => {
3337
3462
  const handleContextMenu = (e) => {
3338
3463
  const svg = document.getElementById("freehand-canvas");
3339
3464
  if (!svg) return;
@@ -3358,7 +3483,7 @@ function ContextMenu() {
3358
3483
  document.removeEventListener("keydown", handleKeyDown);
3359
3484
  };
3360
3485
  }, [close]);
3361
- useEffect10(() => {
3486
+ useEffect12(() => {
3362
3487
  if (!visible || !menuRef.current) return;
3363
3488
  const rect = menuRef.current.getBoundingClientRect();
3364
3489
  const vw = window.innerWidth;
@@ -3570,7 +3695,7 @@ function ContextMenu() {
3570
3695
  close();
3571
3696
  };
3572
3697
  const isShape = !!targetShape;
3573
- return /* @__PURE__ */ jsx17(
3698
+ return /* @__PURE__ */ jsx18(
3574
3699
  "div",
3575
3700
  {
3576
3701
  ref: menuRef,
@@ -3579,49 +3704,49 @@ function ContextMenu() {
3579
3704
  onClick: (e) => e.stopPropagation(),
3580
3705
  children: isShape ? (
3581
3706
  /* ── Shape context menu ── */
3582
- /* @__PURE__ */ jsxs17(Fragment9, { children: [
3583
- /* @__PURE__ */ jsx17(MenuItem, { label: "Cut", shortcut: "Ctrl+X", onClick: handleCut }),
3584
- /* @__PURE__ */ jsx17(MenuItem, { label: "Copy", shortcut: "Ctrl+C", onClick: handleCopy }),
3585
- /* @__PURE__ */ jsx17(MenuItem, { label: "Paste", shortcut: "Ctrl+V", onClick: handlePaste }),
3586
- /* @__PURE__ */ jsx17(Separator, {}),
3587
- !fullyGrouped && /* @__PURE__ */ jsx17(MenuItem, { label: "Wrap selection in frame", onClick: handleWrapInFrame }),
3588
- canGroup && !fullyGrouped && /* @__PURE__ */ jsx17(MenuItem, { label: "Group", shortcut: "Ctrl+G", onClick: handleGroup }),
3589
- canUngroup && /* @__PURE__ */ jsx17(MenuItem, { label: "Ungroup", shortcut: "Ctrl+Shift+G", onClick: handleUngroup }),
3590
- /* @__PURE__ */ jsx17(Separator, {}),
3591
- /* @__PURE__ */ jsx17(MenuItem, { label: "Copy to clipboard as PNG", shortcut: "Shift+Alt+C", onClick: handleCopyPNG }),
3592
- /* @__PURE__ */ jsx17(MenuItem, { label: "Copy to clipboard as SVG", onClick: handleCopySVG }),
3593
- /* @__PURE__ */ jsx17(Separator, {}),
3594
- /* @__PURE__ */ jsx17(MenuItem, { label: "Send backward", shortcut: "Ctrl+[", onClick: () => handleLayerAction("sendBackward") }),
3595
- /* @__PURE__ */ jsx17(MenuItem, { label: "Bring forward", shortcut: "Ctrl+]", onClick: () => handleLayerAction("bringForward") }),
3596
- /* @__PURE__ */ jsx17(MenuItem, { label: "Send to back", shortcut: "Ctrl+Shift+[", onClick: () => handleLayerAction("sendToBack") }),
3597
- /* @__PURE__ */ jsx17(MenuItem, { label: "Bring to front", shortcut: "Ctrl+Shift+]", onClick: () => handleLayerAction("bringToFront") }),
3598
- /* @__PURE__ */ jsx17(Separator, {}),
3599
- /* @__PURE__ */ jsx17(MenuItem, { label: "Flip horizontal", shortcut: "Shift+H", onClick: () => handleFlip("h") }),
3600
- /* @__PURE__ */ jsx17(MenuItem, { label: "Flip vertical", shortcut: "Shift+V", onClick: () => handleFlip("v") }),
3601
- /* @__PURE__ */ jsx17(Separator, {}),
3602
- /* @__PURE__ */ jsx17(MenuItem, { label: "Duplicate", shortcut: "Ctrl+D", onClick: handleDuplicate }),
3603
- /* @__PURE__ */ jsx17(MenuItem, { label: "Delete", danger: true, onClick: handleDeleteShape })
3707
+ /* @__PURE__ */ jsxs18(Fragment9, { children: [
3708
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Cut", shortcut: "Ctrl+X", onClick: handleCut }),
3709
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Copy", shortcut: "Ctrl+C", onClick: handleCopy }),
3710
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Paste", shortcut: "Ctrl+V", onClick: handlePaste }),
3711
+ /* @__PURE__ */ jsx18(Separator, {}),
3712
+ !fullyGrouped && /* @__PURE__ */ jsx18(MenuItem, { label: "Wrap selection in frame", onClick: handleWrapInFrame }),
3713
+ canGroup && !fullyGrouped && /* @__PURE__ */ jsx18(MenuItem, { label: "Group", shortcut: "Ctrl+G", onClick: handleGroup }),
3714
+ canUngroup && /* @__PURE__ */ jsx18(MenuItem, { label: "Ungroup", shortcut: "Ctrl+Shift+G", onClick: handleUngroup }),
3715
+ /* @__PURE__ */ jsx18(Separator, {}),
3716
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Copy to clipboard as PNG", shortcut: "Shift+Alt+C", onClick: handleCopyPNG }),
3717
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Copy to clipboard as SVG", onClick: handleCopySVG }),
3718
+ /* @__PURE__ */ jsx18(Separator, {}),
3719
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Send backward", shortcut: "Ctrl+[", onClick: () => handleLayerAction("sendBackward") }),
3720
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Bring forward", shortcut: "Ctrl+]", onClick: () => handleLayerAction("bringForward") }),
3721
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Send to back", shortcut: "Ctrl+Shift+[", onClick: () => handleLayerAction("sendToBack") }),
3722
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Bring to front", shortcut: "Ctrl+Shift+]", onClick: () => handleLayerAction("bringToFront") }),
3723
+ /* @__PURE__ */ jsx18(Separator, {}),
3724
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Flip horizontal", shortcut: "Shift+H", onClick: () => handleFlip("h") }),
3725
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Flip vertical", shortcut: "Shift+V", onClick: () => handleFlip("v") }),
3726
+ /* @__PURE__ */ jsx18(Separator, {}),
3727
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Duplicate", shortcut: "Ctrl+D", onClick: handleDuplicate }),
3728
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Delete", danger: true, onClick: handleDeleteShape })
3604
3729
  ] })
3605
3730
  ) : (
3606
3731
  /* ── Canvas context menu ── */
3607
- /* @__PURE__ */ jsxs17(Fragment9, { children: [
3608
- /* @__PURE__ */ jsx17(MenuItem, { label: "Paste", shortcut: "Ctrl+V", onClick: handlePaste }),
3609
- /* @__PURE__ */ jsx17(MenuItem, { label: "Copy to clipboard as PNG", shortcut: "Shift+Alt+C", onClick: handleCopyPNG }),
3610
- /* @__PURE__ */ jsx17(MenuItem, { label: "Copy to clipboard as SVG", onClick: handleCopySVG }),
3611
- /* @__PURE__ */ jsx17(Separator, {}),
3612
- /* @__PURE__ */ jsx17(MenuItem, { label: "Select all", shortcut: "Ctrl+A", onClick: handleSelectAll }),
3613
- /* @__PURE__ */ jsx17(Separator, {}),
3614
- /* @__PURE__ */ jsx17(CheckMenuItem, { label: "Toggle grid", shortcut: "Ctrl+'", checked: gridEnabled, onClick: handleToggleGrid }),
3615
- /* @__PURE__ */ jsx17(CheckMenuItem, { label: "Snap to objects", shortcut: "Alt+S", checked: snapToObjects, onClick: handleToggleSnap }),
3616
- /* @__PURE__ */ jsx17(Separator, {}),
3617
- /* @__PURE__ */ jsx17(MenuItem, { label: "Find on canvas", shortcut: "Ctrl+F", onClick: () => {
3732
+ /* @__PURE__ */ jsxs18(Fragment9, { children: [
3733
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Paste", shortcut: "Ctrl+V", onClick: handlePaste }),
3734
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Copy to clipboard as PNG", shortcut: "Shift+Alt+C", onClick: handleCopyPNG }),
3735
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Copy to clipboard as SVG", onClick: handleCopySVG }),
3736
+ /* @__PURE__ */ jsx18(Separator, {}),
3737
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Select all", shortcut: "Ctrl+A", onClick: handleSelectAll }),
3738
+ /* @__PURE__ */ jsx18(Separator, {}),
3739
+ /* @__PURE__ */ jsx18(CheckMenuItem, { label: "Toggle grid", shortcut: "Ctrl+'", checked: gridEnabled, onClick: handleToggleGrid }),
3740
+ /* @__PURE__ */ jsx18(CheckMenuItem, { label: "Snap to objects", shortcut: "Alt+S", checked: snapToObjects, onClick: handleToggleSnap }),
3741
+ /* @__PURE__ */ jsx18(Separator, {}),
3742
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Find on canvas", shortcut: "Ctrl+F", onClick: () => {
3618
3743
  useUIStore_default.getState().toggleFindBar();
3619
3744
  close();
3620
3745
  } }),
3621
- /* @__PURE__ */ jsx17(MenuItem, { label: "Zen mode", shortcut: "Alt+Z", onClick: handleZenMode }),
3622
- /* @__PURE__ */ jsx17(MenuItem, { label: "View mode", shortcut: "Alt+R", onClick: handleViewMode }),
3623
- /* @__PURE__ */ jsx17(Separator, {}),
3624
- /* @__PURE__ */ jsx17(MenuItem, { label: "Reset canvas", danger: true, onClick: () => {
3746
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Zen mode", shortcut: "Alt+Z", onClick: handleZenMode }),
3747
+ /* @__PURE__ */ jsx18(MenuItem, { label: "View mode", shortcut: "Alt+R", onClick: handleViewMode }),
3748
+ /* @__PURE__ */ jsx18(Separator, {}),
3749
+ /* @__PURE__ */ jsx18(MenuItem, { label: "Reset canvas", danger: true, onClick: () => {
3625
3750
  const serializer = window.__sceneSerializer;
3626
3751
  if (serializer?.resetCanvas) serializer.resetCanvas();
3627
3752
  close();
@@ -3633,17 +3758,17 @@ function ContextMenu() {
3633
3758
  }
3634
3759
 
3635
3760
  // src/react/components/canvas/FindBar.jsx
3636
- import { useState as useState15, useEffect as useEffect11, useRef as useRef7, useCallback as useCallback12 } from "react";
3637
- import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
3761
+ import { useState as useState17, useEffect as useEffect13, useRef as useRef8, useCallback as useCallback13 } from "react";
3762
+ import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
3638
3763
  function FindBar() {
3639
3764
  const open = useUIStore_default((s) => s.findBarOpen);
3640
3765
  const closeFindBar = useUIStore_default((s) => s.closeFindBar);
3641
- const [query, setQuery] = useState15("");
3642
- const [results, setResults] = useState15([]);
3643
- const [activeIndex, setActiveIndex] = useState15(-1);
3644
- const inputRef = useRef7(null);
3645
- const highlightRef = useRef7(null);
3646
- useEffect11(() => {
3766
+ const [query, setQuery] = useState17("");
3767
+ const [results, setResults] = useState17([]);
3768
+ const [activeIndex, setActiveIndex] = useState17(-1);
3769
+ const inputRef = useRef8(null);
3770
+ const highlightRef = useRef8(null);
3771
+ useEffect13(() => {
3647
3772
  if (open) {
3648
3773
  setQuery("");
3649
3774
  setResults([]);
@@ -3653,13 +3778,13 @@ function FindBar() {
3653
3778
  removeHighlight();
3654
3779
  }
3655
3780
  }, [open]);
3656
- const removeHighlight = useCallback12(() => {
3781
+ const removeHighlight = useCallback13(() => {
3657
3782
  if (highlightRef.current && highlightRef.current.parentNode) {
3658
3783
  highlightRef.current.parentNode.removeChild(highlightRef.current);
3659
3784
  highlightRef.current = null;
3660
3785
  }
3661
3786
  }, []);
3662
- const highlightShape = useCallback12((result) => {
3787
+ const highlightShape = useCallback13((result) => {
3663
3788
  removeHighlight();
3664
3789
  if (!result || !window.svg) return;
3665
3790
  const shape = result.shape;
@@ -3694,7 +3819,7 @@ function FindBar() {
3694
3819
  window.currentViewBox.y = newY;
3695
3820
  }
3696
3821
  }, [removeHighlight]);
3697
- const doSearch = useCallback12((q) => {
3822
+ const doSearch = useCallback13((q) => {
3698
3823
  const finder = window.__sceneSerializer?.findText;
3699
3824
  if (!finder || !q.trim()) {
3700
3825
  setResults([]);
@@ -3712,7 +3837,7 @@ function FindBar() {
3712
3837
  removeHighlight();
3713
3838
  }
3714
3839
  }, [highlightShape, removeHighlight]);
3715
- const goToResult = useCallback12((idx) => {
3840
+ const goToResult = useCallback13((idx) => {
3716
3841
  if (idx < 0 || idx >= results.length) return;
3717
3842
  setActiveIndex(idx);
3718
3843
  highlightShape(results[idx]);
@@ -3739,9 +3864,9 @@ function FindBar() {
3739
3864
  doSearch(q);
3740
3865
  };
3741
3866
  if (!open) return null;
3742
- return /* @__PURE__ */ jsx18("div", { className: "fixed top-14 right-4 z-[1000] font-[lixFont]", children: /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-2 bg-surface-card/95 backdrop-blur-lg border border-border-light rounded-xl px-3 py-2 shadow-xl min-w-[300px]", children: [
3743
- /* @__PURE__ */ jsx18("i", { className: "bx bx-search text-text-muted text-sm" }),
3744
- /* @__PURE__ */ jsx18(
3867
+ return /* @__PURE__ */ jsx19("div", { className: "fixed top-14 right-4 z-[1000] font-[lixFont]", children: /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-2 bg-surface-card/95 backdrop-blur-lg border border-border-light rounded-xl px-3 py-2 shadow-xl min-w-[300px]", children: [
3868
+ /* @__PURE__ */ jsx19("i", { className: "bx bx-search text-text-muted text-sm" }),
3869
+ /* @__PURE__ */ jsx19(
3745
3870
  "input",
3746
3871
  {
3747
3872
  ref: inputRef,
@@ -3753,68 +3878,68 @@ function FindBar() {
3753
3878
  className: "flex-1 bg-transparent text-text-primary text-xs outline-none placeholder:text-text-dim font-[lixFont]"
3754
3879
  }
3755
3880
  ),
3756
- results.length > 0 && /* @__PURE__ */ jsxs18("span", { className: "text-text-dim text-xs whitespace-nowrap", children: [
3881
+ results.length > 0 && /* @__PURE__ */ jsxs19("span", { className: "text-text-dim text-xs whitespace-nowrap", children: [
3757
3882
  activeIndex + 1,
3758
3883
  "/",
3759
3884
  results.length
3760
3885
  ] }),
3761
- query && results.length === 0 && /* @__PURE__ */ jsx18("span", { className: "text-red-400/70 text-xs whitespace-nowrap", children: "No results" }),
3762
- results.length > 1 && /* @__PURE__ */ jsxs18("div", { className: "flex items-center gap-0.5", children: [
3763
- /* @__PURE__ */ jsx18(
3886
+ query && results.length === 0 && /* @__PURE__ */ jsx19("span", { className: "text-red-400/70 text-xs whitespace-nowrap", children: "No results" }),
3887
+ results.length > 1 && /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-0.5", children: [
3888
+ /* @__PURE__ */ jsx19(
3764
3889
  "button",
3765
3890
  {
3766
3891
  onClick: () => goToResult((activeIndex - 1 + results.length) % results.length),
3767
3892
  className: "w-5 h-5 flex items-center justify-center rounded text-text-muted hover:text-white hover:bg-white/10 transition-colors",
3768
- children: /* @__PURE__ */ jsx18("i", { className: "bx bx-chevron-up text-sm" })
3893
+ children: /* @__PURE__ */ jsx19("i", { className: "bx bx-chevron-up text-sm" })
3769
3894
  }
3770
3895
  ),
3771
- /* @__PURE__ */ jsx18(
3896
+ /* @__PURE__ */ jsx19(
3772
3897
  "button",
3773
3898
  {
3774
3899
  onClick: () => goToResult((activeIndex + 1) % results.length),
3775
3900
  className: "w-5 h-5 flex items-center justify-center rounded text-text-muted hover:text-white hover:bg-white/10 transition-colors",
3776
- children: /* @__PURE__ */ jsx18("i", { className: "bx bx-chevron-down text-sm" })
3901
+ children: /* @__PURE__ */ jsx19("i", { className: "bx bx-chevron-down text-sm" })
3777
3902
  }
3778
3903
  )
3779
3904
  ] }),
3780
- /* @__PURE__ */ jsx18(
3905
+ /* @__PURE__ */ jsx19(
3781
3906
  "button",
3782
3907
  {
3783
3908
  onClick: closeFindBar,
3784
3909
  className: "w-5 h-5 flex items-center justify-center rounded text-text-muted hover:text-white hover:bg-white/10 transition-colors",
3785
- children: /* @__PURE__ */ jsx18("i", { className: "bx bx-x text-sm" })
3910
+ children: /* @__PURE__ */ jsx19("i", { className: "bx bx-x text-sm" })
3786
3911
  }
3787
3912
  )
3788
3913
  ] }) });
3789
3914
  }
3790
3915
 
3791
3916
  // src/react/components/canvas/ImageSourcePicker.jsx
3792
- import { useState as useState16, useEffect as useEffect12, useCallback as useCallback13, useRef as useRef8 } from "react";
3793
- import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
3917
+ import { useState as useState18, useEffect as useEffect14, useCallback as useCallback14, useRef as useRef9 } from "react";
3918
+ import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
3794
3919
  function ImageSourcePicker() {
3795
- const ref = useRef8(null);
3920
+ const ref = useRef9(null);
3796
3921
  const toggleImageGenerateModal = useUIStore_default((s) => s.toggleImageGenerateModal);
3797
3922
  const activeTool = useSketchStore_default((s) => s.activeTool);
3798
3923
  const setActiveTool = useSketchStore_default((s) => s.setActiveTool);
3799
3924
  const visible = activeTool === "image";
3800
- const handleGenerateAI = useCallback13(() => {
3925
+ const handleGenerateAI = useCallback14(() => {
3801
3926
  setActiveTool("select");
3802
3927
  toggleImageGenerateModal();
3803
3928
  }, [setActiveTool, toggleImageGenerateModal]);
3804
- const handleUpload = useCallback13(() => {
3929
+ const handleUpload = useCallback14(() => {
3805
3930
  setActiveTool("select");
3806
3931
  if (window.openImageFilePicker) {
3807
3932
  window.openImageFilePicker();
3808
3933
  }
3809
3934
  }, [setActiveTool]);
3810
- useEffect12(() => {
3935
+ useEffect14(() => {
3811
3936
  window.__showImageSourcePicker = () => {
3812
3937
  };
3813
3938
  return () => {
3814
3939
  delete window.__showImageSourcePicker;
3815
3940
  };
3816
3941
  }, []);
3817
- useEffect12(() => {
3942
+ useEffect14(() => {
3818
3943
  if (!visible) return;
3819
3944
  const handleClick = (e) => {
3820
3945
  if (ref.current && !ref.current.contains(e.target)) {
@@ -3857,44 +3982,44 @@ function ImageSourcePicker() {
3857
3982
  posY = rect.top - 10;
3858
3983
  }
3859
3984
  }
3860
- return /* @__PURE__ */ jsx19(
3985
+ return /* @__PURE__ */ jsx20(
3861
3986
  "div",
3862
3987
  {
3863
3988
  ref,
3864
3989
  className: "fixed z-[1100] font-[lixFont]",
3865
3990
  style: { left: posX, top: posY },
3866
- children: /* @__PURE__ */ jsxs19("div", { className: "bg-surface-card border border-border-light rounded-xl p-1.5 shadow-2xl shadow-black/40 flex flex-col gap-1 min-w-[200px]", children: [
3867
- /* @__PURE__ */ jsxs19(
3991
+ children: /* @__PURE__ */ jsxs20("div", { className: "bg-surface-card border border-border-light rounded-xl p-1.5 shadow-2xl shadow-black/40 flex flex-col gap-1 min-w-[200px]", children: [
3992
+ /* @__PURE__ */ jsxs20(
3868
3993
  "button",
3869
3994
  {
3870
3995
  onClick: handleGenerateAI,
3871
3996
  className: "flex items-center gap-3 px-3 py-2.5 rounded-lg text-text-muted hover:text-accent-blue hover:bg-surface-hover transition-all group",
3872
3997
  children: [
3873
- /* @__PURE__ */ jsx19("div", { className: "w-8 h-8 rounded-lg bg-accent-blue/10 flex items-center justify-center group-hover:bg-accent-blue/20 transition-all", children: /* @__PURE__ */ jsxs19("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-accent-blue", children: [
3874
- /* @__PURE__ */ jsx19("path", { d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z" }),
3875
- /* @__PURE__ */ jsx19("path", { d: "M18 14l1 3 3 1-3 1-1 3-1-3-3-1 3-1 1-3z" })
3998
+ /* @__PURE__ */ jsx20("div", { className: "w-8 h-8 rounded-lg bg-accent-blue/10 flex items-center justify-center group-hover:bg-accent-blue/20 transition-all", children: /* @__PURE__ */ jsxs20("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-accent-blue", children: [
3999
+ /* @__PURE__ */ jsx20("path", { d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z" }),
4000
+ /* @__PURE__ */ jsx20("path", { d: "M18 14l1 3 3 1-3 1-1 3-1-3-3-1 3-1 1-3z" })
3876
4001
  ] }) }),
3877
- /* @__PURE__ */ jsxs19("div", { className: "flex-1 text-left", children: [
3878
- /* @__PURE__ */ jsx19("div", { className: "text-sm font-medium", children: "Generate with AI" }),
3879
- /* @__PURE__ */ jsx19("div", { className: "text-[10px] text-text-dim", children: "10 generations \xB7 5 edits free" })
4002
+ /* @__PURE__ */ jsxs20("div", { className: "flex-1 text-left", children: [
4003
+ /* @__PURE__ */ jsx20("div", { className: "text-sm font-medium", children: "Generate with AI" }),
4004
+ /* @__PURE__ */ jsx20("div", { className: "text-[10px] text-text-dim", children: "10 generations \xB7 5 edits free" })
3880
4005
  ] }),
3881
- /* @__PURE__ */ jsx19("kbd", { className: "text-[10px] text-text-dim bg-surface-dark px-1.5 py-0.5 rounded", children: "G" })
4006
+ /* @__PURE__ */ jsx20("kbd", { className: "text-[10px] text-text-dim bg-surface-dark px-1.5 py-0.5 rounded", children: "G" })
3882
4007
  ]
3883
4008
  }
3884
4009
  ),
3885
- /* @__PURE__ */ jsx19("div", { className: "h-px bg-white/[0.06] mx-2" }),
3886
- /* @__PURE__ */ jsxs19(
4010
+ /* @__PURE__ */ jsx20("div", { className: "h-px bg-white/[0.06] mx-2" }),
4011
+ /* @__PURE__ */ jsxs20(
3887
4012
  "button",
3888
4013
  {
3889
4014
  onClick: handleUpload,
3890
4015
  className: "flex items-center gap-3 px-3 py-2.5 rounded-lg text-text-muted hover:text-text-primary hover:bg-surface-hover transition-all group",
3891
4016
  children: [
3892
- /* @__PURE__ */ jsx19("div", { className: "w-8 h-8 rounded-lg bg-surface-hover flex items-center justify-center group-hover:bg-surface-active transition-all", children: /* @__PURE__ */ jsx19("i", { className: "bx bx-upload text-lg" }) }),
3893
- /* @__PURE__ */ jsxs19("div", { className: "flex-1 text-left", children: [
3894
- /* @__PURE__ */ jsx19("div", { className: "text-sm font-medium", children: "Upload from device" }),
3895
- /* @__PURE__ */ jsx19("div", { className: "text-[10px] text-text-dim", children: "PNG, JPG, SVG, WebP" })
4017
+ /* @__PURE__ */ jsx20("div", { className: "w-8 h-8 rounded-lg bg-surface-hover flex items-center justify-center group-hover:bg-surface-active transition-all", children: /* @__PURE__ */ jsx20("i", { className: "bx bx-upload text-lg" }) }),
4018
+ /* @__PURE__ */ jsxs20("div", { className: "flex-1 text-left", children: [
4019
+ /* @__PURE__ */ jsx20("div", { className: "text-sm font-medium", children: "Upload from device" }),
4020
+ /* @__PURE__ */ jsx20("div", { className: "text-[10px] text-text-dim", children: "PNG, JPG, SVG, WebP" })
3896
4021
  ] }),
3897
- /* @__PURE__ */ jsx19("kbd", { className: "text-[10px] text-text-dim bg-surface-dark px-1.5 py-0.5 rounded", children: "U" })
4022
+ /* @__PURE__ */ jsx20("kbd", { className: "text-[10px] text-text-dim bg-surface-dark px-1.5 py-0.5 rounded", children: "U" })
3898
4023
  ]
3899
4024
  }
3900
4025
  )
@@ -3904,13 +4029,13 @@ function ImageSourcePicker() {
3904
4029
  }
3905
4030
 
3906
4031
  // src/react/components/canvas/CanvasLoadingOverlay.jsx
3907
- import { jsx as jsx20, jsxs as jsxs20 } from "react/jsx-runtime";
4032
+ import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
3908
4033
  function CanvasLoadingOverlay() {
3909
4034
  const loading = useUIStore_default((s) => s.canvasLoading);
3910
4035
  const message = useUIStore_default((s) => s.canvasLoadingMessage);
3911
4036
  if (!loading) return null;
3912
- return /* @__PURE__ */ jsx20("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center bg-black/80 backdrop-blur-sm font-[lixFont] pointer-events-all", children: /* @__PURE__ */ jsxs20("div", { className: "flex flex-col items-center gap-5", children: [
3913
- /* @__PURE__ */ jsx20("style", { children: `
4037
+ return /* @__PURE__ */ jsx21("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center bg-black/80 backdrop-blur-sm font-[lixFont] pointer-events-all", children: /* @__PURE__ */ jsxs21("div", { className: "flex flex-col items-center gap-5", children: [
4038
+ /* @__PURE__ */ jsx21("style", { children: `
3914
4039
  @keyframes cl-glob {
3915
4040
  0%, 100% { transform: translate(0, 0) scale(1); opacity: 0.7; }
3916
4041
  25% { transform: translate(10px, -6px) scale(1.12); opacity: 0.9; }
@@ -3928,8 +4053,8 @@ function CanvasLoadingOverlay() {
3928
4053
  50% { transform: translateY(-3px); }
3929
4054
  }
3930
4055
  ` }),
3931
- /* @__PURE__ */ jsxs20("div", { className: "relative w-20 h-20", children: [
3932
- /* @__PURE__ */ jsx20("div", { className: "absolute rounded-full", style: {
4056
+ /* @__PURE__ */ jsxs21("div", { className: "relative w-20 h-20", children: [
4057
+ /* @__PURE__ */ jsx21("div", { className: "absolute rounded-full", style: {
3933
4058
  width: 38,
3934
4059
  height: 38,
3935
4060
  top: 2,
@@ -3939,7 +4064,7 @@ function CanvasLoadingOverlay() {
3939
4064
  animation: "cl-glob 3.5s ease-in-out infinite",
3940
4065
  willChange: "transform, opacity"
3941
4066
  } }),
3942
- /* @__PURE__ */ jsx20("div", { className: "absolute rounded-full", style: {
4067
+ /* @__PURE__ */ jsx21("div", { className: "absolute rounded-full", style: {
3943
4068
  width: 34,
3944
4069
  height: 34,
3945
4070
  top: 14,
@@ -3949,7 +4074,7 @@ function CanvasLoadingOverlay() {
3949
4074
  animation: "cl-glob-2 4s ease-in-out infinite",
3950
4075
  willChange: "transform, opacity"
3951
4076
  } }),
3952
- /* @__PURE__ */ jsx20("div", { className: "absolute rounded-full", style: {
4077
+ /* @__PURE__ */ jsx21("div", { className: "absolute rounded-full", style: {
3953
4078
  width: 30,
3954
4079
  height: 30,
3955
4080
  bottom: 2,
@@ -3959,25 +4084,25 @@ function CanvasLoadingOverlay() {
3959
4084
  animation: "cl-glob 4.2s ease-in-out infinite reverse",
3960
4085
  willChange: "transform, opacity"
3961
4086
  } }),
3962
- /* @__PURE__ */ jsx20("div", { className: "absolute inset-0 flex items-center justify-center", style: { animation: "cl-float 2.5s ease-in-out infinite" }, children: /* @__PURE__ */ jsx20("div", { className: "w-9 h-9 rounded-lg bg-white/[0.06] backdrop-blur-sm border border-white/[0.08] flex items-center justify-center", children: /* @__PURE__ */ jsxs20("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: "opacity-70", children: [
3963
- /* @__PURE__ */ jsx20("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }),
3964
- /* @__PURE__ */ jsx20("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }),
3965
- /* @__PURE__ */ jsx20("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }),
3966
- /* @__PURE__ */ jsx20("rect", { x: "14", y: "14", width: "7", height: "7", rx: "1" })
4087
+ /* @__PURE__ */ jsx21("div", { className: "absolute inset-0 flex items-center justify-center", style: { animation: "cl-float 2.5s ease-in-out infinite" }, children: /* @__PURE__ */ jsx21("div", { className: "w-9 h-9 rounded-lg bg-white/[0.06] backdrop-blur-sm border border-white/[0.08] flex items-center justify-center", children: /* @__PURE__ */ jsxs21("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: "opacity-70", children: [
4088
+ /* @__PURE__ */ jsx21("rect", { x: "3", y: "3", width: "7", height: "7", rx: "1" }),
4089
+ /* @__PURE__ */ jsx21("rect", { x: "14", y: "3", width: "7", height: "7", rx: "1" }),
4090
+ /* @__PURE__ */ jsx21("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }),
4091
+ /* @__PURE__ */ jsx21("rect", { x: "14", y: "14", width: "7", height: "7", rx: "1" })
3967
4092
  ] }) }) })
3968
4093
  ] }),
3969
- /* @__PURE__ */ jsxs20("div", { className: "flex items-center gap-1.5", children: [
3970
- /* @__PURE__ */ jsx20("span", { className: "w-1.5 h-1.5 rounded-full bg-blue-400 animate-bounce", style: { animationDelay: "0ms" } }),
3971
- /* @__PURE__ */ jsx20("span", { className: "w-1.5 h-1.5 rounded-full bg-purple-400 animate-bounce", style: { animationDelay: "150ms" } }),
3972
- /* @__PURE__ */ jsx20("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-400 animate-bounce", style: { animationDelay: "300ms" } })
4094
+ /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-1.5", children: [
4095
+ /* @__PURE__ */ jsx21("span", { className: "w-1.5 h-1.5 rounded-full bg-blue-400 animate-bounce", style: { animationDelay: "0ms" } }),
4096
+ /* @__PURE__ */ jsx21("span", { className: "w-1.5 h-1.5 rounded-full bg-purple-400 animate-bounce", style: { animationDelay: "150ms" } }),
4097
+ /* @__PURE__ */ jsx21("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-400 animate-bounce", style: { animationDelay: "300ms" } })
3973
4098
  ] }),
3974
- /* @__PURE__ */ jsx20("p", { className: "text-text-dim text-sm", children: message })
4099
+ /* @__PURE__ */ jsx21("p", { className: "text-text-dim text-sm", children: message })
3975
4100
  ] }) });
3976
4101
  }
3977
4102
 
3978
4103
  // src/react/components/modals/CommandPalette.jsx
3979
- import { useState as useState17, useEffect as useEffect13, useRef as useRef9 } from "react";
3980
- import { jsx as jsx21, jsxs as jsxs21 } from "react/jsx-runtime";
4104
+ import { useState as useState19, useEffect as useEffect15, useRef as useRef10 } from "react";
4105
+ import { jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
3981
4106
  var CANVAS_COMMANDS = [
3982
4107
  // --- App ---
3983
4108
  { label: "Library", icon: "bx-library", section: "App" },
@@ -4012,11 +4137,15 @@ var CANVAS_COMMANDS = [
4012
4137
  { label: "Arrow", icon: "bx-right-arrow-alt", section: "Tools", shortcut: "A / 5", action: "tool:arrow" },
4013
4138
  { label: "Line", icon: "bx-minus", section: "Tools", shortcut: "L / 6", action: "tool:line" },
4014
4139
  { label: "Freehand", icon: "bx-pencil", section: "Tools", shortcut: "P / 7", action: "tool:freehand" },
4140
+ { label: "Draw to shape", icon: "bx-vector", section: "Tools", shortcut: "D", action: "tool:drawShape" },
4141
+ { label: "Paint bucket", icon: "bxs-color-fill", section: "Tools", shortcut: "B", action: "tool:paintBucket" },
4015
4142
  { label: "Text", icon: "bx-text", section: "Tools", shortcut: "T / 8", action: "tool:text" },
4016
4143
  { label: "Insert image", icon: "bx-image-add", section: "Tools", shortcut: "9", action: "tool:image" },
4017
4144
  { label: "Eraser", icon: "bx-eraser", section: "Tools", shortcut: "E / 0", action: "tool:eraser" },
4018
4145
  { label: "Laser pointer", icon: "bxs-magic-wand", section: "Tools", shortcut: "K", action: "tool:laser" },
4019
4146
  { label: "Frame tool", icon: "bx-border-all", section: "Tools", shortcut: "F", action: "tool:frame" },
4147
+ { label: "Lasso selection", icon: "bx-shape-polygon", section: "Tools", shortcut: "S", action: "tool:lasso" },
4148
+ { label: "Web embed", icon: "bx-globe", section: "Tools", shortcut: "W", action: "tool:webEmbed" },
4020
4149
  // AI entries removed — feature is hidden behind a coming-soon screen.
4021
4150
  // Restore "Text to diagram..." / "Mermaid to diagram..." here when the
4022
4151
  // assistant ships.
@@ -4070,6 +4199,10 @@ var TOOL_ACTION_MAP = {
4070
4199
  "tool:arrow": TOOLS.ARROW,
4071
4200
  "tool:line": TOOLS.LINE,
4072
4201
  "tool:freehand": TOOLS.FREEHAND,
4202
+ "tool:drawShape": TOOLS.DRAW_SHAPE,
4203
+ "tool:paintBucket": TOOLS.PAINT_BUCKET,
4204
+ "tool:lasso": TOOLS.LASSO,
4205
+ "tool:webEmbed": TOOLS.WEB_EMBED,
4073
4206
  "tool:text": TOOLS.TEXT,
4074
4207
  "tool:image": TOOLS.IMAGE,
4075
4208
  "tool:eraser": TOOLS.ERASER,
@@ -4079,12 +4212,12 @@ var TOOL_ACTION_MAP = {
4079
4212
  function CommandPalette() {
4080
4213
  const open = useUIStore_default((s) => s.commandPaletteOpen);
4081
4214
  const toggleCommandPalette = useUIStore_default((s) => s.toggleCommandPalette);
4082
- const [query, setQuery] = useState17("");
4083
- const [activeTab, setActiveTab] = useState17("canvas");
4084
- const [selectedIndex, setSelectedIndex] = useState17(0);
4085
- const inputRef = useRef9(null);
4086
- const listRef = useRef9(null);
4087
- useEffect13(() => {
4215
+ const [query, setQuery] = useState19("");
4216
+ const [activeTab, setActiveTab] = useState19("canvas");
4217
+ const [selectedIndex, setSelectedIndex] = useState19(0);
4218
+ const inputRef = useRef10(null);
4219
+ const listRef = useRef10(null);
4220
+ useEffect15(() => {
4088
4221
  if (open) {
4089
4222
  setQuery("");
4090
4223
  setActiveTab("canvas");
@@ -4092,12 +4225,12 @@ function CommandPalette() {
4092
4225
  setTimeout(() => inputRef.current?.focus(), 50);
4093
4226
  }
4094
4227
  }, [open]);
4095
- useEffect13(() => {
4228
+ useEffect15(() => {
4096
4229
  if (!open) return;
4097
4230
  const el = listRef.current?.querySelector(`[data-index="${selectedIndex}"]`);
4098
4231
  if (el) el.scrollIntoView({ block: "nearest" });
4099
4232
  }, [selectedIndex, open]);
4100
- useEffect13(() => {
4233
+ useEffect15(() => {
4101
4234
  setSelectedIndex(0);
4102
4235
  }, [query, activeTab]);
4103
4236
  if (!open) return null;
@@ -4211,22 +4344,22 @@ function CommandPalette() {
4211
4344
  }
4212
4345
  };
4213
4346
  let flatIndex = -1;
4214
- return /* @__PURE__ */ jsxs21(
4347
+ return /* @__PURE__ */ jsxs22(
4215
4348
  "div",
4216
4349
  {
4217
4350
  className: "fixed inset-0 z-[9999] flex items-center justify-center font-[lixFont]",
4218
4351
  onClick: toggleCommandPalette,
4219
4352
  children: [
4220
- /* @__PURE__ */ jsx21("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm" }),
4221
- /* @__PURE__ */ jsxs21(
4353
+ /* @__PURE__ */ jsx22("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm" }),
4354
+ /* @__PURE__ */ jsxs22(
4222
4355
  "div",
4223
4356
  {
4224
4357
  className: "relative bg-surface-card border border-border-light rounded-2xl w-[92vw] max-w-[1200px] h-[88vh] max-h-[88vh] mx-4 overflow-hidden flex flex-col",
4225
4358
  onClick: (e) => e.stopPropagation(),
4226
4359
  children: [
4227
- /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-3 px-4 py-3 border-b border-border-light", children: [
4228
- /* @__PURE__ */ jsx21("i", { className: "bx bx-search text-text-muted text-lg" }),
4229
- /* @__PURE__ */ jsx21(
4360
+ /* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-3 px-4 py-3 border-b border-border-light", children: [
4361
+ /* @__PURE__ */ jsx22("i", { className: "bx bx-search text-text-muted text-lg" }),
4362
+ /* @__PURE__ */ jsx22(
4230
4363
  "input",
4231
4364
  {
4232
4365
  ref: inputRef,
@@ -4239,38 +4372,38 @@ function CommandPalette() {
4239
4372
  }
4240
4373
  )
4241
4374
  ] }),
4242
- /* @__PURE__ */ jsx21("div", { className: "grid grid-cols-2 gap-1.5 p-2 border-b border-border-light bg-surface-dark/40", children: TABS.map((tab) => /* @__PURE__ */ jsxs21(
4375
+ /* @__PURE__ */ jsx22("div", { className: "grid grid-cols-2 gap-1.5 p-2 border-b border-border-light bg-surface-dark/40", children: TABS.map((tab) => /* @__PURE__ */ jsxs22(
4243
4376
  "button",
4244
4377
  {
4245
4378
  type: "button",
4246
4379
  onClick: () => setActiveTab(tab.id),
4247
4380
  className: `flex items-center justify-center gap-2 rounded-lg px-3 py-2 text-sm transition-colors ${activeTab === tab.id ? "bg-accent-blue/20 text-accent-blue border border-accent-blue/35" : "text-text-muted border border-transparent hover:bg-surface-hover hover:text-text-primary"}`,
4248
4381
  children: [
4249
- /* @__PURE__ */ jsx21("i", { className: `bx ${tab.icon} text-base` }),
4382
+ /* @__PURE__ */ jsx22("i", { className: `bx ${tab.icon} text-base` }),
4250
4383
  tab.label
4251
4384
  ]
4252
4385
  },
4253
4386
  tab.id
4254
4387
  )) }),
4255
- /* @__PURE__ */ jsxs21("div", { ref: listRef, className: "flex-1 min-h-0 overflow-y-auto no-scrollbar py-2", children: [
4256
- filtered.length === 0 && /* @__PURE__ */ jsx21("div", { className: "px-4 py-6 text-center text-text-dim text-xs", children: "No commands found" }),
4257
- sectionOrder.map((section) => /* @__PURE__ */ jsxs21("div", { children: [
4258
- /* @__PURE__ */ jsx21("div", { className: "px-4 pt-3 pb-1", children: /* @__PURE__ */ jsx21("span", { className: "text-text-dim text-xs uppercase tracking-wider", children: section }) }),
4388
+ /* @__PURE__ */ jsxs22("div", { ref: listRef, className: "flex-1 min-h-0 overflow-y-auto no-scrollbar py-2", children: [
4389
+ filtered.length === 0 && /* @__PURE__ */ jsx22("div", { className: "px-4 py-6 text-center text-text-dim text-xs", children: "No commands found" }),
4390
+ sectionOrder.map((section) => /* @__PURE__ */ jsxs22("div", { children: [
4391
+ /* @__PURE__ */ jsx22("div", { className: "px-4 pt-3 pb-1", children: /* @__PURE__ */ jsx22("span", { className: "text-text-dim text-xs uppercase tracking-wider", children: section }) }),
4259
4392
  sections[section].map((cmd) => {
4260
4393
  flatIndex++;
4261
4394
  const idx = flatIndex;
4262
- return /* @__PURE__ */ jsxs21(
4395
+ return /* @__PURE__ */ jsxs22(
4263
4396
  "button",
4264
4397
  {
4265
4398
  "data-index": idx,
4266
4399
  onClick: () => handleCommand(cmd),
4267
4400
  className: `w-full flex items-center justify-between px-4 py-2 text-text-secondary text-xs transition-all duration-100 ${idx === selectedIndex ? "bg-surface-hover text-text-primary" : "hover:bg-surface-hover/60"}`,
4268
4401
  children: [
4269
- /* @__PURE__ */ jsxs21("span", { className: "flex items-center gap-3", children: [
4270
- /* @__PURE__ */ jsx21("i", { className: `bx ${cmd.icon} text-base text-text-muted` }),
4402
+ /* @__PURE__ */ jsxs22("span", { className: "flex items-center gap-3", children: [
4403
+ /* @__PURE__ */ jsx22("i", { className: `bx ${cmd.icon} text-base text-text-muted` }),
4271
4404
  cmd.label
4272
4405
  ] }),
4273
- cmd.shortcut && /* @__PURE__ */ jsx21("div", { className: "flex items-center gap-0.5", children: /* @__PURE__ */ jsx21("kbd", { className: "px-2 py-0.5 bg-surface-dark rounded text-text-dim text-xs border border-border", children: cmd.shortcut }) })
4406
+ cmd.shortcut && /* @__PURE__ */ jsx22("div", { className: "flex items-center gap-0.5", children: /* @__PURE__ */ jsx22("kbd", { className: "px-2 py-0.5 bg-surface-dark rounded text-text-dim text-xs border border-border", children: cmd.shortcut }) })
4274
4407
  ]
4275
4408
  },
4276
4409
  cmd.label
@@ -4287,8 +4420,8 @@ function CommandPalette() {
4287
4420
  }
4288
4421
 
4289
4422
  // src/react/components/modals/ExportImageModal.jsx
4290
- import { useState as useState18, useEffect as useEffect14, useRef as useRef10, useCallback as useCallback14 } from "react";
4291
- import { jsx as jsx22, jsxs as jsxs22 } from "react/jsx-runtime";
4423
+ import { useState as useState20, useEffect as useEffect16, useRef as useRef11, useCallback as useCallback15 } from "react";
4424
+ import { jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
4292
4425
  var SCALES = [1, 2, 3];
4293
4426
  function getCleanSVG2() {
4294
4427
  const svgEl = window.svg;
@@ -4330,16 +4463,16 @@ function renderToCanvas2(clone, scale, bgColor) {
4330
4463
  function ExportImageModal() {
4331
4464
  const open = useUIStore_default((s) => s.exportImageModalOpen);
4332
4465
  const toggleModal = useUIStore_default((s) => s.toggleExportImageModal);
4333
- const [scale, setScale] = useState18(2);
4334
- const [bgMode, setBgMode] = useState18("dark");
4335
- const [previewUrl, setPreviewUrl] = useState18(null);
4336
- const previewRef = useRef10(null);
4337
- const getBgColor = useCallback14(() => {
4466
+ const [scale, setScale] = useState20(2);
4467
+ const [bgMode, setBgMode] = useState20("dark");
4468
+ const [previewUrl, setPreviewUrl] = useState20(null);
4469
+ const previewRef = useRef11(null);
4470
+ const getBgColor = useCallback15(() => {
4338
4471
  if (bgMode === "dark") return "#121212";
4339
4472
  if (bgMode === "light") return "#ffffff";
4340
4473
  return null;
4341
4474
  }, [bgMode]);
4342
- useEffect14(() => {
4475
+ useEffect16(() => {
4343
4476
  if (!open) return;
4344
4477
  let cancelled = false;
4345
4478
  const generate = async () => {
@@ -4413,71 +4546,71 @@ function ExportImageModal() {
4413
4546
  );
4414
4547
  toggleModal();
4415
4548
  };
4416
- return /* @__PURE__ */ jsxs22(
4549
+ return /* @__PURE__ */ jsxs23(
4417
4550
  "div",
4418
4551
  {
4419
4552
  className: "fixed inset-0 z-[9999] flex items-center justify-center font-[lixFont]",
4420
4553
  onClick: toggleModal,
4421
4554
  children: [
4422
- /* @__PURE__ */ jsx22("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm" }),
4423
- /* @__PURE__ */ jsxs22(
4555
+ /* @__PURE__ */ jsx23("div", { className: "absolute inset-0 bg-black/60 backdrop-blur-sm" }),
4556
+ /* @__PURE__ */ jsxs23(
4424
4557
  "div",
4425
4558
  {
4426
4559
  className: "relative bg-surface-card border border-border-light rounded-2xl w-full max-w-[720px] mx-4 overflow-hidden",
4427
4560
  onClick: (e) => e.stopPropagation(),
4428
4561
  children: [
4429
- /* @__PURE__ */ jsxs22("div", { className: "flex items-center justify-between px-6 pt-5 pb-3", children: [
4430
- /* @__PURE__ */ jsx22("h2", { className: "text-text-primary text-base font-medium", children: "Export Image" }),
4431
- /* @__PURE__ */ jsx22(
4562
+ /* @__PURE__ */ jsxs23("div", { className: "flex items-center justify-between px-6 pt-5 pb-3", children: [
4563
+ /* @__PURE__ */ jsx23("h2", { className: "text-text-primary text-base font-medium", children: "Export Image" }),
4564
+ /* @__PURE__ */ jsx23(
4432
4565
  "button",
4433
4566
  {
4434
4567
  onClick: toggleModal,
4435
4568
  className: "w-7 h-7 flex items-center justify-center rounded-lg text-text-muted hover:text-text-primary hover:bg-surface-hover transition-all duration-200",
4436
- children: /* @__PURE__ */ jsx22("i", { className: "bx bx-x text-xl" })
4569
+ children: /* @__PURE__ */ jsx23("i", { className: "bx bx-x text-xl" })
4437
4570
  }
4438
4571
  )
4439
4572
  ] }),
4440
- /* @__PURE__ */ jsx22("hr", { className: "border-border-light mx-6" }),
4441
- /* @__PURE__ */ jsxs22("div", { className: "flex gap-0", children: [
4442
- /* @__PURE__ */ jsx22("div", { className: "flex-1 p-6 flex items-center justify-center min-h-[300px]", children: /* @__PURE__ */ jsx22(
4573
+ /* @__PURE__ */ jsx23("hr", { className: "border-border-light mx-6" }),
4574
+ /* @__PURE__ */ jsxs23("div", { className: "flex gap-0", children: [
4575
+ /* @__PURE__ */ jsx23("div", { className: "flex-1 p-6 flex items-center justify-center min-h-[300px]", children: /* @__PURE__ */ jsx23(
4443
4576
  "div",
4444
4577
  {
4445
4578
  ref: previewRef,
4446
4579
  className: "w-full max-h-[320px] rounded-xl overflow-hidden border border-border-light flex items-center justify-center",
4447
4580
  style: { background: bgMode === "none" ? "repeating-conic-gradient(#2a2a35 0% 25%, #1e1e28 0% 50%) 0 0 / 16px 16px" : getBgColor() },
4448
- children: previewUrl ? /* @__PURE__ */ jsx22(
4581
+ children: previewUrl ? /* @__PURE__ */ jsx23(
4449
4582
  "img",
4450
4583
  {
4451
4584
  src: previewUrl,
4452
4585
  alt: "Export preview",
4453
4586
  className: "w-full h-full object-contain max-h-[320px]"
4454
4587
  }
4455
- ) : /* @__PURE__ */ jsx22("span", { className: "text-text-dim text-xs", children: "Generating preview..." })
4588
+ ) : /* @__PURE__ */ jsx23("span", { className: "text-text-dim text-xs", children: "Generating preview..." })
4456
4589
  }
4457
4590
  ) }),
4458
- /* @__PURE__ */ jsxs22("div", { className: "w-[240px] border-l border-border-light p-5 flex flex-col gap-5", children: [
4459
- /* @__PURE__ */ jsxs22("div", { children: [
4460
- /* @__PURE__ */ jsx22("p", { className: "text-text-dim text-xs uppercase tracking-wider mb-2", children: "Background" }),
4461
- /* @__PURE__ */ jsx22("div", { className: "flex items-center gap-1", children: [
4591
+ /* @__PURE__ */ jsxs23("div", { className: "w-[240px] border-l border-border-light p-5 flex flex-col gap-5", children: [
4592
+ /* @__PURE__ */ jsxs23("div", { children: [
4593
+ /* @__PURE__ */ jsx23("p", { className: "text-text-dim text-xs uppercase tracking-wider mb-2", children: "Background" }),
4594
+ /* @__PURE__ */ jsx23("div", { className: "flex items-center gap-1", children: [
4462
4595
  { value: "dark", label: "Dark", icon: "bxs-moon" },
4463
4596
  { value: "light", label: "Light", icon: "bxs-sun" },
4464
4597
  { value: "none", label: "None", icon: "bx-hide" }
4465
- ].map((opt) => /* @__PURE__ */ jsxs22(
4598
+ ].map((opt) => /* @__PURE__ */ jsxs23(
4466
4599
  "button",
4467
4600
  {
4468
4601
  onClick: () => setBgMode(opt.value),
4469
4602
  className: `flex-1 flex items-center justify-center gap-1 py-1.5 rounded-lg text-xs transition-all duration-200 ${bgMode === opt.value ? "bg-accent text-text-primary" : "text-text-muted hover:bg-surface-hover"}`,
4470
4603
  children: [
4471
- /* @__PURE__ */ jsx22("i", { className: `bx ${opt.icon} text-xs` }),
4604
+ /* @__PURE__ */ jsx23("i", { className: `bx ${opt.icon} text-xs` }),
4472
4605
  opt.label
4473
4606
  ]
4474
4607
  },
4475
4608
  opt.value
4476
4609
  )) })
4477
4610
  ] }),
4478
- /* @__PURE__ */ jsxs22("div", { children: [
4479
- /* @__PURE__ */ jsx22("p", { className: "text-text-dim text-xs uppercase tracking-wider mb-2", children: "Scale" }),
4480
- /* @__PURE__ */ jsx22("div", { className: "flex items-center gap-1", children: SCALES.map((s) => /* @__PURE__ */ jsxs22(
4611
+ /* @__PURE__ */ jsxs23("div", { children: [
4612
+ /* @__PURE__ */ jsx23("p", { className: "text-text-dim text-xs uppercase tracking-wider mb-2", children: "Scale" }),
4613
+ /* @__PURE__ */ jsx23("div", { className: "flex items-center gap-1", children: SCALES.map((s) => /* @__PURE__ */ jsxs23(
4481
4614
  "button",
4482
4615
  {
4483
4616
  onClick: () => setScale(s),
@@ -4490,51 +4623,51 @@ function ExportImageModal() {
4490
4623
  s
4491
4624
  )) })
4492
4625
  ] }),
4493
- /* @__PURE__ */ jsx22("hr", { className: "border-border-light" }),
4494
- /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", children: [
4495
- /* @__PURE__ */ jsxs22(
4626
+ /* @__PURE__ */ jsx23("hr", { className: "border-border-light" }),
4627
+ /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-2", children: [
4628
+ /* @__PURE__ */ jsxs23(
4496
4629
  "button",
4497
4630
  {
4498
4631
  onClick: handleExportPNG,
4499
4632
  className: "w-full flex items-center gap-2 px-3 py-2.5 rounded-lg bg-accent-blue hover:bg-accent-blue-hover text-text-primary text-xs transition-all duration-200",
4500
4633
  children: [
4501
- /* @__PURE__ */ jsx22("i", { className: "bx bx-image text-sm" }),
4634
+ /* @__PURE__ */ jsx23("i", { className: "bx bx-image text-sm" }),
4502
4635
  "Export as PNG"
4503
4636
  ]
4504
4637
  }
4505
4638
  ),
4506
- /* @__PURE__ */ jsxs22(
4639
+ /* @__PURE__ */ jsxs23(
4507
4640
  "button",
4508
4641
  {
4509
4642
  onClick: handleExportSVG,
4510
4643
  className: "w-full flex items-center gap-2 px-3 py-2.5 rounded-lg bg-surface hover:bg-surface-hover border border-border text-text-secondary text-xs transition-all duration-200",
4511
4644
  children: [
4512
- /* @__PURE__ */ jsx22("i", { className: "bx bx-code-alt text-sm" }),
4645
+ /* @__PURE__ */ jsx23("i", { className: "bx bx-code-alt text-sm" }),
4513
4646
  "Export as SVG"
4514
4647
  ]
4515
4648
  }
4516
4649
  )
4517
4650
  ] }),
4518
- /* @__PURE__ */ jsx22("hr", { className: "border-border-light" }),
4519
- /* @__PURE__ */ jsxs22("div", { className: "flex flex-col gap-2", children: [
4520
- /* @__PURE__ */ jsxs22(
4651
+ /* @__PURE__ */ jsx23("hr", { className: "border-border-light" }),
4652
+ /* @__PURE__ */ jsxs23("div", { className: "flex flex-col gap-2", children: [
4653
+ /* @__PURE__ */ jsxs23(
4521
4654
  "button",
4522
4655
  {
4523
4656
  onClick: handleCopyPNG,
4524
4657
  className: "w-full flex items-center gap-2 px-3 py-2 rounded-lg text-text-secondary text-xs hover:bg-surface-hover border border-border transition-all duration-200",
4525
4658
  children: [
4526
- /* @__PURE__ */ jsx22("i", { className: "bx bx-clipboard text-sm" }),
4659
+ /* @__PURE__ */ jsx23("i", { className: "bx bx-clipboard text-sm" }),
4527
4660
  "Copy as PNG"
4528
4661
  ]
4529
4662
  }
4530
4663
  ),
4531
- /* @__PURE__ */ jsxs22(
4664
+ /* @__PURE__ */ jsxs23(
4532
4665
  "button",
4533
4666
  {
4534
4667
  onClick: handleCopySVG,
4535
4668
  className: "w-full flex items-center gap-2 px-3 py-2 rounded-lg text-text-secondary text-xs hover:bg-surface-hover border border-border transition-all duration-200",
4536
4669
  children: [
4537
- /* @__PURE__ */ jsx22("i", { className: "bx bx-copy text-sm" }),
4670
+ /* @__PURE__ */ jsx23("i", { className: "bx bx-copy text-sm" }),
4538
4671
  "Copy as SVG"
4539
4672
  ]
4540
4673
  }
@@ -4551,12 +4684,12 @@ function ExportImageModal() {
4551
4684
  }
4552
4685
 
4553
4686
  // src/react/components/modals/LixScriptModal.jsx
4554
- import { useEffect as useEffect15 } from "react";
4555
- import { jsx as jsx23, jsxs as jsxs23 } from "react/jsx-runtime";
4687
+ import { useEffect as useEffect17 } from "react";
4688
+ import { jsx as jsx24, jsxs as jsxs24 } from "react/jsx-runtime";
4556
4689
  function LixScriptModal() {
4557
4690
  const open = useUIStore_default((state) => state.aiModalOpen);
4558
4691
  const toggle = useUIStore_default((state) => state.toggleAIModal);
4559
- useEffect15(() => {
4692
+ useEffect17(() => {
4560
4693
  if (!open) return;
4561
4694
  const onKeyDown = (event) => {
4562
4695
  if (event.key === "Escape") toggle();
@@ -4565,7 +4698,7 @@ function LixScriptModal() {
4565
4698
  return () => document.removeEventListener("keydown", onKeyDown);
4566
4699
  }, [open, toggle]);
4567
4700
  if (!open) return null;
4568
- return /* @__PURE__ */ jsx23(
4701
+ return /* @__PURE__ */ jsx24(
4569
4702
  "div",
4570
4703
  {
4571
4704
  className: "fixed inset-0 z-[1100] flex items-center justify-center bg-black/40 backdrop-blur-sm font-[lixFont]",
@@ -4573,25 +4706,25 @@ function LixScriptModal() {
4573
4706
  role: "dialog",
4574
4707
  "aria-modal": "true",
4575
4708
  "aria-labelledby": "lixscript-coming-soon-title",
4576
- children: /* @__PURE__ */ jsxs23(
4709
+ children: /* @__PURE__ */ jsxs24(
4577
4710
  "div",
4578
4711
  {
4579
4712
  onClick: (event) => event.stopPropagation(),
4580
4713
  className: "relative w-[520px] max-w-[94vw] bg-surface border border-border-light rounded-2xl px-8 py-10 shadow-2xl text-center",
4581
4714
  children: [
4582
- /* @__PURE__ */ jsx23(
4715
+ /* @__PURE__ */ jsx24(
4583
4716
  "button",
4584
4717
  {
4585
4718
  onClick: toggle,
4586
4719
  className: "absolute top-3 right-3 w-7 h-7 flex items-center justify-center rounded-md text-text-muted hover:text-text-primary hover:bg-surface-hover transition-colors",
4587
4720
  title: "Close (Esc)",
4588
- children: /* @__PURE__ */ jsx23("i", { className: "bx bx-x text-lg" })
4721
+ children: /* @__PURE__ */ jsx24("i", { className: "bx bx-x text-lg" })
4589
4722
  }
4590
4723
  ),
4591
- /* @__PURE__ */ jsx23("div", { className: "mx-auto mb-5 w-12 h-12 rounded-xl bg-accent-blue/10 border border-accent-blue/25 flex items-center justify-center", children: /* @__PURE__ */ jsx23("i", { className: "bx bx-plug text-2xl text-accent-blue" }) }),
4592
- /* @__PURE__ */ jsx23("span", { className: "inline-flex px-2.5 py-1 rounded-full bg-accent-blue/10 text-accent-blue text-[10px] font-semibold uppercase tracking-wider", children: "Coming soon" }),
4593
- /* @__PURE__ */ jsx23("h2", { id: "lixscript-coming-soon-title", className: "mt-4 text-text-primary text-xl font-medium", children: "LixScript MCP" }),
4594
- /* @__PURE__ */ jsx23("p", { className: "mt-2 text-text-muted text-sm leading-relaxed", children: "LixScript is being prepared as the programmable MCP interface for LixSketch. This workspace panel will become available with the supported platform integration." })
4724
+ /* @__PURE__ */ jsx24("div", { className: "mx-auto mb-5 w-12 h-12 rounded-xl bg-accent-blue/10 border border-accent-blue/25 flex items-center justify-center", children: /* @__PURE__ */ jsx24("i", { className: "bx bx-plug text-2xl text-accent-blue" }) }),
4725
+ /* @__PURE__ */ jsx24("span", { className: "inline-flex px-2.5 py-1 rounded-full bg-accent-blue/10 text-accent-blue text-[10px] font-semibold uppercase tracking-wider", children: "Coming soon" }),
4726
+ /* @__PURE__ */ jsx24("h2", { id: "lixscript-coming-soon-title", className: "mt-4 text-text-primary text-xl font-medium", children: "LixScript MCP" }),
4727
+ /* @__PURE__ */ jsx24("p", { className: "mt-2 text-text-muted text-sm leading-relaxed", children: "LixScript is being prepared as the programmable MCP interface for LixSketch. This workspace panel will become available with the supported platform integration." })
4595
4728
  ]
4596
4729
  }
4597
4730
  )
@@ -4600,8 +4733,8 @@ function LixScriptModal() {
4600
4733
  }
4601
4734
 
4602
4735
  // src/react/components/modals/GraphModal.jsx
4603
- import { useCallback as useCallback15, useEffect as useEffect16, useRef as useRef11, useState as useState19 } from "react";
4604
- import { jsx as jsx24, jsxs as jsxs24 } from "react/jsx-runtime";
4736
+ import { useCallback as useCallback16, useEffect as useEffect18, useRef as useRef12, useState as useState21 } from "react";
4737
+ import { jsx as jsx25, jsxs as jsxs25 } from "react/jsx-runtime";
4605
4738
  var SAMPLE = `# One equation per line. Comments start with #.
4606
4739
  # Hit Cmd/Ctrl+Enter to render onto the canvas.
4607
4740
 
@@ -4616,12 +4749,12 @@ function parseEquations(text) {
4616
4749
  function GraphModal() {
4617
4750
  const open = useUIStore_default((s) => s.graphModalOpen);
4618
4751
  const toggle = useUIStore_default((s) => s.toggleGraphModal);
4619
- const [source, setSource] = useState19(SAMPLE);
4620
- const [settings, setSettings] = useState19(DEFAULT_SETTINGS);
4621
- const [busy, setBusy] = useState19(false);
4622
- const [status, setStatus] = useState19(null);
4623
- const taRef = useRef11(null);
4624
- useEffect16(() => {
4752
+ const [source, setSource] = useState21(SAMPLE);
4753
+ const [settings, setSettings] = useState21(DEFAULT_SETTINGS);
4754
+ const [busy, setBusy] = useState21(false);
4755
+ const [status, setStatus] = useState21(null);
4756
+ const taRef = useRef12(null);
4757
+ useEffect18(() => {
4625
4758
  if (!open) return;
4626
4759
  requestAnimationFrame(() => taRef.current?.focus());
4627
4760
  const onKey = (e) => {
@@ -4630,7 +4763,7 @@ function GraphModal() {
4630
4763
  document.addEventListener("keydown", onKey);
4631
4764
  return () => document.removeEventListener("keydown", onKey);
4632
4765
  }, [open, toggle]);
4633
- const render = useCallback15(async () => {
4766
+ const render = useCallback16(async () => {
4634
4767
  if (busy) return;
4635
4768
  setBusy(true);
4636
4769
  setStatus(null);
@@ -4662,7 +4795,7 @@ function GraphModal() {
4662
4795
  setBusy(false);
4663
4796
  }
4664
4797
  }, [source, settings, busy, toggle]);
4665
- const handleKeyDown = useCallback15((e) => {
4798
+ const handleKeyDown = useCallback16((e) => {
4666
4799
  if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
4667
4800
  e.preventDefault();
4668
4801
  render();
@@ -4673,36 +4806,36 @@ function GraphModal() {
4673
4806
  if (Number.isFinite(v)) setSettings((s) => ({ ...s, [key]: v }));
4674
4807
  };
4675
4808
  if (!open) return null;
4676
- return /* @__PURE__ */ jsx24(
4809
+ return /* @__PURE__ */ jsx25(
4677
4810
  "div",
4678
4811
  {
4679
4812
  className: "fixed inset-0 z-[1100] flex items-center justify-center bg-black/60 backdrop-blur-sm font-[lixFont]",
4680
4813
  onClick: toggle,
4681
4814
  role: "dialog",
4682
4815
  "aria-modal": "true",
4683
- children: /* @__PURE__ */ jsxs24(
4816
+ children: /* @__PURE__ */ jsxs25(
4684
4817
  "div",
4685
4818
  {
4686
4819
  onClick: (e) => e.stopPropagation(),
4687
4820
  className: "relative w-[560px] max-w-[94vw] bg-surface border border-border-light rounded-2xl p-5 shadow-2xl flex flex-col gap-3",
4688
4821
  children: [
4689
- /* @__PURE__ */ jsx24(
4822
+ /* @__PURE__ */ jsx25(
4690
4823
  "button",
4691
4824
  {
4692
4825
  onClick: toggle,
4693
4826
  className: "absolute top-3 right-3 w-7 h-7 flex items-center justify-center rounded-md text-text-muted hover:text-text-primary hover:bg-surface-hover transition-colors",
4694
4827
  title: "Close (Esc)",
4695
- children: /* @__PURE__ */ jsx24("i", { className: "bx bx-x text-lg" })
4828
+ children: /* @__PURE__ */ jsx25("i", { className: "bx bx-x text-lg" })
4696
4829
  }
4697
4830
  ),
4698
- /* @__PURE__ */ jsxs24("div", { className: "flex items-center gap-2", children: [
4699
- /* @__PURE__ */ jsx24("div", { className: "w-8 h-8 rounded-lg bg-accent-blue/10 border border-accent-blue/30 flex items-center justify-center", children: /* @__PURE__ */ jsx24("i", { className: "bx bx-line-chart text-accent-blue" }) }),
4700
- /* @__PURE__ */ jsxs24("div", { className: "flex-1", children: [
4701
- /* @__PURE__ */ jsx24("h2", { className: "text-text-primary text-sm font-medium", children: "Graph" }),
4702
- /* @__PURE__ */ jsx24("p", { className: "text-text-dim text-[11px]", children: "One equation per line \u2014 plotted on the canvas. No AI involved." })
4831
+ /* @__PURE__ */ jsxs25("div", { className: "flex items-center gap-2", children: [
4832
+ /* @__PURE__ */ jsx25("div", { className: "w-8 h-8 rounded-lg bg-accent-blue/10 border border-accent-blue/30 flex items-center justify-center", children: /* @__PURE__ */ jsx25("i", { className: "bx bx-line-chart text-accent-blue" }) }),
4833
+ /* @__PURE__ */ jsxs25("div", { className: "flex-1", children: [
4834
+ /* @__PURE__ */ jsx25("h2", { className: "text-text-primary text-sm font-medium", children: "Graph" }),
4835
+ /* @__PURE__ */ jsx25("p", { className: "text-text-dim text-[11px]", children: "One equation per line \u2014 plotted on the canvas. No AI involved." })
4703
4836
  ] })
4704
4837
  ] }),
4705
- /* @__PURE__ */ jsx24(
4838
+ /* @__PURE__ */ jsx25(
4706
4839
  "textarea",
4707
4840
  {
4708
4841
  ref: taRef,
@@ -4713,10 +4846,10 @@ function GraphModal() {
4713
4846
  className: "w-full h-[200px] resize-none bg-surface-card border border-border-light rounded-lg px-3 py-2 text-[12px] text-text-primary font-[lixCode] outline-none focus:border-accent-blue/50"
4714
4847
  }
4715
4848
  ),
4716
- /* @__PURE__ */ jsxs24("div", { className: "grid grid-cols-4 gap-2 text-[11px]", children: [
4717
- /* @__PURE__ */ jsxs24("label", { className: "flex flex-col gap-0.5", children: [
4718
- /* @__PURE__ */ jsx24("span", { className: "text-text-dim", children: "xMin" }),
4719
- /* @__PURE__ */ jsx24(
4849
+ /* @__PURE__ */ jsxs25("div", { className: "grid grid-cols-4 gap-2 text-[11px]", children: [
4850
+ /* @__PURE__ */ jsxs25("label", { className: "flex flex-col gap-0.5", children: [
4851
+ /* @__PURE__ */ jsx25("span", { className: "text-text-dim", children: "xMin" }),
4852
+ /* @__PURE__ */ jsx25(
4720
4853
  "input",
4721
4854
  {
4722
4855
  type: "number",
@@ -4726,9 +4859,9 @@ function GraphModal() {
4726
4859
  }
4727
4860
  )
4728
4861
  ] }),
4729
- /* @__PURE__ */ jsxs24("label", { className: "flex flex-col gap-0.5", children: [
4730
- /* @__PURE__ */ jsx24("span", { className: "text-text-dim", children: "xMax" }),
4731
- /* @__PURE__ */ jsx24(
4862
+ /* @__PURE__ */ jsxs25("label", { className: "flex flex-col gap-0.5", children: [
4863
+ /* @__PURE__ */ jsx25("span", { className: "text-text-dim", children: "xMax" }),
4864
+ /* @__PURE__ */ jsx25(
4732
4865
  "input",
4733
4866
  {
4734
4867
  type: "number",
@@ -4738,9 +4871,9 @@ function GraphModal() {
4738
4871
  }
4739
4872
  )
4740
4873
  ] }),
4741
- /* @__PURE__ */ jsxs24("label", { className: "flex flex-col gap-0.5", children: [
4742
- /* @__PURE__ */ jsx24("span", { className: "text-text-dim", children: "yMin" }),
4743
- /* @__PURE__ */ jsx24(
4874
+ /* @__PURE__ */ jsxs25("label", { className: "flex flex-col gap-0.5", children: [
4875
+ /* @__PURE__ */ jsx25("span", { className: "text-text-dim", children: "yMin" }),
4876
+ /* @__PURE__ */ jsx25(
4744
4877
  "input",
4745
4878
  {
4746
4879
  type: "number",
@@ -4750,9 +4883,9 @@ function GraphModal() {
4750
4883
  }
4751
4884
  )
4752
4885
  ] }),
4753
- /* @__PURE__ */ jsxs24("label", { className: "flex flex-col gap-0.5", children: [
4754
- /* @__PURE__ */ jsx24("span", { className: "text-text-dim", children: "yMax" }),
4755
- /* @__PURE__ */ jsx24(
4886
+ /* @__PURE__ */ jsxs25("label", { className: "flex flex-col gap-0.5", children: [
4887
+ /* @__PURE__ */ jsx25("span", { className: "text-text-dim", children: "yMax" }),
4888
+ /* @__PURE__ */ jsx25(
4756
4889
  "input",
4757
4890
  {
4758
4891
  type: "number",
@@ -4763,9 +4896,9 @@ function GraphModal() {
4763
4896
  )
4764
4897
  ] })
4765
4898
  ] }),
4766
- /* @__PURE__ */ jsxs24("div", { className: "flex items-center justify-between", children: [
4767
- status ? /* @__PURE__ */ jsx24("span", { className: `text-[11px] ${status.tone === "error" ? "text-red-400" : "text-green-400"}`, children: status.message }) : /* @__PURE__ */ jsx24("span", { className: "text-text-dim text-[11px]", children: "Cmd/Ctrl+Enter to render \xB7 Esc to close" }),
4768
- /* @__PURE__ */ jsx24(
4899
+ /* @__PURE__ */ jsxs25("div", { className: "flex items-center justify-between", children: [
4900
+ status ? /* @__PURE__ */ jsx25("span", { className: `text-[11px] ${status.tone === "error" ? "text-red-400" : "text-green-400"}`, children: status.message }) : /* @__PURE__ */ jsx25("span", { className: "text-text-dim text-[11px]", children: "Cmd/Ctrl+Enter to render \xB7 Esc to close" }),
4901
+ /* @__PURE__ */ jsx25(
4769
4902
  "button",
4770
4903
  {
4771
4904
  onClick: render,
@@ -4782,13 +4915,87 @@ function GraphModal() {
4782
4915
  );
4783
4916
  }
4784
4917
 
4918
+ // src/react/components/modals/WebEmbedModal.jsx
4919
+ import { useEffect as useEffect19, useRef as useRef13, useState as useState22 } from "react";
4920
+ import { jsx as jsx26, jsxs as jsxs26 } from "react/jsx-runtime";
4921
+ function WebEmbedModal() {
4922
+ const [open, setOpen] = useState22(false), [url, setUrl] = useState22(""), [error, setError] = useState22("");
4923
+ const inputRef = useRef13(null);
4924
+ useEffect19(() => {
4925
+ const show = () => {
4926
+ setOpen(true);
4927
+ setError("");
4928
+ requestAnimationFrame(() => inputRef.current?.focus());
4929
+ };
4930
+ window.__showWebEmbedModal = show;
4931
+ window.addEventListener("lixsketch:open-web-embed", show);
4932
+ return () => {
4933
+ delete window.__showWebEmbedModal;
4934
+ window.removeEventListener("lixsketch:open-web-embed", show);
4935
+ };
4936
+ }, []);
4937
+ useEffect19(() => {
4938
+ if (!open) return void 0;
4939
+ const escape = (event) => {
4940
+ if (event.key === "Escape") {
4941
+ setOpen(false);
4942
+ useSketchStore_default.getState().setActiveTool(TOOLS.SELECT);
4943
+ }
4944
+ };
4945
+ window.addEventListener("keydown", escape);
4946
+ return () => window.removeEventListener("keydown", escape);
4947
+ }, [open]);
4948
+ if (!open) return null;
4949
+ let requestedHostname = "";
4950
+ try {
4951
+ requestedHostname = new URL(url).hostname;
4952
+ } catch {
4953
+ }
4954
+ const whitelistRequestUrl = `https://github.com/elixpo/sketch.elixpo/issues/new?template=web-embed-whitelist.yml&title=${encodeURIComponent(`[Web embed whitelist] ${requestedHostname || "New hostname"}`)}`;
4955
+ const submit = (e) => {
4956
+ e.preventDefault();
4957
+ const normalized = normalizeWebEmbedUrl(url);
4958
+ if (!normalized) {
4959
+ setError("This site is not currently supported for web embeds.");
4960
+ return;
4961
+ }
4962
+ window.__placeWebEmbed?.(normalized);
4963
+ setOpen(false);
4964
+ setUrl("");
4965
+ };
4966
+ return /* @__PURE__ */ jsx26("div", { className: "fixed inset-0 z-[12000] flex items-center justify-center bg-black/55 p-4 backdrop-blur-sm", children: /* @__PURE__ */ jsxs26("form", { onSubmit: submit, className: "w-full max-w-xl rounded-2xl border border-border-light bg-surface-card p-6 font-[lixFont] shadow-2xl", children: [
4967
+ /* @__PURE__ */ jsxs26("div", { className: "mb-5 flex justify-between", children: [
4968
+ /* @__PURE__ */ jsxs26("div", { children: [
4969
+ /* @__PURE__ */ jsx26("h2", { className: "text-lg text-text-primary", children: "Embed a website" }),
4970
+ /* @__PURE__ */ jsx26("p", { className: "mt-1 text-xs text-text-muted", children: "One secure embed in a movable, resizable frame." })
4971
+ ] }),
4972
+ /* @__PURE__ */ jsx26("button", { type: "button", onClick: () => {
4973
+ setOpen(false);
4974
+ useSketchStore_default.getState().setActiveTool(TOOLS.SELECT);
4975
+ }, children: /* @__PURE__ */ jsx26("i", { className: "bx bx-x text-2xl" }) })
4976
+ ] }),
4977
+ /* @__PURE__ */ jsx26("input", { ref: inputRef, value: url, onChange: (e) => {
4978
+ setUrl(e.target.value);
4979
+ setError("");
4980
+ }, placeholder: "https://www.youtube.com/watch?v=...", className: "w-full rounded-xl border border-border-light bg-surface px-4 py-3 text-sm text-text-primary outline-none focus:border-accent" }),
4981
+ error && /* @__PURE__ */ jsxs26("div", { className: "mt-3 flex items-center justify-between gap-3 rounded-xl border border-border-light bg-surface/60 px-3 py-2.5", children: [
4982
+ /* @__PURE__ */ jsxs26("p", { className: "text-xs text-text-muted", children: [
4983
+ /* @__PURE__ */ jsx26("i", { className: "bx bx-info-circle mr-1" }),
4984
+ error
4985
+ ] }),
4986
+ /* @__PURE__ */ jsx26("a", { href: whitelistRequestUrl, target: "_blank", rel: "noreferrer", className: "shrink-0 rounded-lg border border-accent/50 px-3 py-1.5 text-xs text-accent", children: "Request whitelist" })
4987
+ ] }),
4988
+ /* @__PURE__ */ jsx26("button", { type: "submit", className: "mt-5 w-full rounded-xl bg-accent px-4 py-3 text-sm text-white", children: "Place on canvas" })
4989
+ ] }) });
4990
+ }
4991
+
4785
4992
  // src/react/LixSketchCanvas.jsx
4786
- import { jsx as jsx25, jsxs as jsxs25 } from "react/jsx-runtime";
4993
+ import { jsx as jsx27, jsxs as jsxs27 } from "react/jsx-runtime";
4787
4994
  var _saveScene = null;
4788
4995
  var _loadScene = null;
4789
4996
  async function ensureSceneSerializer() {
4790
4997
  if (_saveScene && _loadScene) return;
4791
- const m = await import("./SceneSerializer-RDISX4X7.js");
4998
+ const m = await import("./SceneSerializer-SG6SJN5X.js");
4792
4999
  _saveScene = m.saveScene;
4793
5000
  _loadScene = m.loadScene;
4794
5001
  }
@@ -4801,14 +5008,14 @@ function LixSketchCanvas({
4801
5008
  className = "",
4802
5009
  style = null
4803
5010
  }) {
4804
- const wrapperRef = useRef12(null);
4805
- const lastSceneJsonRef = useRef12("");
4806
- const debounceRef = useRef12(null);
4807
- const [bootstrapped, setBootstrapped] = useState20(false);
4808
- useEffect17(() => {
5011
+ const wrapperRef = useRef14(null);
5012
+ const lastSceneJsonRef = useRef14("");
5013
+ const debounceRef = useRef14(null);
5014
+ const [bootstrapped, setBootstrapped] = useState23(false);
5015
+ useEffect20(() => {
4809
5016
  installImageUploadBridge(onUploadImage);
4810
5017
  }, [onUploadImage]);
4811
- useEffect17(() => {
5018
+ useEffect20(() => {
4812
5019
  if (typeof document === "undefined" || !document.fonts?.load) return;
4813
5020
  Promise.allSettled([
4814
5021
  document.fonts.load("1em lixFont"),
@@ -4816,7 +5023,7 @@ function LixSketchCanvas({
4816
5023
  ]).catch(() => {
4817
5024
  });
4818
5025
  }, []);
4819
- useEffect17(() => {
5026
+ useEffect20(() => {
4820
5027
  if (!initialScene || bootstrapped) return;
4821
5028
  let cancelled = false;
4822
5029
  async function tryLoad() {
@@ -4844,7 +5051,7 @@ function LixSketchCanvas({
4844
5051
  cancelled = true;
4845
5052
  };
4846
5053
  }, [initialScene, bootstrapped]);
4847
- useEffect17(() => {
5054
+ useEffect20(() => {
4848
5055
  function handleKey(e) {
4849
5056
  if (e.key === "Escape") {
4850
5057
  useUIStore_default.getState().closeAllModals?.();
@@ -4893,7 +5100,7 @@ function LixSketchCanvas({
4893
5100
  window.addEventListener("keydown", handleKey);
4894
5101
  return () => window.removeEventListener("keydown", handleKey);
4895
5102
  }, [onSceneChange]);
4896
- useEffect17(() => {
5103
+ useEffect20(() => {
4897
5104
  if (!onSceneChange) return;
4898
5105
  let svg = null;
4899
5106
  let observer = null;
@@ -4939,84 +5146,86 @@ function LixSketchCanvas({
4939
5146
  clearTimeout(debounceRef.current);
4940
5147
  };
4941
5148
  }, [onSceneChange]);
4942
- return /* @__PURE__ */ jsxs25(
5149
+ return /* @__PURE__ */ jsxs27(
4943
5150
  "div",
4944
5151
  {
4945
5152
  ref: wrapperRef,
4946
5153
  className: `lixsketch-canvas-root canvas-mode ${className}`,
4947
5154
  style,
4948
5155
  children: [
4949
- /* @__PURE__ */ jsx25(SVGCanvas, {}),
4950
- /* @__PURE__ */ jsx25(Toolbar, {}),
4951
- /* @__PURE__ */ jsx25(Footer, {}),
4952
- /* @__PURE__ */ jsx25(AppMenu, {}),
4953
- /* @__PURE__ */ jsx25(RectangleSidebar, {}),
4954
- /* @__PURE__ */ jsx25(CircleSidebar, {}),
4955
- /* @__PURE__ */ jsx25(LineSidebar, {}),
4956
- /* @__PURE__ */ jsx25(ArrowSidebar, {}),
4957
- /* @__PURE__ */ jsx25(PaintbrushSidebar, {}),
4958
- /* @__PURE__ */ jsx25(TextSidebar, {}),
4959
- /* @__PURE__ */ jsx25(FrameSidebar, {}),
4960
- /* @__PURE__ */ jsx25(IconSidebar, {}),
4961
- /* @__PURE__ */ jsx25(ImageSidebar, {}),
4962
- /* @__PURE__ */ jsx25(MultiSelectActions, {}),
4963
- /* @__PURE__ */ jsx25(CommandPalette, {}),
4964
- /* @__PURE__ */ jsx25(ExportImageModal, {}),
4965
- /* @__PURE__ */ jsx25(LixScriptModal, {}),
4966
- /* @__PURE__ */ jsx25(GraphModal, {}),
4967
- /* @__PURE__ */ jsx25(ContextMenu, {}),
4968
- /* @__PURE__ */ jsx25(FindBar, {}),
4969
- /* @__PURE__ */ jsx25(ImageSourcePicker, {}),
4970
- /* @__PURE__ */ jsx25(CanvasLoadingOverlay, {}),
4971
- /* @__PURE__ */ jsxs25("div", { className: "lixsketch-floating-header absolute top-2 right-2 z-[1000] flex items-center gap-1.5 font-[lixFont]", children: [
4972
- /* @__PURE__ */ jsx25(
5156
+ /* @__PURE__ */ jsx27(SVGCanvas, {}),
5157
+ /* @__PURE__ */ jsx27(Toolbar, {}),
5158
+ /* @__PURE__ */ jsx27(Footer, {}),
5159
+ /* @__PURE__ */ jsx27(AppMenu, {}),
5160
+ /* @__PURE__ */ jsx27(RectangleSidebar, {}),
5161
+ /* @__PURE__ */ jsx27(CircleSidebar, {}),
5162
+ /* @__PURE__ */ jsx27(PaintBucketSidebar, {}),
5163
+ /* @__PURE__ */ jsx27(LineSidebar, {}),
5164
+ /* @__PURE__ */ jsx27(ArrowSidebar, {}),
5165
+ /* @__PURE__ */ jsx27(PaintbrushSidebar, {}),
5166
+ /* @__PURE__ */ jsx27(TextSidebar, {}),
5167
+ /* @__PURE__ */ jsx27(FrameSidebar, {}),
5168
+ /* @__PURE__ */ jsx27(IconSidebar, {}),
5169
+ /* @__PURE__ */ jsx27(ImageSidebar, {}),
5170
+ /* @__PURE__ */ jsx27(MultiSelectActions, {}),
5171
+ /* @__PURE__ */ jsx27(CommandPalette, {}),
5172
+ /* @__PURE__ */ jsx27(ExportImageModal, {}),
5173
+ /* @__PURE__ */ jsx27(LixScriptModal, {}),
5174
+ /* @__PURE__ */ jsx27(GraphModal, {}),
5175
+ /* @__PURE__ */ jsx27(WebEmbedModal, {}),
5176
+ /* @__PURE__ */ jsx27(ContextMenu, {}),
5177
+ /* @__PURE__ */ jsx27(FindBar, {}),
5178
+ /* @__PURE__ */ jsx27(ImageSourcePicker, {}),
5179
+ /* @__PURE__ */ jsx27(CanvasLoadingOverlay, {}),
5180
+ /* @__PURE__ */ jsxs27("div", { className: "lixsketch-floating-header absolute top-2 right-2 z-[1000] flex items-center gap-1.5 font-[lixFont]", children: [
5181
+ /* @__PURE__ */ jsx27(
4973
5182
  "button",
4974
5183
  {
4975
5184
  type: "button",
4976
5185
  title: "LixScript MCP \u2014 coming soon",
4977
5186
  onClick: () => useUIStore_default.getState().toggleAIModal?.(),
4978
5187
  className: "w-9 h-9 flex items-center justify-center rounded-lg bg-surface border border-border-light text-text-muted hover:text-text-primary hover:bg-surface-hover transition-colors cursor-pointer",
4979
- children: /* @__PURE__ */ jsx25("i", { className: "bx bx-code-alt text-base" })
5188
+ children: /* @__PURE__ */ jsx27("i", { className: "bx bx-code-alt text-base" })
4980
5189
  }
4981
5190
  ),
4982
- /* @__PURE__ */ jsx25(
5191
+ /* @__PURE__ */ jsx27(
4983
5192
  "button",
4984
5193
  {
4985
5194
  type: "button",
4986
5195
  title: "Graph \u2014 plot equations",
4987
5196
  onClick: () => useUIStore_default.getState().toggleGraphModal?.(),
4988
5197
  className: "w-9 h-9 flex items-center justify-center rounded-lg bg-surface border border-border-light text-text-muted hover:text-text-primary hover:bg-surface-hover transition-colors cursor-pointer",
4989
- children: /* @__PURE__ */ jsx25("i", { className: "bx bx-line-chart text-base" })
5198
+ children: /* @__PURE__ */ jsx27("i", { className: "bx bx-line-chart text-base" })
4990
5199
  }
4991
5200
  ),
4992
- /* @__PURE__ */ jsx25(
5201
+ /* @__PURE__ */ jsx27(
4993
5202
  "button",
4994
5203
  {
4995
5204
  type: "button",
4996
5205
  title: "Commands and shortcuts (Ctrl+/)",
4997
5206
  onClick: () => useUIStore_default.getState().toggleCommandPalette?.(),
4998
5207
  className: "w-9 h-9 flex items-center justify-center rounded-lg bg-surface border border-border-light text-text-muted hover:text-text-primary hover:bg-surface-hover transition-colors cursor-pointer",
4999
- children: /* @__PURE__ */ jsx25("i", { className: "bx bx-command text-base" })
5208
+ children: /* @__PURE__ */ jsx27("i", { className: "bx bx-command text-base" })
5000
5209
  }
5001
5210
  ),
5002
- /* @__PURE__ */ jsx25(
5211
+ /* @__PURE__ */ jsx27(
5003
5212
  "button",
5004
5213
  {
5005
5214
  type: "button",
5006
5215
  title: "Menu",
5007
5216
  onClick: () => useUIStore_default.getState().toggleMenu?.(),
5008
5217
  className: "w-9 h-9 flex items-center justify-center rounded-lg bg-surface border border-border-light text-text-muted hover:text-text-primary hover:bg-surface-hover transition-colors cursor-pointer",
5009
- children: /* @__PURE__ */ jsx25("i", { className: "bx bx-menu text-base" })
5218
+ children: /* @__PURE__ */ jsx27("i", { className: "bx bx-menu text-base" })
5010
5219
  }
5011
5220
  )
5012
5221
  ] }),
5013
- /* @__PURE__ */ jsxs25(
5222
+ /* @__PURE__ */ jsxs27(
5014
5223
  "div",
5015
5224
  {
5016
5225
  id: "lixsketch-save-toast",
5017
5226
  className: "hidden fixed bottom-20 left-1/2 -translate-x-1/2 z-[9999] px-4 py-2 rounded-xl bg-surface/85 backdrop-blur-md border border-border-light text-text-secondary text-xs font-[lixFont] pointer-events-none",
5018
5227
  children: [
5019
- /* @__PURE__ */ jsx25("i", { className: "bx bx-check text-green-400 mr-1.5" }),
5228
+ /* @__PURE__ */ jsx27("i", { className: "bx bx-check text-green-400 mr-1.5" }),
5020
5229
  "Saved"
5021
5230
  ]
5022
5231
  }
@@ -5090,7 +5299,11 @@ var TOOLS2 = {
5090
5299
  LASER: "laser",
5091
5300
  IMAGE: "image",
5092
5301
  FRAME: "frame",
5093
- ICON: "icon"
5302
+ ICON: "icon",
5303
+ DRAW_SHAPE: "draw-shape",
5304
+ PAINT_BUCKET: "paint-bucket",
5305
+ LASSO: "lasso",
5306
+ WEB_EMBED: "web-embed"
5094
5307
  };
5095
5308
 
5096
5309
  // src/EngineShortcuts.js
@@ -5115,7 +5328,11 @@ var SHORTCUT_MAP2 = {
5115
5328
  0: "eraser",
5116
5329
  i: "icon",
5117
5330
  f: "frame",
5118
- k: "laser"
5331
+ k: "laser",
5332
+ d: "draw-shape",
5333
+ b: "paint-bucket",
5334
+ s: "lasso",
5335
+ w: "web-embed"
5119
5336
  };
5120
5337
  var TOOLS3 = {
5121
5338
  SELECT: "select",
@@ -5131,7 +5348,11 @@ var TOOLS3 = {
5131
5348
  LASER: "laser",
5132
5349
  IMAGE: "image",
5133
5350
  FRAME: "frame",
5134
- ICON: "icon"
5351
+ ICON: "icon",
5352
+ DRAW_SHAPE: "draw-shape",
5353
+ PAINT_BUCKET: "paint-bucket",
5354
+ LASSO: "lasso",
5355
+ WEB_EMBED: "web-embed"
5135
5356
  };
5136
5357
  function isTypingTarget(target) {
5137
5358
  if (!target) return false;
@@ -5328,6 +5549,7 @@ function installEngineShortcuts(engine, options = {}) {
5328
5549
  if (skipWhen && skipWhen(e)) return;
5329
5550
  e.preventDefault();
5330
5551
  spaceHeld = true;
5552
+ window.__spacePanActive = true;
5331
5553
  const active = getActiveTool();
5332
5554
  if (active && active !== TOOLS3.PAN) {
5333
5555
  toolBeforeSpace = active;
@@ -5337,12 +5559,21 @@ function installEngineShortcuts(engine, options = {}) {
5337
5559
  function handleKeyUp(e) {
5338
5560
  if (e.code === "Space" && spaceHeld) {
5339
5561
  spaceHeld = false;
5562
+ window.__spacePanActive = false;
5340
5563
  if (toolBeforeSpace) {
5341
5564
  setTool(toolBeforeSpace);
5342
5565
  toolBeforeSpace = null;
5343
5566
  }
5344
5567
  }
5345
5568
  }
5569
+ function handleWindowBlur() {
5570
+ spaceHeld = false;
5571
+ window.__spacePanActive = false;
5572
+ if (toolBeforeSpace) {
5573
+ setTool(toolBeforeSpace);
5574
+ toolBeforeSpace = null;
5575
+ }
5576
+ }
5346
5577
  function handleWheel(e) {
5347
5578
  if (e.ctrlKey || e.metaKey) e.preventDefault();
5348
5579
  }
@@ -5350,11 +5581,14 @@ function installEngineShortcuts(engine, options = {}) {
5350
5581
  document.addEventListener("keydown", handleSpaceDown);
5351
5582
  document.addEventListener("keyup", handleKeyUp);
5352
5583
  document.addEventListener("wheel", handleWheel, { passive: false });
5584
+ window.addEventListener("blur", handleWindowBlur);
5353
5585
  return function uninstall() {
5354
5586
  document.removeEventListener("keydown", handleKeyDown);
5355
5587
  document.removeEventListener("keydown", handleSpaceDown);
5356
5588
  document.removeEventListener("keyup", handleKeyUp);
5357
5589
  document.removeEventListener("wheel", handleWheel);
5590
+ window.removeEventListener("blur", handleWindowBlur);
5591
+ window.__spacePanActive = false;
5358
5592
  };
5359
5593
  }
5360
5594
  export {