@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.
- package/README.md +85 -6
- package/dist/mcp/index.js +585 -0
- package/dist/mcp/index.js.map +7 -0
- package/dist/mcp/node.js +184 -0
- package/dist/mcp/node.js.map +7 -0
- package/dist/mcp/stdio.js +723 -0
- package/dist/mcp/stdio.js.map +7 -0
- package/dist/react/{CopyPaste-5OWPTCQ5.js → CopyPaste-YUDZ6DHY.js} +7 -7
- package/dist/react/EventDispatcher-7LAK7GQ7.js +1097 -0
- package/dist/react/EventDispatcher-7LAK7GQ7.js.map +7 -0
- package/dist/react/Frame-7D2MXCFF.js +11 -0
- package/dist/react/IconShape-ZADX7Y33.js +10 -0
- package/dist/react/ImageShape-UJQN2HI7.js +10 -0
- package/dist/react/Line-APEULMHE.js +10 -0
- package/dist/react/{SceneSerializer-RDISX4X7.js → SceneSerializer-SG6SJN5X.js} +17 -7
- package/dist/react/SceneSerializer-SG6SJN5X.js.map +7 -0
- package/dist/react/{Selection-ZL3G6IAO.js → Selection-2TSH3J6P.js} +6 -4
- package/dist/react/{SketchEngine-OB6ZW3B6.js → SketchEngine-UD2XV2KT.js} +50 -23
- package/dist/react/{SketchEngine-OB6ZW3B6.js.map → SketchEngine-UD2XV2KT.js.map} +2 -2
- package/dist/react/{UndoRedo-NL7KLR5B.js → UndoRedo-IN4SXDG6.js} +2 -2
- package/dist/react/{ZoomPan-FAWA5OPS.js → ZoomPan-RR7KUYZT.js} +34 -1
- package/dist/react/{ZoomPan-FAWA5OPS.js.map → ZoomPan-RR7KUYZT.js.map} +2 -2
- package/dist/react/{arrowTool-CNVGM6RX.js → arrowTool-OYDWJGQK.js} +3 -3
- package/dist/react/{chunk-U3TB4KRS.js → chunk-6GPEWDRB.js} +19 -12
- package/dist/react/chunk-6GPEWDRB.js.map +7 -0
- package/dist/react/{chunk-4BLMNGTR.js → chunk-7CM5XQDN.js} +3 -3
- package/dist/react/{chunk-XFQECTTF.js → chunk-APTOPAOY.js} +3 -3
- package/dist/react/{chunk-EDSKEM6E.js → chunk-ASBC5G35.js} +47 -8
- package/dist/react/chunk-ASBC5G35.js.map +7 -0
- package/dist/react/{chunk-4TAS67SL.js → chunk-EOURRJ55.js} +2 -2
- package/dist/react/{chunk-ETAAQUUV.js → chunk-GQUZPON4.js} +4 -4
- package/dist/react/{chunk-KVAQPCUH.js → chunk-K5BG5MHY.js} +49 -5
- package/dist/react/chunk-K5BG5MHY.js.map +7 -0
- package/dist/react/{chunk-AH4PWNEB.js → chunk-K5RY4EV7.js} +23 -3
- package/dist/react/chunk-K5RY4EV7.js.map +7 -0
- package/dist/react/{chunk-GC3KTQDA.js → chunk-LJR7EVW2.js} +3 -3
- package/dist/react/{chunk-SZD7DKYJ.js → chunk-LSHZYN77.js} +2 -2
- package/dist/react/{chunk-HFQZYCHJ.js → chunk-M6TMN76K.js} +3 -3
- package/dist/react/{chunk-V2QTYSBK.js → chunk-OP56XPWF.js} +2 -2
- package/dist/react/chunk-QZI4UIE5.js +48 -0
- package/dist/react/chunk-QZI4UIE5.js.map +7 -0
- package/dist/react/{chunk-ILGAFR56.js → chunk-RGMDWLRJ.js} +3 -3
- package/dist/react/{chunk-OFGJJKPH.js → chunk-XFL4R5ZF.js} +3 -3
- package/dist/react/{chunk-GPIYXREE.js → chunk-XOWNCYE4.js} +3 -3
- package/dist/react/{chunk-YF3TK7SC.js → chunk-XYUFEIZR.js} +2 -2
- package/dist/react/{circleTool-KICNRQCI.js → circleTool-LDKGZALF.js} +4 -4
- package/dist/react/{codeTool-NCQ73R6M.js → codeTool-4YZO5W7J.js} +4 -4
- package/dist/react/{frameTool-Y6KB67DO.js → frameTool-MXNJEXQQ.js} +4 -4
- package/dist/react/{freehandTool-MMULHCQ7.js → freehandTool-26D3FOOX.js} +4 -4
- package/dist/react/{iconTool-LSW2DYGB.js → iconTool-46O5VEUX.js} +4 -4
- package/dist/react/{imageTool-2DSR32RX.js → imageTool-P2RWZRHO.js} +4 -4
- package/dist/react/index.js +848 -614
- package/dist/react/index.js.map +4 -4
- package/dist/react/{lineTool-N5I7IGT7.js → lineTool-ZMR27U5L.js} +4 -4
- package/dist/react/{rectangleTool-YUT7ZK2E.js → rectangleTool-EJKK6UTX.js} +4 -4
- package/dist/react/{textTool-JMTX7OVT.js → textTool-S4XXZHZH.js} +5 -5
- package/package.json +7 -1
- package/src/EngineShortcuts.js +22 -0
- package/src/SketchEngine.js +27 -0
- package/src/core/EventDispatcher.js +35 -4
- package/src/core/SceneSerializer.js +5 -0
- package/src/core/Selection.js +26 -0
- package/src/core/UndoRedo.js +20 -16
- package/src/core/WebEmbedPolicy.js +41 -0
- package/src/core/ZoomPan.js +36 -0
- package/src/index.js +4 -0
- package/src/mcp/fileStore.js +70 -0
- package/src/mcp/index.js +5 -0
- package/src/mcp/node.js +2 -0
- package/src/mcp/preview.js +39 -0
- package/src/mcp/scene.js +275 -0
- package/src/mcp/server.js +195 -0
- package/src/mcp/stdio.js +41 -0
- package/src/mcp/stdioTransport.js +46 -0
- package/src/mcp/store.js +23 -0
- package/src/mcp/templates.js +51 -0
- package/src/react/LixSketchCanvas.jsx +4 -0
- package/src/react/components/Toolbar.jsx +84 -7
- package/src/react/components/modals/CommandPalette.jsx +8 -0
- package/src/react/components/modals/WebEmbedModal.jsx +40 -0
- package/src/react/components/sidebars/PaintBucketSidebar.jsx +49 -0
- package/src/react/components/sidebars/PaintbrushSidebar.jsx +1 -1
- package/src/react/store/useSketchStore.js +13 -0
- package/src/react/toolsEnum.js +4 -0
- package/src/shapes/Frame.js +47 -4
- package/src/shapes/ImageShape.js +49 -6
- package/src/tools/lassoTool.js +84 -0
- package/src/tools/paintBucketTool.js +50 -0
- package/src/tools/shapeRecognitionTool.js +431 -0
- package/src/tools/webEmbedTool.js +61 -0
- package/dist/react/EventDispatcher-GKNO2KSL.js +0 -464
- package/dist/react/EventDispatcher-GKNO2KSL.js.map +0 -7
- package/dist/react/Frame-RLSMJJSK.js +0 -11
- package/dist/react/IconShape-7OPXAKLK.js +0 -10
- package/dist/react/ImageShape-T7UEHP4A.js +0 -10
- package/dist/react/Line-WWQFBNX5.js +0 -10
- package/dist/react/SceneSerializer-RDISX4X7.js.map +0 -7
- package/dist/react/chunk-AH4PWNEB.js.map +0 -7
- package/dist/react/chunk-EDSKEM6E.js.map +0 -7
- package/dist/react/chunk-KVAQPCUH.js.map +0 -7
- package/dist/react/chunk-U3TB4KRS.js.map +0 -7
- /package/dist/react/{CopyPaste-5OWPTCQ5.js.map → CopyPaste-YUDZ6DHY.js.map} +0 -0
- /package/dist/react/{Frame-RLSMJJSK.js.map → Frame-7D2MXCFF.js.map} +0 -0
- /package/dist/react/{IconShape-7OPXAKLK.js.map → IconShape-ZADX7Y33.js.map} +0 -0
- /package/dist/react/{ImageShape-T7UEHP4A.js.map → ImageShape-UJQN2HI7.js.map} +0 -0
- /package/dist/react/{Line-WWQFBNX5.js.map → Line-APEULMHE.js.map} +0 -0
- /package/dist/react/{Selection-ZL3G6IAO.js.map → Selection-2TSH3J6P.js.map} +0 -0
- /package/dist/react/{UndoRedo-NL7KLR5B.js.map → UndoRedo-IN4SXDG6.js.map} +0 -0
- /package/dist/react/{arrowTool-CNVGM6RX.js.map → arrowTool-OYDWJGQK.js.map} +0 -0
- /package/dist/react/{chunk-4BLMNGTR.js.map → chunk-7CM5XQDN.js.map} +0 -0
- /package/dist/react/{chunk-XFQECTTF.js.map → chunk-APTOPAOY.js.map} +0 -0
- /package/dist/react/{chunk-4TAS67SL.js.map → chunk-EOURRJ55.js.map} +0 -0
- /package/dist/react/{chunk-ETAAQUUV.js.map → chunk-GQUZPON4.js.map} +0 -0
- /package/dist/react/{chunk-GC3KTQDA.js.map → chunk-LJR7EVW2.js.map} +0 -0
- /package/dist/react/{chunk-SZD7DKYJ.js.map → chunk-LSHZYN77.js.map} +0 -0
- /package/dist/react/{chunk-HFQZYCHJ.js.map → chunk-M6TMN76K.js.map} +0 -0
- /package/dist/react/{chunk-V2QTYSBK.js.map → chunk-OP56XPWF.js.map} +0 -0
- /package/dist/react/{chunk-ILGAFR56.js.map → chunk-RGMDWLRJ.js.map} +0 -0
- /package/dist/react/{chunk-OFGJJKPH.js.map → chunk-XFL4R5ZF.js.map} +0 -0
- /package/dist/react/{chunk-GPIYXREE.js.map → chunk-XOWNCYE4.js.map} +0 -0
- /package/dist/react/{chunk-YF3TK7SC.js.map → chunk-XYUFEIZR.js.map} +0 -0
- /package/dist/react/{circleTool-KICNRQCI.js.map → circleTool-LDKGZALF.js.map} +0 -0
- /package/dist/react/{codeTool-NCQ73R6M.js.map → codeTool-4YZO5W7J.js.map} +0 -0
- /package/dist/react/{frameTool-Y6KB67DO.js.map → frameTool-MXNJEXQQ.js.map} +0 -0
- /package/dist/react/{freehandTool-MMULHCQ7.js.map → freehandTool-26D3FOOX.js.map} +0 -0
- /package/dist/react/{iconTool-LSW2DYGB.js.map → iconTool-46O5VEUX.js.map} +0 -0
- /package/dist/react/{imageTool-2DSR32RX.js.map → imageTool-P2RWZRHO.js.map} +0 -0
- /package/dist/react/{lineTool-N5I7IGT7.js.map → lineTool-ZMR27U5L.js.map} +0 -0
- /package/dist/react/{rectangleTool-YUT7ZK2E.js.map → rectangleTool-EJKK6UTX.js.map} +0 -0
- /package/dist/react/{textTool-JMTX7OVT.js.map → textTool-S4XXZHZH.js.map} +0 -0
package/dist/react/index.js
CHANGED
|
@@ -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
|
|
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-
|
|
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.
|
|
850
|
-
|
|
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-
|
|
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
|
|
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
|
-
|
|
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] =
|
|
1258
|
-
const [actionsOpen, setActionsOpen] =
|
|
1259
|
-
const [actionsFlyoutPosition, setActionsFlyoutPosition] =
|
|
1260
|
-
const actionsButtonRef =
|
|
1261
|
-
const [dangerAction, setDangerAction] =
|
|
1262
|
-
|
|
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
|
|
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] =
|
|
1612
|
-
const ref =
|
|
1613
|
-
|
|
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
|
|
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] =
|
|
1733
|
-
const [bgColor, setBgColor] =
|
|
1734
|
-
const [thickness, setThickness] =
|
|
1735
|
-
const [lineStyle, setLineStyle] =
|
|
1736
|
-
const [fillStyle, setFillStyle] =
|
|
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
|
|
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] =
|
|
1868
|
-
const [bgColor, setBgColor] =
|
|
1869
|
-
const [thickness, setThickness] =
|
|
1870
|
-
const [lineStyle, setLineStyle] =
|
|
1871
|
-
const [fillStyle, setFillStyle] =
|
|
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/
|
|
1964
|
-
import {
|
|
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__ */
|
|
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] =
|
|
1983
|
-
const [thickness, setThickness] =
|
|
1984
|
-
const [lineStyle, setLineStyle] =
|
|
1985
|
-
const [sloppiness, setSloppiness] =
|
|
1986
|
-
const [edge, setEdge] =
|
|
1987
|
-
const updateStroke =
|
|
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 =
|
|
2116
|
+
const updateThickness = useCallback5((v) => {
|
|
1992
2117
|
setThickness(v);
|
|
1993
2118
|
if (window.updateSelectedLineStyle) window.updateSelectedLineStyle({ strokeWidth: v });
|
|
1994
2119
|
}, []);
|
|
1995
|
-
const updateStyle =
|
|
2120
|
+
const updateStyle = useCallback5((v) => {
|
|
1996
2121
|
setLineStyle(v);
|
|
1997
2122
|
if (window.updateSelectedLineStyle) window.updateSelectedLineStyle({ strokeStyle: v });
|
|
1998
2123
|
}, []);
|
|
1999
|
-
const updateSloppiness =
|
|
2124
|
+
const updateSloppiness = useCallback5((v) => {
|
|
2000
2125
|
setSloppiness(v);
|
|
2001
2126
|
if (window.updateSelectedLineStyle) window.updateSelectedLineStyle({ sloppiness: v });
|
|
2002
2127
|
}, []);
|
|
2003
|
-
const updateEdge =
|
|
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__ */
|
|
2008
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2137
|
+
preview: /* @__PURE__ */ jsx10("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: strokeColor } }),
|
|
2013
2138
|
children: [
|
|
2014
|
-
/* @__PURE__ */
|
|
2015
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2020
|
-
/* @__PURE__ */
|
|
2021
|
-
/* @__PURE__ */
|
|
2022
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2033
|
-
/* @__PURE__ */
|
|
2034
|
-
/* @__PURE__ */
|
|
2035
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2046
|
-
/* @__PURE__ */
|
|
2047
|
-
/* @__PURE__ */
|
|
2048
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2059
|
-
/* @__PURE__ */
|
|
2060
|
-
/* @__PURE__ */
|
|
2061
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2076
|
-
/* @__PURE__ */
|
|
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
|
|
2082
|
-
import { Fragment as Fragment5, jsx as
|
|
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__ */
|
|
2216
|
+
return /* @__PURE__ */ jsx11("span", { dangerouslySetInnerHTML: { __html: svg } });
|
|
2092
2217
|
}
|
|
2093
2218
|
function ColorGrid4({ colors, selected, onSelect }) {
|
|
2094
|
-
return /* @__PURE__ */
|
|
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] =
|
|
2109
|
-
const [strokeColor, setStrokeColor] =
|
|
2110
|
-
const [thickness, setThickness] =
|
|
2111
|
-
const [outlineStyle, setOutlineStyle] =
|
|
2112
|
-
const [arrowType, setArrowType] =
|
|
2113
|
-
const [curvature, setCurvature] =
|
|
2114
|
-
const updateHead =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
2145
|
-
/* @__PURE__ */
|
|
2146
|
-
/* @__PURE__ */
|
|
2147
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2277
|
+
children: /* @__PURE__ */ jsx11(SvgIcon, { svg: h.svg })
|
|
2153
2278
|
},
|
|
2154
2279
|
h.value
|
|
2155
2280
|
)) })
|
|
2156
2281
|
] }),
|
|
2157
|
-
/* @__PURE__ */
|
|
2158
|
-
/* @__PURE__ */
|
|
2282
|
+
/* @__PURE__ */ jsx11(Divider, {}),
|
|
2283
|
+
/* @__PURE__ */ jsxs11(
|
|
2159
2284
|
ToolbarButton,
|
|
2160
2285
|
{
|
|
2161
2286
|
tooltip: t("sidebar.strokeColor"),
|
|
2162
|
-
preview: /* @__PURE__ */
|
|
2287
|
+
preview: /* @__PURE__ */ jsx11("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: strokeColor } }),
|
|
2163
2288
|
children: [
|
|
2164
|
-
/* @__PURE__ */
|
|
2165
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2170
|
-
/* @__PURE__ */
|
|
2171
|
-
/* @__PURE__ */
|
|
2172
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2183
|
-
/* @__PURE__ */
|
|
2184
|
-
/* @__PURE__ */
|
|
2185
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2196
|
-
/* @__PURE__ */
|
|
2197
|
-
/* @__PURE__ */
|
|
2198
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2217
|
-
/* @__PURE__ */
|
|
2218
|
-
/* @__PURE__ */
|
|
2219
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2232
|
-
/* @__PURE__ */
|
|
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
|
|
2238
|
-
import { jsx as
|
|
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__ */
|
|
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] =
|
|
2257
|
-
const [thickness, setThickness] =
|
|
2258
|
-
const [lineStyle, setLineStyle] =
|
|
2259
|
-
const [taper, setTaper] =
|
|
2260
|
-
const [roughness, setRoughness] =
|
|
2261
|
-
const [opacity, setOpacity] =
|
|
2262
|
-
const updateStroke =
|
|
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 =
|
|
2391
|
+
const updateThickness = useCallback7((v) => {
|
|
2267
2392
|
setThickness(v);
|
|
2268
2393
|
if (window.updateSelectedFreehandStyle) window.updateSelectedFreehandStyle({ strokeWidth: v });
|
|
2269
2394
|
}, []);
|
|
2270
|
-
const updateTaper =
|
|
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 =
|
|
2399
|
+
const updateRoughness = useCallback7((v) => {
|
|
2275
2400
|
setRoughness(v);
|
|
2276
2401
|
if (window.updateSelectedFreehandStyle) window.updateSelectedFreehandStyle({ roughness: v });
|
|
2277
2402
|
}, []);
|
|
2278
|
-
const updateOpacity =
|
|
2403
|
+
const updateOpacity = useCallback7((v) => {
|
|
2279
2404
|
setOpacity(v);
|
|
2280
2405
|
if (window.updateSelectedFreehandStyle) window.updateSelectedFreehandStyle({ opacity: v });
|
|
2281
2406
|
}, []);
|
|
2282
|
-
return /* @__PURE__ */
|
|
2283
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2412
|
+
preview: /* @__PURE__ */ jsx12("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: strokeColor } }),
|
|
2288
2413
|
children: [
|
|
2289
|
-
/* @__PURE__ */
|
|
2290
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2295
|
-
/* @__PURE__ */
|
|
2296
|
-
/* @__PURE__ */
|
|
2297
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2308
|
-
/* @__PURE__ */
|
|
2309
|
-
/* @__PURE__ */
|
|
2310
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2329
|
-
/* @__PURE__ */
|
|
2330
|
-
/* @__PURE__ */
|
|
2331
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2350
|
-
/* @__PURE__ */
|
|
2351
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2370
|
-
/* @__PURE__ */
|
|
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
|
|
2376
|
-
import { Fragment as Fragment6, jsx as
|
|
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] =
|
|
2412
|
-
const [fontSize, setFontSize] =
|
|
2413
|
-
const [font, setFont] =
|
|
2414
|
-
const [codeMode, setCodeMode] =
|
|
2415
|
-
const [language, setLanguage] =
|
|
2416
|
-
|
|
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 =
|
|
2550
|
+
const updateColor = useCallback8((c) => {
|
|
2426
2551
|
setTextColor(c);
|
|
2427
2552
|
if (window.updateSelectedTextStyle) window.updateSelectedTextStyle({ color: c });
|
|
2428
2553
|
}, []);
|
|
2429
|
-
const updateFont =
|
|
2554
|
+
const updateFont = useCallback8((f) => {
|
|
2430
2555
|
setFont(f);
|
|
2431
2556
|
if (window.updateSelectedTextStyle) window.updateSelectedTextStyle({ font: f });
|
|
2432
2557
|
}, []);
|
|
2433
|
-
const updateSize =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
2453
|
-
/* @__PURE__ */
|
|
2454
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2583
|
+
preview: /* @__PURE__ */ jsx13("span", { className: "w-4 h-4 rounded-md border border-white/20", style: { backgroundColor: textColor } }),
|
|
2459
2584
|
children: [
|
|
2460
|
-
/* @__PURE__ */
|
|
2461
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2474
|
-
/* @__PURE__ */
|
|
2475
|
-
/* @__PURE__ */
|
|
2476
|
-
/* @__PURE__ */
|
|
2477
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2490
|
-
/* @__PURE__ */
|
|
2491
|
-
/* @__PURE__ */
|
|
2492
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2503
|
-
/* @__PURE__ */
|
|
2504
|
-
/* @__PURE__ */
|
|
2505
|
-
/* @__PURE__ */
|
|
2506
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
2529
|
-
/* @__PURE__ */
|
|
2653
|
+
/* @__PURE__ */ jsx13(Divider, {}),
|
|
2654
|
+
/* @__PURE__ */ jsx13(LayerControls, {})
|
|
2530
2655
|
] }),
|
|
2531
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2536
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2663
|
+
/* @__PURE__ */ jsx13("span", { className: "text-white/50", children: "Enter" }),
|
|
2539
2664
|
" \u2014 ",
|
|
2540
2665
|
t("sidebar.renderText"),
|
|
2541
2666
|
" \xA0\xA0",
|
|
2542
|
-
/* @__PURE__ */
|
|
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
|
|
2553
|
-
import { Fragment as Fragment7, jsx as
|
|
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] =
|
|
2573
|
-
const [isGraph, setIsGraph] =
|
|
2574
|
-
const [fillStyle, setFillStyle] =
|
|
2575
|
-
const [fillColor, setFillColor] =
|
|
2576
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
2630
|
-
/* @__PURE__ */
|
|
2631
|
-
/* @__PURE__ */
|
|
2632
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2644
|
-
/* @__PURE__ */
|
|
2645
|
-
/* @__PURE__ */
|
|
2646
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2660
|
-
/* @__PURE__ */
|
|
2661
|
-
/* @__PURE__ */
|
|
2662
|
-
FILL_COLORS.map((c) => /* @__PURE__ */
|
|
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__ */
|
|
2673
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2688
|
-
/* @__PURE__ */
|
|
2689
|
-
/* @__PURE__ */
|
|
2690
|
-
/* @__PURE__ */
|
|
2691
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2847
|
+
/* @__PURE__ */ jsx14("i", { className: "bx bx-upload text-sm" }),
|
|
2723
2848
|
"Set Image"
|
|
2724
2849
|
]
|
|
2725
2850
|
}
|
|
2726
2851
|
),
|
|
2727
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2749
|
-
/* @__PURE__ */
|
|
2750
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2772
|
-
/* @__PURE__ */
|
|
2773
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2777
|
-
/* @__PURE__ */
|
|
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
|
|
2783
|
-
import { jsx as
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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] =
|
|
2851
|
-
const [category, setCategory] =
|
|
2852
|
-
const [icons, setIcons] =
|
|
2853
|
-
const [loading, setLoading] =
|
|
2854
|
-
const debounceRef =
|
|
2855
|
-
const searchInputRef =
|
|
2856
|
-
const requestSequenceRef =
|
|
2857
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
2937
|
-
/* @__PURE__ */
|
|
2938
|
-
/* @__PURE__ */
|
|
2939
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3070
|
+
children: /* @__PURE__ */ jsx15("i", { className: "bx bx-x text-lg" })
|
|
2946
3071
|
}
|
|
2947
3072
|
)
|
|
2948
3073
|
] }),
|
|
2949
|
-
/* @__PURE__ */
|
|
2950
|
-
/* @__PURE__ */
|
|
2951
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3096
|
+
children: /* @__PURE__ */ jsx15("i", { className: "bx bxs-x-circle text-sm" })
|
|
2972
3097
|
}
|
|
2973
3098
|
)
|
|
2974
3099
|
] })
|
|
2975
3100
|
] }),
|
|
2976
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
2991
|
-
/* @__PURE__ */
|
|
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__ */
|
|
2999
|
-
/* @__PURE__ */
|
|
3000
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
3017
|
-
import { Fragment as Fragment8, jsx as
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
3047
|
-
isGraph && /* @__PURE__ */
|
|
3048
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3056
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3185
|
+
/* @__PURE__ */ jsx16(Divider, {})
|
|
3061
3186
|
] }),
|
|
3062
|
-
!isGraph && /* @__PURE__ */
|
|
3063
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3071
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3076
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3084
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3213
|
+
/* @__PURE__ */ jsx16(Divider, {})
|
|
3089
3214
|
] }),
|
|
3090
|
-
/* @__PURE__ */
|
|
3215
|
+
/* @__PURE__ */ jsx16(LayerControls, {})
|
|
3091
3216
|
] });
|
|
3092
3217
|
}
|
|
3093
3218
|
|
|
3094
3219
|
// src/react/components/canvas/MultiSelectActions.jsx
|
|
3095
|
-
import { useState as
|
|
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
|
|
3246
|
+
import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
3122
3247
|
function MultiSelectActions() {
|
|
3123
|
-
const [count, setCount] =
|
|
3124
|
-
const [groupState, setGroupState] =
|
|
3125
|
-
const [frameEligible, setFrameEligible] =
|
|
3126
|
-
|
|
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__ */
|
|
3191
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3319
|
+
grouped && /* @__PURE__ */ jsx17("span", { className: "ml-1 text-accent-blue", children: "\xB7 grouped" })
|
|
3195
3320
|
] }),
|
|
3196
|
-
/* @__PURE__ */
|
|
3197
|
-
!grouped && frameEligible && /* @__PURE__ */
|
|
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__ */
|
|
3329
|
+
/* @__PURE__ */ jsx17("i", { className: "bx bx-crop text-sm" }),
|
|
3205
3330
|
"Frame it"
|
|
3206
3331
|
]
|
|
3207
3332
|
}
|
|
3208
3333
|
),
|
|
3209
|
-
grouped ? /* @__PURE__ */
|
|
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__ */
|
|
3341
|
+
/* @__PURE__ */ jsx17("i", { className: "bx bx-unlink text-sm" }),
|
|
3217
3342
|
"Ungroup"
|
|
3218
3343
|
]
|
|
3219
3344
|
}
|
|
3220
|
-
) : /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
3237
|
-
import { Fragment as Fragment9, jsx as
|
|
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__ */
|
|
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__ */
|
|
3298
|
-
shortcut && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3311
|
-
checked && /* @__PURE__ */
|
|
3312
|
-
!checked && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3446
|
+
return /* @__PURE__ */ jsx18("hr", { className: "border-border-light my-1" });
|
|
3322
3447
|
}
|
|
3323
3448
|
function ContextMenu() {
|
|
3324
|
-
const [visible, setVisible] =
|
|
3325
|
-
const [position, setPosition] =
|
|
3326
|
-
const [targetShape, setTargetShape] =
|
|
3327
|
-
const menuRef =
|
|
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 =
|
|
3457
|
+
const close = useCallback12(() => {
|
|
3333
3458
|
setVisible(false);
|
|
3334
3459
|
setTargetShape(null);
|
|
3335
3460
|
}, []);
|
|
3336
|
-
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
3583
|
-
/* @__PURE__ */
|
|
3584
|
-
/* @__PURE__ */
|
|
3585
|
-
/* @__PURE__ */
|
|
3586
|
-
/* @__PURE__ */
|
|
3587
|
-
!fullyGrouped && /* @__PURE__ */
|
|
3588
|
-
canGroup && !fullyGrouped && /* @__PURE__ */
|
|
3589
|
-
canUngroup && /* @__PURE__ */
|
|
3590
|
-
/* @__PURE__ */
|
|
3591
|
-
/* @__PURE__ */
|
|
3592
|
-
/* @__PURE__ */
|
|
3593
|
-
/* @__PURE__ */
|
|
3594
|
-
/* @__PURE__ */
|
|
3595
|
-
/* @__PURE__ */
|
|
3596
|
-
/* @__PURE__ */
|
|
3597
|
-
/* @__PURE__ */
|
|
3598
|
-
/* @__PURE__ */
|
|
3599
|
-
/* @__PURE__ */
|
|
3600
|
-
/* @__PURE__ */
|
|
3601
|
-
/* @__PURE__ */
|
|
3602
|
-
/* @__PURE__ */
|
|
3603
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3608
|
-
/* @__PURE__ */
|
|
3609
|
-
/* @__PURE__ */
|
|
3610
|
-
/* @__PURE__ */
|
|
3611
|
-
/* @__PURE__ */
|
|
3612
|
-
/* @__PURE__ */
|
|
3613
|
-
/* @__PURE__ */
|
|
3614
|
-
/* @__PURE__ */
|
|
3615
|
-
/* @__PURE__ */
|
|
3616
|
-
/* @__PURE__ */
|
|
3617
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3622
|
-
/* @__PURE__ */
|
|
3623
|
-
/* @__PURE__ */
|
|
3624
|
-
/* @__PURE__ */
|
|
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
|
|
3637
|
-
import { jsx as
|
|
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] =
|
|
3642
|
-
const [results, setResults] =
|
|
3643
|
-
const [activeIndex, setActiveIndex] =
|
|
3644
|
-
const inputRef =
|
|
3645
|
-
const highlightRef =
|
|
3646
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
3743
|
-
/* @__PURE__ */
|
|
3744
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3762
|
-
results.length > 1 && /* @__PURE__ */
|
|
3763
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3893
|
+
children: /* @__PURE__ */ jsx19("i", { className: "bx bx-chevron-up text-sm" })
|
|
3769
3894
|
}
|
|
3770
3895
|
),
|
|
3771
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3901
|
+
children: /* @__PURE__ */ jsx19("i", { className: "bx bx-chevron-down text-sm" })
|
|
3777
3902
|
}
|
|
3778
3903
|
)
|
|
3779
3904
|
] }),
|
|
3780
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
3793
|
-
import { jsx as
|
|
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 =
|
|
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 =
|
|
3925
|
+
const handleGenerateAI = useCallback14(() => {
|
|
3801
3926
|
setActiveTool("select");
|
|
3802
3927
|
toggleImageGenerateModal();
|
|
3803
3928
|
}, [setActiveTool, toggleImageGenerateModal]);
|
|
3804
|
-
const handleUpload =
|
|
3929
|
+
const handleUpload = useCallback14(() => {
|
|
3805
3930
|
setActiveTool("select");
|
|
3806
3931
|
if (window.openImageFilePicker) {
|
|
3807
3932
|
window.openImageFilePicker();
|
|
3808
3933
|
}
|
|
3809
3934
|
}, [setActiveTool]);
|
|
3810
|
-
|
|
3935
|
+
useEffect14(() => {
|
|
3811
3936
|
window.__showImageSourcePicker = () => {
|
|
3812
3937
|
};
|
|
3813
3938
|
return () => {
|
|
3814
3939
|
delete window.__showImageSourcePicker;
|
|
3815
3940
|
};
|
|
3816
3941
|
}, []);
|
|
3817
|
-
|
|
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__ */
|
|
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__ */
|
|
3867
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3874
|
-
/* @__PURE__ */
|
|
3875
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3878
|
-
/* @__PURE__ */
|
|
3879
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
3886
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3893
|
-
/* @__PURE__ */
|
|
3894
|
-
/* @__PURE__ */
|
|
3895
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
3913
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3932
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3963
|
-
/* @__PURE__ */
|
|
3964
|
-
/* @__PURE__ */
|
|
3965
|
-
/* @__PURE__ */
|
|
3966
|
-
/* @__PURE__ */
|
|
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__ */
|
|
3970
|
-
/* @__PURE__ */
|
|
3971
|
-
/* @__PURE__ */
|
|
3972
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
3980
|
-
import { jsx as
|
|
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] =
|
|
4083
|
-
const [activeTab, setActiveTab] =
|
|
4084
|
-
const [selectedIndex, setSelectedIndex] =
|
|
4085
|
-
const inputRef =
|
|
4086
|
-
const listRef =
|
|
4087
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
4221
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4228
|
-
/* @__PURE__ */
|
|
4229
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
4256
|
-
filtered.length === 0 && /* @__PURE__ */
|
|
4257
|
-
sectionOrder.map((section) => /* @__PURE__ */
|
|
4258
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4270
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
4291
|
-
import { jsx as
|
|
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] =
|
|
4334
|
-
const [bgMode, setBgMode] =
|
|
4335
|
-
const [previewUrl, setPreviewUrl] =
|
|
4336
|
-
const previewRef =
|
|
4337
|
-
const getBgColor =
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
4423
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4430
|
-
/* @__PURE__ */
|
|
4431
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4569
|
+
children: /* @__PURE__ */ jsx23("i", { className: "bx bx-x text-xl" })
|
|
4437
4570
|
}
|
|
4438
4571
|
)
|
|
4439
4572
|
] }),
|
|
4440
|
-
/* @__PURE__ */
|
|
4441
|
-
/* @__PURE__ */
|
|
4442
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4588
|
+
) : /* @__PURE__ */ jsx23("span", { className: "text-text-dim text-xs", children: "Generating preview..." })
|
|
4456
4589
|
}
|
|
4457
4590
|
) }),
|
|
4458
|
-
/* @__PURE__ */
|
|
4459
|
-
/* @__PURE__ */
|
|
4460
|
-
/* @__PURE__ */
|
|
4461
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
4479
|
-
/* @__PURE__ */
|
|
4480
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4494
|
-
/* @__PURE__ */
|
|
4495
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4634
|
+
/* @__PURE__ */ jsx23("i", { className: "bx bx-image text-sm" }),
|
|
4502
4635
|
"Export as PNG"
|
|
4503
4636
|
]
|
|
4504
4637
|
}
|
|
4505
4638
|
),
|
|
4506
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4519
|
-
/* @__PURE__ */
|
|
4520
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4659
|
+
/* @__PURE__ */ jsx23("i", { className: "bx bx-clipboard text-sm" }),
|
|
4527
4660
|
"Copy as PNG"
|
|
4528
4661
|
]
|
|
4529
4662
|
}
|
|
4530
4663
|
),
|
|
4531
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
4555
|
-
import { jsx as
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
4721
|
+
children: /* @__PURE__ */ jsx24("i", { className: "bx bx-x text-lg" })
|
|
4589
4722
|
}
|
|
4590
4723
|
),
|
|
4591
|
-
/* @__PURE__ */
|
|
4592
|
-
/* @__PURE__ */
|
|
4593
|
-
/* @__PURE__ */
|
|
4594
|
-
/* @__PURE__ */
|
|
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
|
|
4604
|
-
import { jsx as
|
|
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] =
|
|
4620
|
-
const [settings, setSettings] =
|
|
4621
|
-
const [busy, setBusy] =
|
|
4622
|
-
const [status, setStatus] =
|
|
4623
|
-
const taRef =
|
|
4624
|
-
|
|
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 =
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
4828
|
+
children: /* @__PURE__ */ jsx25("i", { className: "bx bx-x text-lg" })
|
|
4696
4829
|
}
|
|
4697
4830
|
),
|
|
4698
|
-
/* @__PURE__ */
|
|
4699
|
-
/* @__PURE__ */
|
|
4700
|
-
/* @__PURE__ */
|
|
4701
|
-
/* @__PURE__ */
|
|
4702
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4717
|
-
/* @__PURE__ */
|
|
4718
|
-
/* @__PURE__ */
|
|
4719
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4730
|
-
/* @__PURE__ */
|
|
4731
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4742
|
-
/* @__PURE__ */
|
|
4743
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4754
|
-
/* @__PURE__ */
|
|
4755
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4767
|
-
status ? /* @__PURE__ */
|
|
4768
|
-
/* @__PURE__ */
|
|
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
|
|
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-
|
|
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 =
|
|
4805
|
-
const lastSceneJsonRef =
|
|
4806
|
-
const debounceRef =
|
|
4807
|
-
const [bootstrapped, setBootstrapped] =
|
|
4808
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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__ */
|
|
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__ */
|
|
4950
|
-
/* @__PURE__ */
|
|
4951
|
-
/* @__PURE__ */
|
|
4952
|
-
/* @__PURE__ */
|
|
4953
|
-
/* @__PURE__ */
|
|
4954
|
-
/* @__PURE__ */
|
|
4955
|
-
/* @__PURE__ */
|
|
4956
|
-
/* @__PURE__ */
|
|
4957
|
-
/* @__PURE__ */
|
|
4958
|
-
/* @__PURE__ */
|
|
4959
|
-
/* @__PURE__ */
|
|
4960
|
-
/* @__PURE__ */
|
|
4961
|
-
/* @__PURE__ */
|
|
4962
|
-
/* @__PURE__ */
|
|
4963
|
-
/* @__PURE__ */
|
|
4964
|
-
/* @__PURE__ */
|
|
4965
|
-
/* @__PURE__ */
|
|
4966
|
-
/* @__PURE__ */
|
|
4967
|
-
/* @__PURE__ */
|
|
4968
|
-
/* @__PURE__ */
|
|
4969
|
-
/* @__PURE__ */
|
|
4970
|
-
/* @__PURE__ */
|
|
4971
|
-
/* @__PURE__ */
|
|
4972
|
-
|
|
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__ */
|
|
5188
|
+
children: /* @__PURE__ */ jsx27("i", { className: "bx bx-code-alt text-base" })
|
|
4980
5189
|
}
|
|
4981
5190
|
),
|
|
4982
|
-
/* @__PURE__ */
|
|
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__ */
|
|
5198
|
+
children: /* @__PURE__ */ jsx27("i", { className: "bx bx-line-chart text-base" })
|
|
4990
5199
|
}
|
|
4991
5200
|
),
|
|
4992
|
-
/* @__PURE__ */
|
|
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__ */
|
|
5208
|
+
children: /* @__PURE__ */ jsx27("i", { className: "bx bx-command text-base" })
|
|
5000
5209
|
}
|
|
5001
5210
|
),
|
|
5002
|
-
/* @__PURE__ */
|
|
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__ */
|
|
5218
|
+
children: /* @__PURE__ */ jsx27("i", { className: "bx bx-menu text-base" })
|
|
5010
5219
|
}
|
|
5011
5220
|
)
|
|
5012
5221
|
] }),
|
|
5013
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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 {
|