@pixerate/editor-react 0.28.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 +257 -152
- 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 +237 -133
- 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,70 +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
|
-
overlay.builder.
|
|
288
|
-
|
|
374
|
+
overlay.builder.hatches.map(
|
|
375
|
+
(d, i) => d ? /* @__PURE__ */ jsx2(
|
|
376
|
+
"path",
|
|
377
|
+
{
|
|
378
|
+
"data-vector-builder-hatch": "",
|
|
379
|
+
d,
|
|
380
|
+
fill: "none",
|
|
381
|
+
stroke: overlay.builder.mode === "erase" ? THEME2.builderErase : accentColor,
|
|
382
|
+
strokeOpacity: THEME2.builderHatchOpacity,
|
|
383
|
+
strokeWidth: 1
|
|
384
|
+
},
|
|
385
|
+
`h${i}`
|
|
386
|
+
) : null
|
|
387
|
+
),
|
|
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 })
|
|
289
390
|
] }),
|
|
290
|
-
overlay.toolStroke && /* @__PURE__ */
|
|
391
|
+
overlay.toolStroke && /* @__PURE__ */ jsx2(
|
|
291
392
|
"path",
|
|
292
393
|
{
|
|
293
394
|
"data-vector-tool-stroke": overlay.toolStroke.tool,
|
|
294
395
|
d: overlay.toolStroke.d,
|
|
295
|
-
stroke: overlay.toolStroke.tool === "eraser" ?
|
|
396
|
+
stroke: overlay.toolStroke.tool === "eraser" ? THEME2.eraserFill : accentColor,
|
|
296
397
|
strokeWidth: overlay.toolStroke.tool === "eraser" ? overlay.toolStroke.width : 1,
|
|
297
398
|
strokeLinecap: "round",
|
|
298
399
|
strokeLinejoin: "round",
|
|
299
400
|
strokeDasharray: overlay.toolStroke.tool === "knife" ? "5 3" : void 0
|
|
300
401
|
}
|
|
301
402
|
),
|
|
302
|
-
overlay.pencilString && /* @__PURE__ */
|
|
403
|
+
overlay.pencilString && /* @__PURE__ */ jsx2(
|
|
303
404
|
"line",
|
|
304
405
|
{
|
|
305
406
|
"data-vector-pencil-string": "",
|
|
@@ -311,8 +412,8 @@ function VectorCanvas({
|
|
|
311
412
|
strokeDasharray: "2 2"
|
|
312
413
|
}
|
|
313
414
|
),
|
|
314
|
-
overlay.cutPoint && /* @__PURE__ */
|
|
315
|
-
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(
|
|
316
417
|
"rect",
|
|
317
418
|
{
|
|
318
419
|
"data-vector-marquee": "",
|
|
@@ -320,13 +421,13 @@ function VectorCanvas({
|
|
|
320
421
|
y: overlay.marquee.y,
|
|
321
422
|
width: overlay.marquee.width,
|
|
322
423
|
height: overlay.marquee.height,
|
|
323
|
-
fill:
|
|
424
|
+
fill: THEME2.marqueeFill,
|
|
324
425
|
stroke: accentColor,
|
|
325
426
|
strokeDasharray: "3 2"
|
|
326
427
|
}
|
|
327
428
|
),
|
|
328
|
-
overlay.guides.lines.length > 0 && /* @__PURE__ */
|
|
329
|
-
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(
|
|
330
431
|
"text",
|
|
331
432
|
{
|
|
332
433
|
"data-vector-guide-label": l.kind,
|
|
@@ -342,8 +443,10 @@ function VectorCanvas({
|
|
|
342
443
|
},
|
|
343
444
|
i
|
|
344
445
|
)),
|
|
345
|
-
overlay.status && /* @__PURE__ */
|
|
346
|
-
] })
|
|
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}`) })
|
|
347
450
|
]
|
|
348
451
|
}
|
|
349
452
|
);
|
|
@@ -370,7 +473,7 @@ import {
|
|
|
370
473
|
vectorPaintToHex,
|
|
371
474
|
vectorToolLabel
|
|
372
475
|
} from "@pixerate/editor/vector";
|
|
373
|
-
import { Fragment as Fragment2, jsx as
|
|
476
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
374
477
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
375
478
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
376
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";
|
|
@@ -380,9 +483,9 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
380
483
|
const points = state.tool === "direct" ? state.selectedAnchors.length : 0;
|
|
381
484
|
const editing = state.editing;
|
|
382
485
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
383
|
-
const act = (label, title, run, disabled = false) => /* @__PURE__ */
|
|
384
|
-
return /* @__PURE__ */
|
|
385
|
-
/* @__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(
|
|
386
489
|
"button",
|
|
387
490
|
{
|
|
388
491
|
type: "button",
|
|
@@ -396,11 +499,11 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
396
499
|
},
|
|
397
500
|
tool
|
|
398
501
|
)) }),
|
|
399
|
-
showHistory && /* @__PURE__ */
|
|
502
|
+
showHistory && /* @__PURE__ */ jsxs3("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "History", children: [
|
|
400
503
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
401
504
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
402
505
|
] }),
|
|
403
|
-
showSnap && /* @__PURE__ */
|
|
506
|
+
showSnap && /* @__PURE__ */ jsx3("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Snapping", children: /* @__PURE__ */ jsx3(
|
|
404
507
|
"button",
|
|
405
508
|
{
|
|
406
509
|
type: "button",
|
|
@@ -413,8 +516,8 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
413
516
|
children: "Snap"
|
|
414
517
|
}
|
|
415
518
|
) }),
|
|
416
|
-
showPathEdit && /* @__PURE__ */
|
|
417
|
-
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(
|
|
418
521
|
"button",
|
|
419
522
|
{
|
|
420
523
|
type: "button",
|
|
@@ -428,7 +531,7 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
428
531
|
},
|
|
429
532
|
a.id
|
|
430
533
|
)),
|
|
431
|
-
VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */
|
|
534
|
+
VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ jsx3(
|
|
432
535
|
"button",
|
|
433
536
|
{
|
|
434
537
|
type: "button",
|
|
@@ -442,9 +545,9 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
442
545
|
},
|
|
443
546
|
t.key
|
|
444
547
|
)),
|
|
445
|
-
state.tool === "pencil" && /* @__PURE__ */
|
|
548
|
+
state.tool === "pencil" && /* @__PURE__ */ jsxs3("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
446
549
|
"Smoothing",
|
|
447
|
-
/* @__PURE__ */
|
|
550
|
+
/* @__PURE__ */ jsx3(
|
|
448
551
|
"input",
|
|
449
552
|
{
|
|
450
553
|
type: "range",
|
|
@@ -458,9 +561,9 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
458
561
|
}
|
|
459
562
|
)
|
|
460
563
|
] }),
|
|
461
|
-
state.tool === "eraser" && /* @__PURE__ */
|
|
564
|
+
state.tool === "eraser" && /* @__PURE__ */ jsxs3("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
462
565
|
"Size",
|
|
463
|
-
/* @__PURE__ */
|
|
566
|
+
/* @__PURE__ */ jsx3(
|
|
464
567
|
"input",
|
|
465
568
|
{
|
|
466
569
|
type: "number",
|
|
@@ -476,7 +579,7 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
476
579
|
}
|
|
477
580
|
)
|
|
478
581
|
] }),
|
|
479
|
-
state.tool === "paintBucket" && /* @__PURE__ */
|
|
582
|
+
state.tool === "paintBucket" && /* @__PURE__ */ jsx3(
|
|
480
583
|
"button",
|
|
481
584
|
{
|
|
482
585
|
type: "button",
|
|
@@ -490,8 +593,8 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
490
593
|
}
|
|
491
594
|
)
|
|
492
595
|
] }),
|
|
493
|
-
showArrange && /* @__PURE__ */
|
|
494
|
-
/* @__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: [
|
|
495
598
|
act("\u222A", "Union", () => controller.booleanOp("union"), count < 2),
|
|
496
599
|
act("\u2212", "Subtract", () => controller.booleanOp("subtract"), count < 2),
|
|
497
600
|
act("\u2229", "Intersect", () => controller.booleanOp("intersect"), count < 2),
|
|
@@ -499,7 +602,7 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
499
602
|
act("G", "Group", () => controller.group(), count < 1),
|
|
500
603
|
act("U", "Ungroup", () => controller.ungroup(), !groupSelected)
|
|
501
604
|
] }),
|
|
502
|
-
/* @__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(
|
|
503
606
|
"button",
|
|
504
607
|
{
|
|
505
608
|
type: "button",
|
|
@@ -513,7 +616,7 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
|
|
|
513
616
|
},
|
|
514
617
|
a.id
|
|
515
618
|
)) }),
|
|
516
|
-
/* @__PURE__ */
|
|
619
|
+
/* @__PURE__ */ jsxs3("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
517
620
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
518
621
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
519
622
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -558,17 +661,17 @@ function VectorStylePanel({ controller, className }) {
|
|
|
558
661
|
if (style) controller.setWidthProfile(id);
|
|
559
662
|
else controller.setDefaults({ strokeWidthProfile: widthProfilePreset(id)?.length ? widthProfilePreset(id) : null });
|
|
560
663
|
};
|
|
561
|
-
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;
|
|
562
665
|
const arrowRow = (end, label) => {
|
|
563
666
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
564
667
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
565
|
-
return /* @__PURE__ */
|
|
566
|
-
/* @__PURE__ */
|
|
567
|
-
/* @__PURE__ */
|
|
568
|
-
/* @__PURE__ */
|
|
569
|
-
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))
|
|
570
673
|
] }),
|
|
571
|
-
/* @__PURE__ */
|
|
674
|
+
/* @__PURE__ */ jsx3(
|
|
572
675
|
"input",
|
|
573
676
|
{
|
|
574
677
|
type: "number",
|
|
@@ -594,12 +697,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
594
697
|
const paint = source[key];
|
|
595
698
|
const hex = vectorPaintToHex(paint);
|
|
596
699
|
const on = paint !== null && paint !== "none";
|
|
597
|
-
return /* @__PURE__ */
|
|
598
|
-
/* @__PURE__ */
|
|
599
|
-
/* @__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 }) }),
|
|
600
703
|
label
|
|
601
704
|
] }),
|
|
602
|
-
/* @__PURE__ */
|
|
705
|
+
/* @__PURE__ */ jsx3(
|
|
603
706
|
"input",
|
|
604
707
|
{
|
|
605
708
|
type: "color",
|
|
@@ -610,17 +713,17 @@ function VectorStylePanel({ controller, className }) {
|
|
|
610
713
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
611
714
|
}
|
|
612
715
|
),
|
|
613
|
-
on && !hex && /* @__PURE__ */
|
|
614
|
-
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" })
|
|
615
718
|
] });
|
|
616
719
|
};
|
|
617
|
-
return /* @__PURE__ */
|
|
618
|
-
/* @__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" }),
|
|
619
722
|
paintRow("fill", "Fill"),
|
|
620
723
|
paintRow("stroke", "Stroke"),
|
|
621
|
-
/* @__PURE__ */
|
|
622
|
-
/* @__PURE__ */
|
|
623
|
-
/* @__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(
|
|
624
727
|
"input",
|
|
625
728
|
{
|
|
626
729
|
type: "number",
|
|
@@ -636,14 +739,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
636
739
|
}
|
|
637
740
|
)
|
|
638
741
|
] }),
|
|
639
|
-
/* @__PURE__ */
|
|
640
|
-
/* @__PURE__ */
|
|
641
|
-
/* @__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)) }),
|
|
642
745
|
mixed("strokeAlign")
|
|
643
746
|
] }),
|
|
644
|
-
/* @__PURE__ */
|
|
645
|
-
/* @__PURE__ */
|
|
646
|
-
/* @__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(
|
|
647
750
|
"select",
|
|
648
751
|
{
|
|
649
752
|
"aria-label": "Width profile",
|
|
@@ -653,12 +756,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
653
756
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
654
757
|
},
|
|
655
758
|
children: [
|
|
656
|
-
VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */
|
|
657
|
-
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" })
|
|
658
761
|
]
|
|
659
762
|
}
|
|
660
763
|
),
|
|
661
|
-
/* @__PURE__ */
|
|
764
|
+
/* @__PURE__ */ jsx3(
|
|
662
765
|
"button",
|
|
663
766
|
{
|
|
664
767
|
type: "button",
|
|
@@ -672,20 +775,20 @@ function VectorStylePanel({ controller, className }) {
|
|
|
672
775
|
),
|
|
673
776
|
mixed("widthProfile")
|
|
674
777
|
] }),
|
|
675
|
-
source.hasOpenPath && /* @__PURE__ */
|
|
778
|
+
source.hasOpenPath && /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
676
779
|
arrowRow("start", "Start"),
|
|
677
780
|
arrowRow("end", "End"),
|
|
678
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */
|
|
679
|
-
/* @__PURE__ */
|
|
680
|
-
/* @__PURE__ */
|
|
681
|
-
/* @__PURE__ */
|
|
682
|
-
/* @__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" })
|
|
683
786
|
] })
|
|
684
787
|
] })
|
|
685
788
|
] }),
|
|
686
|
-
source.corners > 0 && /* @__PURE__ */
|
|
687
|
-
/* @__PURE__ */
|
|
688
|
-
/* @__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(
|
|
689
792
|
"input",
|
|
690
793
|
{
|
|
691
794
|
type: "number",
|
|
@@ -700,12 +803,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
700
803
|
}
|
|
701
804
|
}
|
|
702
805
|
),
|
|
703
|
-
/* @__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)) }),
|
|
704
807
|
mixed("cornerRadius")
|
|
705
808
|
] }),
|
|
706
|
-
style && /* @__PURE__ */
|
|
707
|
-
/* @__PURE__ */
|
|
708
|
-
/* @__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(
|
|
709
812
|
"input",
|
|
710
813
|
{
|
|
711
814
|
type: "range",
|
|
@@ -723,13 +826,13 @@ function VectorStylePanel({ controller, className }) {
|
|
|
723
826
|
}
|
|
724
827
|
|
|
725
828
|
// src/vector/VectorEditor.tsx
|
|
726
|
-
import { jsx as
|
|
829
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
727
830
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }) {
|
|
728
|
-
return /* @__PURE__ */
|
|
729
|
-
/* @__PURE__ */
|
|
730
|
-
/* @__PURE__ */
|
|
731
|
-
/* @__PURE__ */
|
|
732
|
-
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" })
|
|
733
836
|
] })
|
|
734
837
|
] });
|
|
735
838
|
}
|
|
@@ -740,6 +843,7 @@ export {
|
|
|
740
843
|
VectorSceneNodes,
|
|
741
844
|
VectorStylePanel,
|
|
742
845
|
VectorToolbar,
|
|
846
|
+
VectorWidthPointEditor,
|
|
743
847
|
useVectorCommands,
|
|
744
848
|
useVectorEditor,
|
|
745
849
|
useVectorEditorController,
|