@pixerate/editor-react 0.29.0 → 0.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/vector/index.cjs +246 -155
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +19 -2
- package/dist/vector/index.d.ts +19 -2
- package/dist/vector/index.js +226 -136
- package/dist/vector/index.js.map +1 -1
- package/package.json +3 -3
package/dist/vector/index.js
CHANGED
|
@@ -44,9 +44,9 @@ function useVectorCommands(registry, controller, options = {}) {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
// src/vector/VectorCanvas.tsx
|
|
47
|
-
import { useEffect as useEffect2, useId, useRef as
|
|
47
|
+
import { useEffect as useEffect2, useId, useRef as useRef3 } from "react";
|
|
48
48
|
import {
|
|
49
|
-
VECTOR_OVERLAY_THEME as
|
|
49
|
+
VECTOR_OVERLAY_THEME as THEME2,
|
|
50
50
|
getVectorOverlayRenderData,
|
|
51
51
|
getVectorSceneRenderData,
|
|
52
52
|
isVectorTextTarget,
|
|
@@ -54,17 +54,102 @@ import {
|
|
|
54
54
|
toVectorPointerInput,
|
|
55
55
|
vectorDiamondPath
|
|
56
56
|
} from "@pixerate/editor/vector";
|
|
57
|
-
|
|
57
|
+
|
|
58
|
+
// src/vector/VectorWidthPointEditor.tsx
|
|
59
|
+
import { useRef as useRef2, useState } from "react";
|
|
60
|
+
import { VECTOR_OVERLAY_THEME as THEME } from "@pixerate/editor/vector";
|
|
61
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
62
|
+
var round = (v, digits) => String(Math.round(v * 10 ** digits) / 10 ** digits);
|
|
63
|
+
var fieldStyle = { display: "flex", alignItems: "center", justifyContent: "space-between", gap: 6 };
|
|
64
|
+
var inputStyle = { width: 72, font: "inherit", padding: "1px 4px" };
|
|
65
|
+
function VectorWidthPointEditor({ controller, edit, accentColor = THEME.accent, className, style }) {
|
|
66
|
+
const [position, setPosition] = useState(() => round(edit.t * 100, 2));
|
|
67
|
+
const [left, setLeft] = useState(() => round(edit.left, 3));
|
|
68
|
+
const [right, setRight] = useState(() => round(edit.right, 3));
|
|
69
|
+
const formRef = useRef2(null);
|
|
70
|
+
const refocus = () => formRef.current?.closest("svg")?.focus?.({ preventScroll: true });
|
|
71
|
+
const close = () => {
|
|
72
|
+
refocus();
|
|
73
|
+
controller.closeWidthPointEdit();
|
|
74
|
+
};
|
|
75
|
+
const num = (v) => v.trim() !== "" && Number.isFinite(Number(v)) ? Number(v) : void 0;
|
|
76
|
+
const apply = () => {
|
|
77
|
+
const t = num(position);
|
|
78
|
+
refocus();
|
|
79
|
+
controller.commitWidthPointEdit({ t: t === void 0 ? void 0 : Math.min(Math.max(t, 0), 100) / 100, left: num(left), right: num(right) });
|
|
80
|
+
};
|
|
81
|
+
const stop = (e) => e.stopPropagation();
|
|
82
|
+
return /* @__PURE__ */ jsxs(
|
|
83
|
+
"form",
|
|
84
|
+
{
|
|
85
|
+
ref: formRef,
|
|
86
|
+
"data-vector-width-point-editor": "",
|
|
87
|
+
"aria-label": "Width point",
|
|
88
|
+
className,
|
|
89
|
+
style: {
|
|
90
|
+
display: "grid",
|
|
91
|
+
gap: 4,
|
|
92
|
+
padding: 8,
|
|
93
|
+
background: "#ffffff",
|
|
94
|
+
border: "1px solid rgba(0,0,0,0.15)",
|
|
95
|
+
borderRadius: 6,
|
|
96
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.15)",
|
|
97
|
+
font: "12px system-ui, sans-serif",
|
|
98
|
+
color: "#18181b",
|
|
99
|
+
...style
|
|
100
|
+
},
|
|
101
|
+
onPointerDown: stop,
|
|
102
|
+
onPointerMove: stop,
|
|
103
|
+
onPointerUp: stop,
|
|
104
|
+
onDoubleClick: stop,
|
|
105
|
+
onCopy: stop,
|
|
106
|
+
onCut: stop,
|
|
107
|
+
onPaste: stop,
|
|
108
|
+
onKeyDown: (e) => {
|
|
109
|
+
e.stopPropagation();
|
|
110
|
+
if (e.key === "Escape") {
|
|
111
|
+
e.preventDefault();
|
|
112
|
+
close();
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
onSubmit: (e) => {
|
|
116
|
+
e.preventDefault();
|
|
117
|
+
apply();
|
|
118
|
+
},
|
|
119
|
+
children: [
|
|
120
|
+
/* @__PURE__ */ jsxs("label", { style: fieldStyle, children: [
|
|
121
|
+
"Position %",
|
|
122
|
+
/* @__PURE__ */ jsx("input", { "aria-label": "Width point position", type: "number", min: 0, max: 100, step: "any", value: position, onChange: (e) => setPosition(e.target.value), style: inputStyle, autoFocus: true })
|
|
123
|
+
] }),
|
|
124
|
+
/* @__PURE__ */ jsxs("label", { style: fieldStyle, children: [
|
|
125
|
+
"Left",
|
|
126
|
+
/* @__PURE__ */ jsx("input", { "aria-label": "Width point left side", type: "number", min: 0, step: "any", value: left, onChange: (e) => setLeft(e.target.value), style: inputStyle })
|
|
127
|
+
] }),
|
|
128
|
+
/* @__PURE__ */ jsxs("label", { style: fieldStyle, children: [
|
|
129
|
+
"Right",
|
|
130
|
+
/* @__PURE__ */ jsx("input", { "aria-label": "Width point right side", type: "number", min: 0, step: "any", value: right, onChange: (e) => setRight(e.target.value), style: inputStyle })
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ jsxs("div", { style: { display: "flex", justifyContent: "flex-end", gap: 4, marginTop: 2 }, children: [
|
|
133
|
+
/* @__PURE__ */ jsx("button", { type: "button", onClick: close, children: "Cancel" }),
|
|
134
|
+
/* @__PURE__ */ jsx("button", { type: "submit", style: { background: accentColor, color: "#ffffff", border: "none", borderRadius: 4, padding: "2px 8px" }, children: edit.index === null ? "Add" : "Apply" })
|
|
135
|
+
] })
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/vector/VectorCanvas.tsx
|
|
142
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
58
143
|
function VectorGradientDefs({ defs }) {
|
|
59
144
|
if (!defs.length) return null;
|
|
60
|
-
return /* @__PURE__ */
|
|
61
|
-
const stops = def.stops.map((s, i) => /* @__PURE__ */
|
|
62
|
-
return def.type === "radial" ? /* @__PURE__ */
|
|
145
|
+
return /* @__PURE__ */ jsx2("defs", { children: defs.map((def) => {
|
|
146
|
+
const stops = def.stops.map((s, i) => /* @__PURE__ */ jsx2("stop", { offset: s.offset, stopColor: s.stopColor, stopOpacity: s.stopOpacity }, i));
|
|
147
|
+
return def.type === "radial" ? /* @__PURE__ */ jsx2("radialGradient", { id: def.id, ...def.attrs, children: stops }, def.id) : /* @__PURE__ */ jsx2("linearGradient", { id: def.id, ...def.attrs, children: stops }, def.id);
|
|
63
148
|
}) });
|
|
64
149
|
}
|
|
65
150
|
function VectorSceneNodes({ nodes }) {
|
|
66
|
-
return /* @__PURE__ */
|
|
67
|
-
(node) => node.kind === "group" ? /* @__PURE__ */
|
|
151
|
+
return /* @__PURE__ */ jsx2(Fragment, { children: nodes.map(
|
|
152
|
+
(node) => node.kind === "group" ? /* @__PURE__ */ jsx2("g", { "data-vector-id": node.id, transform: node.transform, opacity: node.opacity < 1 ? node.opacity : void 0, children: /* @__PURE__ */ jsx2(VectorSceneNodes, { nodes: node.children }) }, node.id) : node.strokeParts ? /* @__PURE__ */ jsx2(VectorPartedPath, { node }, node.id) : /* @__PURE__ */ jsx2(
|
|
68
153
|
"path",
|
|
69
154
|
{
|
|
70
155
|
"data-vector-id": node.id,
|
|
@@ -87,15 +172,15 @@ function VectorPartedPath({ node }) {
|
|
|
87
172
|
const sp = node.strokeParts;
|
|
88
173
|
const clip = sp.clip;
|
|
89
174
|
const b = clip?.bounds;
|
|
90
|
-
return /* @__PURE__ */
|
|
91
|
-
clip && b && /* @__PURE__ */
|
|
92
|
-
/* @__PURE__ */
|
|
93
|
-
/* @__PURE__ */
|
|
175
|
+
return /* @__PURE__ */ jsxs2("g", { "data-vector-id": node.id, "data-vector-stroke-align": sp.align, transform: node.transform, opacity: node.opacity < 1 ? node.opacity : void 0, children: [
|
|
176
|
+
clip && b && /* @__PURE__ */ jsx2("defs", { children: clip.kind === "clip" ? /* @__PURE__ */ jsx2("clipPath", { id: clip.id, children: /* @__PURE__ */ jsx2("path", { d: node.d, clipRule: node.fillRule }) }) : /* @__PURE__ */ jsxs2("mask", { id: clip.id, maskUnits: "userSpaceOnUse", x: b.x, y: b.y, width: b.width, height: b.height, children: [
|
|
177
|
+
/* @__PURE__ */ jsx2("rect", { x: b.x, y: b.y, width: b.width, height: b.height, fill: "#fff" }),
|
|
178
|
+
/* @__PURE__ */ jsx2("path", { d: node.d, fill: "#000", fillRule: node.fillRule })
|
|
94
179
|
] }) }),
|
|
95
|
-
/* @__PURE__ */
|
|
180
|
+
/* @__PURE__ */ jsx2("path", { "data-vector-part": "fill", d: node.d, fill: node.fill, fillRule: node.fillRule, stroke: "none" }),
|
|
96
181
|
sp.outline !== void 0 ? (
|
|
97
182
|
// A variable-width stroke: its outline, filled.
|
|
98
|
-
/* @__PURE__ */
|
|
183
|
+
/* @__PURE__ */ jsx2(
|
|
99
184
|
"path",
|
|
100
185
|
{
|
|
101
186
|
"data-vector-part": "stroke-outline",
|
|
@@ -105,7 +190,7 @@ function VectorPartedPath({ node }) {
|
|
|
105
190
|
mask: clip?.kind === "mask" ? `url(#${clip.id})` : void 0
|
|
106
191
|
}
|
|
107
192
|
)
|
|
108
|
-
) : /* @__PURE__ */
|
|
193
|
+
) : /* @__PURE__ */ jsx2(
|
|
109
194
|
"path",
|
|
110
195
|
{
|
|
111
196
|
"data-vector-part": "stroke",
|
|
@@ -120,22 +205,22 @@ function VectorPartedPath({ node }) {
|
|
|
120
205
|
mask: clip?.kind === "mask" ? `url(#${clip.id})` : void 0
|
|
121
206
|
}
|
|
122
207
|
),
|
|
123
|
-
sp.heads.map((head, i) => /* @__PURE__ */
|
|
208
|
+
sp.heads.map((head, i) => /* @__PURE__ */ jsx2("path", { "data-vector-part": "head", d: head, fill: node.stroke }, i))
|
|
124
209
|
] });
|
|
125
210
|
}
|
|
126
211
|
function VectorCanvas({
|
|
127
212
|
controller,
|
|
128
213
|
fitOnMount = true,
|
|
129
214
|
checkerboard = true,
|
|
130
|
-
accentColor =
|
|
131
|
-
guideColor =
|
|
215
|
+
accentColor = THEME2.accent,
|
|
216
|
+
guideColor = THEME2.guide,
|
|
132
217
|
className,
|
|
133
218
|
style,
|
|
134
219
|
"aria-label": ariaLabel = "Vector canvas"
|
|
135
220
|
}) {
|
|
136
221
|
const state = useVectorEditorState(controller);
|
|
137
|
-
const svgRef =
|
|
138
|
-
const fitted =
|
|
222
|
+
const svgRef = useRef3(null);
|
|
223
|
+
const fitted = useRef3(!fitOnMount);
|
|
139
224
|
const uid = useId().replace(/:/g, "");
|
|
140
225
|
const scene = getVectorSceneRenderData(state, { idPrefix: `ve${uid}-` });
|
|
141
226
|
const overlay = getVectorOverlayRenderData(state);
|
|
@@ -183,10 +268,12 @@ function VectorCanvas({
|
|
|
183
268
|
event.preventDefault?.();
|
|
184
269
|
}
|
|
185
270
|
};
|
|
186
|
-
const hs =
|
|
187
|
-
const as =
|
|
271
|
+
const hs = THEME2.transformHandleSize;
|
|
272
|
+
const as = THEME2.anchorSize;
|
|
188
273
|
const box = overlay.selectionBox;
|
|
189
|
-
|
|
274
|
+
const edit = state.widthPointEdit;
|
|
275
|
+
const editAt = edit && { x: edit.point.x * state.viewport.zoom + state.viewport.x, y: edit.point.y * state.viewport.zoom + state.viewport.y };
|
|
276
|
+
return /* @__PURE__ */ jsxs2(
|
|
190
277
|
"svg",
|
|
191
278
|
{
|
|
192
279
|
ref: svgRef,
|
|
@@ -218,13 +305,13 @@ function VectorCanvas({
|
|
|
218
305
|
onCut: clipboard("cut"),
|
|
219
306
|
onPaste: clipboard("paste"),
|
|
220
307
|
children: [
|
|
221
|
-
checkerboard && /* @__PURE__ */
|
|
222
|
-
/* @__PURE__ */
|
|
223
|
-
/* @__PURE__ */
|
|
224
|
-
/* @__PURE__ */
|
|
308
|
+
checkerboard && /* @__PURE__ */ jsx2("defs", { children: /* @__PURE__ */ jsxs2("pattern", { id: `ve${uid}-checker`, width: 16, height: 16, patternUnits: "userSpaceOnUse", children: [
|
|
309
|
+
/* @__PURE__ */ jsx2("rect", { width: 16, height: 16, fill: "#ffffff" }),
|
|
310
|
+
/* @__PURE__ */ jsx2("rect", { width: 8, height: 8, fill: "#e5e7eb" }),
|
|
311
|
+
/* @__PURE__ */ jsx2("rect", { x: 8, y: 8, width: 8, height: 8, fill: "#e5e7eb" })
|
|
225
312
|
] }) }),
|
|
226
|
-
/* @__PURE__ */
|
|
227
|
-
/* @__PURE__ */
|
|
313
|
+
/* @__PURE__ */ jsx2(VectorGradientDefs, { defs: scene.defs }),
|
|
314
|
+
/* @__PURE__ */ jsx2(
|
|
228
315
|
"rect",
|
|
229
316
|
{
|
|
230
317
|
"data-vector-artboard": "",
|
|
@@ -236,84 +323,84 @@ function VectorCanvas({
|
|
|
236
323
|
stroke: "rgba(0,0,0,0.12)"
|
|
237
324
|
}
|
|
238
325
|
),
|
|
239
|
-
/* @__PURE__ */
|
|
240
|
-
/* @__PURE__ */
|
|
241
|
-
overlay.outlines.map((o) => /* @__PURE__ */
|
|
242
|
-
overlay.penPreview && /* @__PURE__ */
|
|
243
|
-
box && /* @__PURE__ */
|
|
244
|
-
/* @__PURE__ */
|
|
245
|
-
/* @__PURE__ */
|
|
326
|
+
/* @__PURE__ */ jsx2("g", { "data-vector-scene": "", transform: scene.transform, children: /* @__PURE__ */ jsx2(VectorSceneNodes, { nodes: scene.nodes }) }),
|
|
327
|
+
/* @__PURE__ */ jsxs2("g", { "data-vector-overlay": "", pointerEvents: "none", fill: "none", children: [
|
|
328
|
+
overlay.outlines.map((o) => /* @__PURE__ */ jsx2("path", { d: o.d, stroke: accentColor, strokeWidth: o.selected ? 1 : 1.5, opacity: o.selected ? 1 : 0.7 }, o.id)),
|
|
329
|
+
overlay.penPreview && /* @__PURE__ */ jsx2("path", { d: overlay.penPreview, stroke: accentColor, strokeDasharray: "4 3" }),
|
|
330
|
+
box && /* @__PURE__ */ jsxs2("g", { "data-vector-selection": "", transform: box.transform || void 0, children: [
|
|
331
|
+
/* @__PURE__ */ jsx2("rect", { x: box.x, y: box.y, width: box.width, height: box.height, stroke: accentColor }),
|
|
332
|
+
/* @__PURE__ */ jsx2("line", { x1: box.x + box.width / 2, y1: box.y, x2: box.x + box.width / 2, y2: box.y - 24, stroke: accentColor }),
|
|
246
333
|
box.handles.map(
|
|
247
|
-
(h) => h.handle === "rotate" ? /* @__PURE__ */
|
|
334
|
+
(h) => h.handle === "rotate" ? /* @__PURE__ */ jsx2("circle", { "data-handle": h.handle, cx: h.x, cy: h.y, r: hs / 2 + 1, fill: THEME2.handleFill, stroke: accentColor }, h.handle) : /* @__PURE__ */ jsx2("rect", { "data-handle": h.handle, x: h.x - hs / 2, y: h.y - hs / 2, width: hs, height: hs, fill: THEME2.handleFill, stroke: accentColor }, h.handle)
|
|
248
335
|
)
|
|
249
336
|
] }),
|
|
250
|
-
overlay.handles.map((h) => /* @__PURE__ */
|
|
251
|
-
/* @__PURE__ */
|
|
252
|
-
/* @__PURE__ */
|
|
337
|
+
overlay.handles.map((h) => /* @__PURE__ */ jsxs2("g", { "data-vector-handle": h.ref.handle, children: [
|
|
338
|
+
/* @__PURE__ */ jsx2("line", { x1: h.anchorX, y1: h.anchorY, x2: h.x, y2: h.y, stroke: accentColor }),
|
|
339
|
+
/* @__PURE__ */ jsx2("circle", { cx: h.x, cy: h.y, r: THEME2.handleRadius + (h.hovered ? 1 : 0), fill: THEME2.handleFill, stroke: accentColor })
|
|
253
340
|
] }, `${h.ref.nodeId}:${h.ref.subpath}:${h.ref.index}:${h.ref.handle}`)),
|
|
254
341
|
overlay.anchors.map((a) => {
|
|
255
342
|
const size = as + (a.hovered ? 2 : 0);
|
|
256
|
-
const fill = a.selected ? accentColor :
|
|
343
|
+
const fill = a.selected ? accentColor : THEME2.handleFill;
|
|
257
344
|
const key = `${a.ref.nodeId}:${a.ref.subpath}:${a.ref.index}`;
|
|
258
|
-
return a.type === "corner" ? /* @__PURE__ */
|
|
345
|
+
return a.type === "corner" ? /* @__PURE__ */ jsx2("rect", { "data-vector-anchor": a.ref.index, x: a.x - size / 2, y: a.y - size / 2, width: size, height: size, fill, stroke: accentColor }, key) : /* @__PURE__ */ jsx2("circle", { "data-vector-anchor": a.ref.index, cx: a.x, cy: a.y, r: size / 2, fill, stroke: accentColor }, key);
|
|
259
346
|
}),
|
|
260
|
-
overlay.cornerWidgets.map((w) => /* @__PURE__ */
|
|
261
|
-
/* @__PURE__ */
|
|
262
|
-
/* @__PURE__ */
|
|
347
|
+
overlay.cornerWidgets.map((w) => /* @__PURE__ */ jsxs2("g", { "data-vector-corner-widget": w.ref.index, "data-corner-kind": w.kind, children: [
|
|
348
|
+
/* @__PURE__ */ jsx2("circle", { cx: w.x, cy: w.y, r: THEME2.cornerWidgetRadius + (w.hovered ? 1 : 0), fill: THEME2.handleFill, stroke: accentColor }),
|
|
349
|
+
/* @__PURE__ */ jsx2("circle", { cx: w.x, cy: w.y, r: 1.5, fill: accentColor })
|
|
263
350
|
] }, `corner:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`)),
|
|
264
|
-
overlay.widthSpot && /* @__PURE__ */
|
|
265
|
-
/* @__PURE__ */
|
|
266
|
-
/* @__PURE__ */
|
|
351
|
+
overlay.widthSpot && /* @__PURE__ */ jsxs2("g", { "data-vector-width-spot": "", children: [
|
|
352
|
+
/* @__PURE__ */ jsx2("line", { x1: overlay.widthSpot.left.x, y1: overlay.widthSpot.left.y, x2: overlay.widthSpot.right.x, y2: overlay.widthSpot.right.y, stroke: accentColor, strokeDasharray: "3 2" }),
|
|
353
|
+
/* @__PURE__ */ jsx2("path", { d: vectorDiamondPath(overlay.widthSpot.x, overlay.widthSpot.y), fill: "none", stroke: accentColor })
|
|
267
354
|
] }),
|
|
268
|
-
overlay.widthPoints.map((w) => /* @__PURE__ */
|
|
269
|
-
/* @__PURE__ */
|
|
270
|
-
/* @__PURE__ */
|
|
271
|
-
["left", "right"].map((side) => /* @__PURE__ */
|
|
355
|
+
overlay.widthPoints.map((w) => /* @__PURE__ */ jsxs2("g", { "data-vector-width-point": w.ref.index, "data-selected": w.selected || void 0, children: [
|
|
356
|
+
/* @__PURE__ */ jsx2("line", { x1: w.left.x, y1: w.left.y, x2: w.right.x, y2: w.right.y, stroke: accentColor }),
|
|
357
|
+
/* @__PURE__ */ jsx2("path", { d: vectorDiamondPath(w.x, w.y), fill: w.selected || w.active ? accentColor : THEME2.handleFill, stroke: accentColor, strokeWidth: w.hovered === "center" ? 2 : 1 }),
|
|
358
|
+
["left", "right"].map((side) => /* @__PURE__ */ jsx2("circle", { "data-vector-width-side": side, cx: w[side].x, cy: w[side].y, r: THEME2.handleRadius + (w.hovered === side ? 1 : 0), fill: THEME2.handleFill, stroke: accentColor }, side))
|
|
272
359
|
] }, `width:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`)),
|
|
273
|
-
state.tool === "pen" && overlay.anchors.some((a) => a.closes && a.hovered) && /* @__PURE__ */
|
|
274
|
-
overlay.builder && /* @__PURE__ */
|
|
275
|
-
overlay.builder.faces.map((d, i) => /* @__PURE__ */
|
|
360
|
+
state.tool === "pen" && overlay.anchors.some((a) => a.closes && a.hovered) && /* @__PURE__ */ jsx2("circle", { cx: overlay.anchors.find((a) => a.closes).x, cy: overlay.anchors.find((a) => a.closes).y, r: as, stroke: accentColor }),
|
|
361
|
+
overlay.builder && /* @__PURE__ */ jsxs2("g", { "data-vector-builder": overlay.builder.mode, children: [
|
|
362
|
+
overlay.builder.faces.map((d, i) => /* @__PURE__ */ jsx2(
|
|
276
363
|
"path",
|
|
277
364
|
{
|
|
278
365
|
"data-vector-builder-face": "",
|
|
279
366
|
d,
|
|
280
|
-
fill: overlay.builder.mode === "erase" ?
|
|
367
|
+
fill: overlay.builder.mode === "erase" ? THEME2.builderEraseFill : THEME2.builderFill,
|
|
281
368
|
fillRule: "nonzero",
|
|
282
|
-
stroke: overlay.builder.mode === "erase" ?
|
|
369
|
+
stroke: overlay.builder.mode === "erase" ? THEME2.builderErase : accentColor,
|
|
283
370
|
strokeWidth: 1
|
|
284
371
|
},
|
|
285
372
|
`f${i}`
|
|
286
373
|
)),
|
|
287
374
|
overlay.builder.hatches.map(
|
|
288
|
-
(d, i) => d ? /* @__PURE__ */
|
|
375
|
+
(d, i) => d ? /* @__PURE__ */ jsx2(
|
|
289
376
|
"path",
|
|
290
377
|
{
|
|
291
378
|
"data-vector-builder-hatch": "",
|
|
292
379
|
d,
|
|
293
380
|
fill: "none",
|
|
294
|
-
stroke: overlay.builder.mode === "erase" ?
|
|
295
|
-
strokeOpacity:
|
|
381
|
+
stroke: overlay.builder.mode === "erase" ? THEME2.builderErase : accentColor,
|
|
382
|
+
strokeOpacity: THEME2.builderHatchOpacity,
|
|
296
383
|
strokeWidth: 1
|
|
297
384
|
},
|
|
298
385
|
`h${i}`
|
|
299
386
|
) : null
|
|
300
387
|
),
|
|
301
|
-
overlay.builder.lines.map((d, i) => /* @__PURE__ */
|
|
302
|
-
overlay.builder.trail && /* @__PURE__ */
|
|
388
|
+
overlay.builder.lines.map((d, i) => /* @__PURE__ */ jsx2("path", { "data-vector-builder-line": "", d, fill: "none", stroke: THEME2.builderErase, strokeWidth: 3, strokeLinecap: "round" }, `l${i}`)),
|
|
389
|
+
overlay.builder.trail && /* @__PURE__ */ jsx2("path", { "data-vector-builder-trail": "", d: overlay.builder.trail, fill: "none", stroke: overlay.builder.mode === "erase" ? THEME2.builderErase : accentColor, strokeWidth: 1 })
|
|
303
390
|
] }),
|
|
304
|
-
overlay.toolStroke && /* @__PURE__ */
|
|
391
|
+
overlay.toolStroke && /* @__PURE__ */ jsx2(
|
|
305
392
|
"path",
|
|
306
393
|
{
|
|
307
394
|
"data-vector-tool-stroke": overlay.toolStroke.tool,
|
|
308
395
|
d: overlay.toolStroke.d,
|
|
309
|
-
stroke: overlay.toolStroke.tool === "eraser" ?
|
|
396
|
+
stroke: overlay.toolStroke.tool === "eraser" ? THEME2.eraserFill : accentColor,
|
|
310
397
|
strokeWidth: overlay.toolStroke.tool === "eraser" ? overlay.toolStroke.width : 1,
|
|
311
398
|
strokeLinecap: "round",
|
|
312
399
|
strokeLinejoin: "round",
|
|
313
400
|
strokeDasharray: overlay.toolStroke.tool === "knife" ? "5 3" : void 0
|
|
314
401
|
}
|
|
315
402
|
),
|
|
316
|
-
overlay.pencilString && /* @__PURE__ */
|
|
403
|
+
overlay.pencilString && /* @__PURE__ */ jsx2(
|
|
317
404
|
"line",
|
|
318
405
|
{
|
|
319
406
|
"data-vector-pencil-string": "",
|
|
@@ -325,8 +412,8 @@ function VectorCanvas({
|
|
|
325
412
|
strokeDasharray: "2 2"
|
|
326
413
|
}
|
|
327
414
|
),
|
|
328
|
-
overlay.cutPoint && /* @__PURE__ */
|
|
329
|
-
overlay.marquee && /* @__PURE__ */
|
|
415
|
+
overlay.cutPoint && /* @__PURE__ */ jsx2("circle", { "data-vector-cut-point": "", cx: overlay.cutPoint.x, cy: overlay.cutPoint.y, r: THEME2.handleRadius + 1, fill: THEME2.handleFill, stroke: accentColor }),
|
|
416
|
+
overlay.marquee && /* @__PURE__ */ jsx2(
|
|
330
417
|
"rect",
|
|
331
418
|
{
|
|
332
419
|
"data-vector-marquee": "",
|
|
@@ -334,13 +421,13 @@ function VectorCanvas({
|
|
|
334
421
|
y: overlay.marquee.y,
|
|
335
422
|
width: overlay.marquee.width,
|
|
336
423
|
height: overlay.marquee.height,
|
|
337
|
-
fill:
|
|
424
|
+
fill: THEME2.marqueeFill,
|
|
338
425
|
stroke: accentColor,
|
|
339
426
|
strokeDasharray: "3 2"
|
|
340
427
|
}
|
|
341
428
|
),
|
|
342
|
-
overlay.guides.lines.length > 0 && /* @__PURE__ */
|
|
343
|
-
overlay.guides.labels.map((l, i) => /* @__PURE__ */
|
|
429
|
+
overlay.guides.lines.length > 0 && /* @__PURE__ */ jsx2("g", { "data-vector-guides": "", stroke: guideColor, children: overlay.guides.lines.map((l, i) => /* @__PURE__ */ jsx2("line", { "data-vector-guide": l.kind, x1: l.x1, y1: l.y1, x2: l.x2, y2: l.y2, strokeDasharray: l.kind === "construction" ? "4 3" : void 0 }, i)) }),
|
|
430
|
+
overlay.guides.labels.map((l, i) => /* @__PURE__ */ jsx2(
|
|
344
431
|
"text",
|
|
345
432
|
{
|
|
346
433
|
"data-vector-guide-label": l.kind,
|
|
@@ -356,8 +443,10 @@ function VectorCanvas({
|
|
|
356
443
|
},
|
|
357
444
|
i
|
|
358
445
|
)),
|
|
359
|
-
overlay.status && /* @__PURE__ */
|
|
360
|
-
] })
|
|
446
|
+
overlay.status && /* @__PURE__ */ jsx2("text", { "data-vector-status": "", x: 8, y: "100%", dy: -8, fontSize: 11, fill: accentColor, style: { fontFamily: "system-ui, sans-serif" }, children: overlay.status })
|
|
447
|
+
] }),
|
|
448
|
+
edit && editAt && // Width Point Edit (double-click with the width tool), beside the point.
|
|
449
|
+
/* @__PURE__ */ jsx2("foreignObject", { "data-vector-width-point-edit": "", x: editAt.x + 12, y: editAt.y + 12, width: 180, height: 140, style: { overflow: "visible" }, children: /* @__PURE__ */ jsx2(VectorWidthPointEditor, { controller, edit, accentColor }, `${edit.nodeId}:${edit.index}:${edit.t}`) })
|
|
361
450
|
]
|
|
362
451
|
}
|
|
363
452
|
);
|
|
@@ -384,7 +473,7 @@ import {
|
|
|
384
473
|
vectorPaintToHex,
|
|
385
474
|
vectorToolLabel
|
|
386
475
|
} from "@pixerate/editor/vector";
|
|
387
|
-
import { Fragment as Fragment2, jsx as
|
|
476
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
388
477
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
389
478
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
390
479
|
var buttonClass = "inline-flex h-8 min-w-8 items-center justify-center rounded-md border border-border bg-background px-2 text-xs font-medium text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40 aria-pressed:bg-primary aria-pressed:text-primary-foreground";
|
|
@@ -394,9 +483,9 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
394
483
|
const points = state.tool === "direct" ? state.selectedAnchors.length : 0;
|
|
395
484
|
const editing = state.editing;
|
|
396
485
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
397
|
-
const act = (label, title, run, disabled = false) => /* @__PURE__ */
|
|
398
|
-
return /* @__PURE__ */
|
|
399
|
-
/* @__PURE__ */
|
|
486
|
+
const act = (label, title, run, disabled = false) => /* @__PURE__ */ jsx3("button", { type: "button", className: buttonClass, title, "aria-label": title, disabled, onClick: () => void run(), children: label }, label);
|
|
487
|
+
return /* @__PURE__ */ jsxs3("div", { role: "toolbar", "aria-label": "Vector tools", className: `flex flex-wrap items-center gap-1 ${className ?? ""}`, children: [
|
|
488
|
+
/* @__PURE__ */ jsx3("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Tools", children: tools.map((tool) => /* @__PURE__ */ jsx3(
|
|
400
489
|
"button",
|
|
401
490
|
{
|
|
402
491
|
type: "button",
|
|
@@ -410,11 +499,11 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
410
499
|
},
|
|
411
500
|
tool
|
|
412
501
|
)) }),
|
|
413
|
-
showHistory && /* @__PURE__ */
|
|
502
|
+
showHistory && /* @__PURE__ */ jsxs3("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "History", children: [
|
|
414
503
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
415
504
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
416
505
|
] }),
|
|
417
|
-
showSnap && /* @__PURE__ */
|
|
506
|
+
showSnap && /* @__PURE__ */ jsx3("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Snapping", children: /* @__PURE__ */ jsx3(
|
|
418
507
|
"button",
|
|
419
508
|
{
|
|
420
509
|
type: "button",
|
|
@@ -427,8 +516,8 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
427
516
|
children: "Snap"
|
|
428
517
|
}
|
|
429
518
|
) }),
|
|
430
|
-
showPathEdit && /* @__PURE__ */
|
|
431
|
-
VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */
|
|
519
|
+
showPathEdit && /* @__PURE__ */ jsxs3("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Path editing", children: [
|
|
520
|
+
VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */ jsx3(
|
|
432
521
|
"button",
|
|
433
522
|
{
|
|
434
523
|
type: "button",
|
|
@@ -442,7 +531,7 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
442
531
|
},
|
|
443
532
|
a.id
|
|
444
533
|
)),
|
|
445
|
-
VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */
|
|
534
|
+
VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ jsx3(
|
|
446
535
|
"button",
|
|
447
536
|
{
|
|
448
537
|
type: "button",
|
|
@@ -456,9 +545,9 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
456
545
|
},
|
|
457
546
|
t.key
|
|
458
547
|
)),
|
|
459
|
-
state.tool === "pencil" && /* @__PURE__ */
|
|
548
|
+
state.tool === "pencil" && /* @__PURE__ */ jsxs3("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
460
549
|
"Smoothing",
|
|
461
|
-
/* @__PURE__ */
|
|
550
|
+
/* @__PURE__ */ jsx3(
|
|
462
551
|
"input",
|
|
463
552
|
{
|
|
464
553
|
type: "range",
|
|
@@ -472,9 +561,9 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
472
561
|
}
|
|
473
562
|
)
|
|
474
563
|
] }),
|
|
475
|
-
state.tool === "eraser" && /* @__PURE__ */
|
|
564
|
+
state.tool === "eraser" && /* @__PURE__ */ jsxs3("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
476
565
|
"Size",
|
|
477
|
-
/* @__PURE__ */
|
|
566
|
+
/* @__PURE__ */ jsx3(
|
|
478
567
|
"input",
|
|
479
568
|
{
|
|
480
569
|
type: "number",
|
|
@@ -490,7 +579,7 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
490
579
|
}
|
|
491
580
|
)
|
|
492
581
|
] }),
|
|
493
|
-
state.tool === "paintBucket" && /* @__PURE__ */
|
|
582
|
+
state.tool === "paintBucket" && /* @__PURE__ */ jsx3(
|
|
494
583
|
"button",
|
|
495
584
|
{
|
|
496
585
|
type: "button",
|
|
@@ -504,8 +593,8 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
504
593
|
}
|
|
505
594
|
)
|
|
506
595
|
] }),
|
|
507
|
-
showArrange && /* @__PURE__ */
|
|
508
|
-
/* @__PURE__ */
|
|
596
|
+
showArrange && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
597
|
+
/* @__PURE__ */ jsxs3("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
|
|
509
598
|
act("\u222A", "Union", () => controller.booleanOp("union"), count < 2),
|
|
510
599
|
act("\u2212", "Subtract", () => controller.booleanOp("subtract"), count < 2),
|
|
511
600
|
act("\u2229", "Intersect", () => controller.booleanOp("intersect"), count < 2),
|
|
@@ -513,7 +602,7 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
513
602
|
act("G", "Group", () => controller.group(), count < 1),
|
|
514
603
|
act("U", "Ungroup", () => controller.ungroup(), !groupSelected)
|
|
515
604
|
] }),
|
|
516
|
-
/* @__PURE__ */
|
|
605
|
+
/* @__PURE__ */ jsx3("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ jsx3(
|
|
517
606
|
"button",
|
|
518
607
|
{
|
|
519
608
|
type: "button",
|
|
@@ -527,7 +616,7 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
527
616
|
},
|
|
528
617
|
a.id
|
|
529
618
|
)) }),
|
|
530
|
-
/* @__PURE__ */
|
|
619
|
+
/* @__PURE__ */ jsxs3("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
531
620
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
532
621
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
533
622
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -572,17 +661,17 @@ function VectorStylePanel({ controller, className }) {
|
|
|
572
661
|
if (style) controller.setWidthProfile(id);
|
|
573
662
|
else controller.setDefaults({ strokeWidthProfile: widthProfilePreset(id)?.length ? widthProfilePreset(id) : null });
|
|
574
663
|
};
|
|
575
|
-
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */
|
|
664
|
+
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ jsx3("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
|
|
576
665
|
const arrowRow = (end, label) => {
|
|
577
666
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
578
667
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
579
|
-
return /* @__PURE__ */
|
|
580
|
-
/* @__PURE__ */
|
|
581
|
-
/* @__PURE__ */
|
|
582
|
-
/* @__PURE__ */
|
|
583
|
-
VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */
|
|
668
|
+
return /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
669
|
+
/* @__PURE__ */ jsx3("span", { className: "w-16 text-xs text-foreground", children: label }),
|
|
670
|
+
/* @__PURE__ */ jsxs3("select", { "aria-label": `${label} arrowhead`, className: selectClass, value: source[key] ?? "", onChange: (e) => apply({ [key]: e.target.value || null }), children: [
|
|
671
|
+
/* @__PURE__ */ jsx3("option", { value: "", children: "None" }),
|
|
672
|
+
VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */ jsx3("option", { value: h, children: VECTOR_ARROWHEAD_LABELS[h] }, h))
|
|
584
673
|
] }),
|
|
585
|
-
/* @__PURE__ */
|
|
674
|
+
/* @__PURE__ */ jsx3(
|
|
586
675
|
"input",
|
|
587
676
|
{
|
|
588
677
|
type: "number",
|
|
@@ -608,12 +697,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
608
697
|
const paint = source[key];
|
|
609
698
|
const hex = vectorPaintToHex(paint);
|
|
610
699
|
const on = paint !== null && paint !== "none";
|
|
611
|
-
return /* @__PURE__ */
|
|
612
|
-
/* @__PURE__ */
|
|
613
|
-
/* @__PURE__ */
|
|
700
|
+
return /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
701
|
+
/* @__PURE__ */ jsxs3("label", { className: "flex w-16 items-center gap-1.5 text-xs text-foreground", children: [
|
|
702
|
+
/* @__PURE__ */ jsx3("input", { type: "checkbox", checked: on, "aria-label": `${label} on`, onChange: (e) => apply({ [key]: e.target.checked ? hex ?? "#000000" : null }) }),
|
|
614
703
|
label
|
|
615
704
|
] }),
|
|
616
|
-
/* @__PURE__ */
|
|
705
|
+
/* @__PURE__ */ jsx3(
|
|
617
706
|
"input",
|
|
618
707
|
{
|
|
619
708
|
type: "color",
|
|
@@ -624,17 +713,17 @@ function VectorStylePanel({ controller, className }) {
|
|
|
624
713
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
625
714
|
}
|
|
626
715
|
),
|
|
627
|
-
on && !hex && /* @__PURE__ */
|
|
628
|
-
style?.mixed[key] && /* @__PURE__ */
|
|
716
|
+
on && !hex && /* @__PURE__ */ jsx3("span", { className: "truncate text-[11px] text-muted-foreground", children: typeof paint === "string" ? paint : "Gradient" }),
|
|
717
|
+
style?.mixed[key] && /* @__PURE__ */ jsx3("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
629
718
|
] });
|
|
630
719
|
};
|
|
631
|
-
return /* @__PURE__ */
|
|
632
|
-
/* @__PURE__ */
|
|
720
|
+
return /* @__PURE__ */ jsxs3("div", { className: `space-y-2 ${className ?? ""}`, "aria-label": style ? "Selection style" : "New shape style", children: [
|
|
721
|
+
/* @__PURE__ */ jsx3("p", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: style ? "Selection" : "New shapes" }),
|
|
633
722
|
paintRow("fill", "Fill"),
|
|
634
723
|
paintRow("stroke", "Stroke"),
|
|
635
|
-
/* @__PURE__ */
|
|
636
|
-
/* @__PURE__ */
|
|
637
|
-
/* @__PURE__ */
|
|
724
|
+
/* @__PURE__ */ jsxs3("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
725
|
+
/* @__PURE__ */ jsx3("span", { className: "w-16", children: "Width" }),
|
|
726
|
+
/* @__PURE__ */ jsx3(
|
|
638
727
|
"input",
|
|
639
728
|
{
|
|
640
729
|
type: "number",
|
|
@@ -650,14 +739,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
650
739
|
}
|
|
651
740
|
)
|
|
652
741
|
] }),
|
|
653
|
-
/* @__PURE__ */
|
|
654
|
-
/* @__PURE__ */
|
|
655
|
-
/* @__PURE__ */
|
|
742
|
+
/* @__PURE__ */ jsxs3("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "strokeAlign", children: [
|
|
743
|
+
/* @__PURE__ */ jsx3("span", { className: "w-16", children: "Align" }),
|
|
744
|
+
/* @__PURE__ */ jsx3("select", { "aria-label": "Stroke alignment", className: selectClass, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(VECTOR_STROKE_ALIGN_LABELS).map((a) => /* @__PURE__ */ jsx3("option", { value: a, children: VECTOR_STROKE_ALIGN_LABELS[a] }, a)) }),
|
|
656
745
|
mixed("strokeAlign")
|
|
657
746
|
] }),
|
|
658
|
-
/* @__PURE__ */
|
|
659
|
-
/* @__PURE__ */
|
|
660
|
-
/* @__PURE__ */
|
|
747
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
|
|
748
|
+
/* @__PURE__ */ jsx3("span", { className: "w-16", children: "Profile" }),
|
|
749
|
+
/* @__PURE__ */ jsxs3(
|
|
661
750
|
"select",
|
|
662
751
|
{
|
|
663
752
|
"aria-label": "Width profile",
|
|
@@ -667,12 +756,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
667
756
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
668
757
|
},
|
|
669
758
|
children: [
|
|
670
|
-
VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */
|
|
671
|
-
source.widthProfile === "custom" && /* @__PURE__ */
|
|
759
|
+
VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ jsx3("option", { value: p.id, children: p.label }, p.id)),
|
|
760
|
+
source.widthProfile === "custom" && /* @__PURE__ */ jsx3("option", { value: "custom", disabled: true, children: "Custom" })
|
|
672
761
|
]
|
|
673
762
|
}
|
|
674
763
|
),
|
|
675
|
-
/* @__PURE__ */
|
|
764
|
+
/* @__PURE__ */ jsx3(
|
|
676
765
|
"button",
|
|
677
766
|
{
|
|
678
767
|
type: "button",
|
|
@@ -686,20 +775,20 @@ function VectorStylePanel({ controller, className }) {
|
|
|
686
775
|
),
|
|
687
776
|
mixed("widthProfile")
|
|
688
777
|
] }),
|
|
689
|
-
source.hasOpenPath && /* @__PURE__ */
|
|
778
|
+
source.hasOpenPath && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
690
779
|
arrowRow("start", "Start"),
|
|
691
780
|
arrowRow("end", "End"),
|
|
692
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */
|
|
693
|
-
/* @__PURE__ */
|
|
694
|
-
/* @__PURE__ */
|
|
695
|
-
/* @__PURE__ */
|
|
696
|
-
/* @__PURE__ */
|
|
781
|
+
(source.startArrow || source.endArrow) && /* @__PURE__ */ jsxs3("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "arrowAlign", children: [
|
|
782
|
+
/* @__PURE__ */ jsx3("span", { className: "w-16", children: "Heads" }),
|
|
783
|
+
/* @__PURE__ */ jsxs3("select", { "aria-label": "Arrowhead alignment", className: selectClass, value: source.arrowAlign, onChange: (e) => apply({ arrowAlign: e.target.value }), children: [
|
|
784
|
+
/* @__PURE__ */ jsx3("option", { value: "extend", children: "Tip past end" }),
|
|
785
|
+
/* @__PURE__ */ jsx3("option", { value: "tip", children: "Tip at end" })
|
|
697
786
|
] })
|
|
698
787
|
] })
|
|
699
788
|
] }),
|
|
700
|
-
source.corners > 0 && /* @__PURE__ */
|
|
701
|
-
/* @__PURE__ */
|
|
702
|
-
/* @__PURE__ */
|
|
789
|
+
source.corners > 0 && /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", "data-vector-style": "corners", children: [
|
|
790
|
+
/* @__PURE__ */ jsx3("span", { className: "w-16 text-xs text-foreground", children: "Corners" }),
|
|
791
|
+
/* @__PURE__ */ jsx3(
|
|
703
792
|
"input",
|
|
704
793
|
{
|
|
705
794
|
type: "number",
|
|
@@ -714,12 +803,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
714
803
|
}
|
|
715
804
|
}
|
|
716
805
|
),
|
|
717
|
-
/* @__PURE__ */
|
|
806
|
+
/* @__PURE__ */ jsx3("select", { "aria-label": "Corner kind", className: selectClass, value: source.cornerKind, onChange: (e) => setCorners({ kind: e.target.value }), children: VECTOR_CORNER_KINDS.map((k) => /* @__PURE__ */ jsx3("option", { value: k, children: VECTOR_CORNER_KIND_LABELS[k] }, k)) }),
|
|
718
807
|
mixed("cornerRadius")
|
|
719
808
|
] }),
|
|
720
|
-
style && /* @__PURE__ */
|
|
721
|
-
/* @__PURE__ */
|
|
722
|
-
/* @__PURE__ */
|
|
809
|
+
style && /* @__PURE__ */ jsxs3("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
810
|
+
/* @__PURE__ */ jsx3("span", { className: "w-16", children: "Opacity" }),
|
|
811
|
+
/* @__PURE__ */ jsx3(
|
|
723
812
|
"input",
|
|
724
813
|
{
|
|
725
814
|
type: "range",
|
|
@@ -737,13 +826,13 @@ function VectorStylePanel({ controller, className }) {
|
|
|
737
826
|
}
|
|
738
827
|
|
|
739
828
|
// src/vector/VectorEditor.tsx
|
|
740
|
-
import { jsx as
|
|
829
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
741
830
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }) {
|
|
742
|
-
return /* @__PURE__ */
|
|
743
|
-
/* @__PURE__ */
|
|
744
|
-
/* @__PURE__ */
|
|
745
|
-
/* @__PURE__ */
|
|
746
|
-
showStylePanel && /* @__PURE__ */
|
|
831
|
+
return /* @__PURE__ */ jsxs4("div", { className: `flex flex-col gap-2 ${className ?? ""}`, "data-vector-editor": "", children: [
|
|
832
|
+
/* @__PURE__ */ jsx4(VectorToolbar, { controller, tools }),
|
|
833
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex min-h-0 flex-col gap-2 md:flex-row", children: [
|
|
834
|
+
/* @__PURE__ */ jsx4("div", { className: "relative min-h-[320px] flex-1 overflow-hidden rounded-md border border-border bg-muted/40", style: { height }, children: /* @__PURE__ */ jsx4(VectorCanvas, { controller, ...canvasProps }) }),
|
|
835
|
+
showStylePanel && /* @__PURE__ */ jsx4(VectorStylePanel, { controller, className: "w-full shrink-0 rounded-md border border-border p-3 md:w-56" })
|
|
747
836
|
] })
|
|
748
837
|
] });
|
|
749
838
|
}
|
|
@@ -754,6 +843,7 @@ export {
|
|
|
754
843
|
VectorSceneNodes,
|
|
755
844
|
VectorStylePanel,
|
|
756
845
|
VectorToolbar,
|
|
846
|
+
VectorWidthPointEditor,
|
|
757
847
|
useVectorCommands,
|
|
758
848
|
useVectorEditor,
|
|
759
849
|
useVectorEditorController,
|