@pixerate/editor-react 0.32.0 → 0.34.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 +469 -113
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +39 -6
- package/dist/vector/index.d.ts +39 -6
- package/dist/vector/index.js +465 -101
- package/dist/vector/index.js.map +1 -1
- package/package.json +3 -3
package/dist/vector/index.cjs
CHANGED
|
@@ -33,7 +33,10 @@ __export(vector_exports, {
|
|
|
33
33
|
VectorCanvas: () => VectorCanvas,
|
|
34
34
|
VectorEditor: () => VectorEditor,
|
|
35
35
|
VectorEffectsPanel: () => VectorEffectsPanel,
|
|
36
|
+
VectorEnvelopePanel: () => VectorEnvelopePanel,
|
|
37
|
+
VectorGradientAnnotator: () => VectorGradientAnnotator,
|
|
36
38
|
VectorGradientDefs: () => VectorGradientDefs,
|
|
39
|
+
VectorGradientEditor: () => VectorGradientEditor,
|
|
37
40
|
VectorSceneNodes: () => VectorSceneNodes,
|
|
38
41
|
VectorStylePanel: () => VectorStylePanel,
|
|
39
42
|
VectorToolbar: () => VectorToolbar,
|
|
@@ -176,12 +179,50 @@ function VectorWidthPointEditor({ controller, edit, accentColor = import_vector2
|
|
|
176
179
|
|
|
177
180
|
// src/vector/VectorCanvas.tsx
|
|
178
181
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
182
|
+
function GradientElement({ def }) {
|
|
183
|
+
const stops = def.stops.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("stop", { offset: s.offset, stopColor: s.stopColor, stopOpacity: s.stopOpacity }, i));
|
|
184
|
+
return def.type === "radial" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("radialGradient", { id: def.id, ...def.attrs, children: stops }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("linearGradient", { id: def.id, ...def.attrs, children: stops });
|
|
185
|
+
}
|
|
179
186
|
function VectorGradientDefs({ defs }) {
|
|
180
187
|
if (!defs.length) return null;
|
|
181
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: defs.map(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: defs.map(
|
|
189
|
+
(def) => def.type === "pattern" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("pattern", { id: def.id, ...def.attrs, children: [
|
|
190
|
+
def.gradients.map((g) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GradientElement, { def: g }, g.id)),
|
|
191
|
+
def.tiles.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: t.d, fill: t.fill }, i))
|
|
192
|
+
] }, def.id) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GradientElement, { def }, def.id)
|
|
193
|
+
) });
|
|
194
|
+
}
|
|
195
|
+
function VectorGradientAnnotator({ annotator: g, accentColor = import_vector3.VECTOR_OVERLAY_THEME.accent }) {
|
|
196
|
+
const r = import_vector3.VECTOR_OVERLAY_THEME.handleRadius + 1.5;
|
|
197
|
+
const ring = (p, part, size = r) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { "data-vector-gradient-handle": part, cx: p.x, cy: p.y, r: size + (p.hovered ? 1 : 0), fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor, strokeWidth: p.hovered ? 2 : 1 });
|
|
198
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-gradient-annotator": g.type, children: [
|
|
199
|
+
g.extent && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-gradient-extent": "", d: g.extent, fill: "none", stroke: accentColor, strokeDasharray: "4 3" }),
|
|
200
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: g.start.x, y1: g.start.y, x2: g.end.x, y2: g.end.y, stroke: "#ffffff", strokeWidth: 3 }),
|
|
201
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { "data-vector-gradient-bar": "", x1: g.start.x, y1: g.start.y, x2: g.end.x, y2: g.end.y, stroke: accentColor }),
|
|
202
|
+
g.aspect && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: g.start.x, y1: g.start.y, x2: g.aspect.x, y2: g.aspect.y, stroke: accentColor, strokeDasharray: "2 2" }),
|
|
203
|
+
ring(g.start, "start"),
|
|
204
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
205
|
+
"rect",
|
|
206
|
+
{
|
|
207
|
+
"data-vector-gradient-handle": g.end.handle,
|
|
208
|
+
x: g.end.x - r,
|
|
209
|
+
y: g.end.y - r,
|
|
210
|
+
width: 2 * r,
|
|
211
|
+
height: 2 * r,
|
|
212
|
+
fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill,
|
|
213
|
+
stroke: accentColor,
|
|
214
|
+
strokeWidth: g.end.hovered ? 2 : 1
|
|
215
|
+
}
|
|
216
|
+
),
|
|
217
|
+
g.aspect && ring(g.aspect, "aspect", import_vector3.VECTOR_OVERLAY_THEME.handleRadius),
|
|
218
|
+
g.focal && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { "data-vector-gradient-handle": "focal", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: g.focal.x, cy: g.focal.y, r: import_vector3.VECTOR_OVERLAY_THEME.handleRadius - 1 + (g.focal.hovered ? 1 : 0), fill: accentColor, stroke: import_vector3.VECTOR_OVERLAY_THEME.handleFill }) }),
|
|
219
|
+
g.midpoints.map((m) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-gradient-midpoint": m.index, d: (0, import_vector3.vectorDiamondPath)(m.x, m.y, 4 + (m.hovered ? 1 : 0)), fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor }, m.index)),
|
|
220
|
+
g.stops.map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-gradient-stop": s.index, "data-selected": s.selected || void 0, opacity: g.removing && s.selected ? 0.35 : 1, children: [
|
|
221
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: s.barX, y1: s.barY, x2: s.x, y2: s.y, stroke: accentColor }),
|
|
222
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: s.x - 5, y: s.y - 5, width: 10, height: 10, rx: 2, fill: s.color, fillOpacity: s.opacity, stroke: s.selected ? accentColor : "#ffffff", strokeWidth: s.selected || s.hovered ? 2 : 1 }),
|
|
223
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: s.x - 6.5, y: s.y - 6.5, width: 13, height: 13, rx: 3, fill: "none", stroke: s.selected ? "#ffffff" : accentColor })
|
|
224
|
+
] }, s.index))
|
|
225
|
+
] });
|
|
185
226
|
}
|
|
186
227
|
function VectorSceneNodes({ nodes }) {
|
|
187
228
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: nodes.map(
|
|
@@ -363,13 +404,28 @@ function VectorCanvas({
|
|
|
363
404
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-overlay": "", pointerEvents: "none", fill: "none", children: [
|
|
364
405
|
overlay.outlines.map((o) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: o.d, stroke: accentColor, strokeWidth: o.selected ? 1 : 1.5, opacity: o.selected ? 1 : 0.7 }, o.id)),
|
|
365
406
|
overlay.penPreview && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: overlay.penPreview, stroke: accentColor, strokeDasharray: "4 3" }),
|
|
366
|
-
box && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-selection": "", transform: box.transform || void 0, children: [
|
|
407
|
+
box && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-selection": "", "data-free-distort": box.freeDistort || void 0, transform: box.transform || void 0, children: [
|
|
367
408
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: box.x, y: box.y, width: box.width, height: box.height, stroke: accentColor }),
|
|
368
409
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: box.x + box.width / 2, y1: box.y, x2: box.x + box.width / 2, y2: box.y - 24, stroke: accentColor }),
|
|
369
410
|
box.handles.map(
|
|
370
411
|
(h) => h.handle === "rotate" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { "data-handle": h.handle, cx: h.x, cy: h.y, r: hs / 2 + 1, fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor }, h.handle) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { "data-handle": h.handle, x: h.x - hs / 2, y: h.y - hs / 2, width: hs, height: hs, fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor }, h.handle)
|
|
371
412
|
)
|
|
372
413
|
] }),
|
|
414
|
+
overlay.distort && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-distort": overlay.distort.mode, children: [
|
|
415
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: overlay.distort.d, stroke: accentColor }),
|
|
416
|
+
overlay.distort.corners.map((c, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: c.x - hs / 2, y: c.y - hs / 2, width: hs, height: hs, fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor }, i))
|
|
417
|
+
] }),
|
|
418
|
+
overlay.envelope && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-envelope-mesh": overlay.envelope.nodeId, children: [
|
|
419
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-envelope-grid": "", d: overlay.envelope.grid, stroke: accentColor, strokeOpacity: 0.8 }),
|
|
420
|
+
overlay.envelope.handles.map((h) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-envelope-handle": h.index, children: [
|
|
421
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: h.anchorX, y1: h.anchorY, x2: h.x, y2: h.y, stroke: accentColor, strokeOpacity: 0.6 }),
|
|
422
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: h.x, cy: h.y, r: import_vector3.VECTOR_OVERLAY_THEME.handleRadius + (h.hovered || h.active ? 1 : 0), fill: h.active ? accentColor : import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor })
|
|
423
|
+
] }, h.index)),
|
|
424
|
+
overlay.envelope.anchors.map((a) => {
|
|
425
|
+
const size = as + (a.hovered || a.active ? 2 : 0);
|
|
426
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { "data-vector-envelope-anchor": a.index, x: a.x - size / 2, y: a.y - size / 2, width: size, height: size, fill: a.active ? accentColor : import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor }, a.index);
|
|
427
|
+
})
|
|
428
|
+
] }),
|
|
373
429
|
overlay.handles.map((h) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-handle": h.ref.handle, children: [
|
|
374
430
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: h.anchorX, y1: h.anchorY, x2: h.x, y2: h.y, stroke: accentColor }),
|
|
375
431
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: h.x, cy: h.y, r: import_vector3.VECTOR_OVERLAY_THEME.handleRadius + (h.hovered ? 1 : 0), fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor })
|
|
@@ -405,6 +461,7 @@ function VectorCanvas({
|
|
|
405
461
|
},
|
|
406
462
|
`blend-anchor:${i}`
|
|
407
463
|
)),
|
|
464
|
+
overlay.gradient && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(VectorGradientAnnotator, { annotator: overlay.gradient, accentColor }),
|
|
408
465
|
overlay.widthSpot && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-width-spot": "", children: [
|
|
409
466
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" }),
|
|
410
467
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: (0, import_vector3.vectorDiamondPath)(overlay.widthSpot.x, overlay.widthSpot.y), fill: "none", stroke: accentColor })
|
|
@@ -510,8 +567,8 @@ function VectorCanvas({
|
|
|
510
567
|
}
|
|
511
568
|
|
|
512
569
|
// src/vector/VectorToolbar.tsx
|
|
513
|
-
var
|
|
514
|
-
var
|
|
570
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
571
|
+
var import_vector7 = require("@pixerate/editor/vector");
|
|
515
572
|
|
|
516
573
|
// src/vector/VectorEffectsPanel.tsx
|
|
517
574
|
var import_vector4 = require("@pixerate/editor/vector");
|
|
@@ -653,19 +710,300 @@ function VectorEffectsPanel({ controller, className }) {
|
|
|
653
710
|
] });
|
|
654
711
|
}
|
|
655
712
|
|
|
656
|
-
// src/vector/
|
|
713
|
+
// src/vector/VectorEnvelopePanel.tsx
|
|
714
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
715
|
+
var import_vector5 = require("@pixerate/editor/vector");
|
|
657
716
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
717
|
+
var buttonClass2 = "inline-flex h-7 min-w-7 items-center justify-center rounded-md border border-border bg-background px-1.5 text-xs font-medium text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40";
|
|
718
|
+
var numberClass2 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
719
|
+
var selectClass2 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
720
|
+
var labelClass2 = "w-full truncate text-[11px] text-muted-foreground";
|
|
721
|
+
var SLIDERS = [
|
|
722
|
+
{ key: "bend", label: "Bend %" },
|
|
723
|
+
{ key: "horizontal", label: "Horizontal distortion %" },
|
|
724
|
+
{ key: "vertical", label: "Vertical distortion %" }
|
|
725
|
+
];
|
|
726
|
+
function VectorEnvelopePanel({ controller, className }) {
|
|
727
|
+
const state = useVectorEditorState(controller);
|
|
728
|
+
const panel = (0, import_vector5.getVectorEnvelopePanel)(state);
|
|
729
|
+
const [size, setSize] = import_react4.default.useState({ rows: 2, columns: 2 });
|
|
730
|
+
if (!panel) return null;
|
|
731
|
+
const env = panel.envelope;
|
|
732
|
+
const ids = panel.nodeId ? [panel.nodeId] : void 0;
|
|
733
|
+
const end = () => controller.endMergedEdit();
|
|
734
|
+
const set = (patch, merge = false) => controller.envelope(patch, { ids, merge });
|
|
735
|
+
const rows = env?.params.rows ?? size.rows;
|
|
736
|
+
const columns = env?.params.columns ?? size.columns;
|
|
737
|
+
const setCount = (key, raw) => {
|
|
738
|
+
const n = Math.round(parseFloat(raw));
|
|
739
|
+
if (!Number.isFinite(n) || n < 1 || n > 16) return;
|
|
740
|
+
if (env) set({ [key]: n });
|
|
741
|
+
else setSize({ ...size, [key]: n });
|
|
742
|
+
};
|
|
743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-envelope": "", "aria-label": "Envelope", children: [
|
|
744
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
745
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Envelope" }),
|
|
746
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", "data-vector-envelope-action": "warp", className: buttonClass2, title: "Make with Warp", "aria-label": "Make with Warp", disabled: !panel.canMake || !!env, onClick: () => set({ style: "arc", bend: 50 }), children: "Warp" }),
|
|
747
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
748
|
+
"button",
|
|
749
|
+
{
|
|
750
|
+
type: "button",
|
|
751
|
+
"data-vector-envelope-action": "mesh",
|
|
752
|
+
className: buttonClass2,
|
|
753
|
+
title: "Make with Mesh",
|
|
754
|
+
"aria-label": "Make with Mesh",
|
|
755
|
+
disabled: !panel.canMake || !!env,
|
|
756
|
+
onClick: () => set({ style: "mesh", rows: size.rows, columns: size.columns }),
|
|
757
|
+
children: "Mesh"
|
|
758
|
+
}
|
|
759
|
+
),
|
|
760
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
761
|
+
"button",
|
|
762
|
+
{
|
|
763
|
+
type: "button",
|
|
764
|
+
"data-vector-envelope-action": "top",
|
|
765
|
+
className: buttonClass2,
|
|
766
|
+
title: "Make with Top Object",
|
|
767
|
+
"aria-label": "Make with Top Object",
|
|
768
|
+
disabled: !panel.canMakeWithTopObject,
|
|
769
|
+
onClick: () => controller.makeEnvelopeWithTopObject({ rows: size.rows, columns: size.columns }),
|
|
770
|
+
children: "Top"
|
|
771
|
+
}
|
|
772
|
+
),
|
|
773
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", "data-vector-envelope-action": "release", className: buttonClass2, title: "Release Envelope", "aria-label": "Release Envelope", disabled: !panel.canRelease, onClick: () => controller.releaseEnvelope(), children: "Release" }),
|
|
774
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", "data-vector-envelope-action": "expand", className: buttonClass2, title: "Expand Envelope", "aria-label": "Expand Envelope", disabled: !panel.canRelease, onClick: () => controller.expandAppearance(), children: "Expand" })
|
|
775
|
+
] }),
|
|
776
|
+
env && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-foreground", "data-vector-envelope-param": "style", children: [
|
|
777
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: labelClass2, children: "Warp" }),
|
|
778
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { "aria-label": "Envelope warp", className: selectClass2, value: env.params.style, onChange: (e) => set({ style: e.target.value }), children: import_vector5.VECTOR_ENVELOPE_STYLE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: o.value, children: o.label }, o.value)) })
|
|
779
|
+
] }),
|
|
780
|
+
env && env.params.style !== "mesh" && SLIDERS.map((s) => {
|
|
781
|
+
const value = env.params[s.key];
|
|
782
|
+
const onChange = (ev) => {
|
|
783
|
+
const n = parseFloat(ev.target.value);
|
|
784
|
+
if (Number.isFinite(n)) set({ [s.key]: n }, true);
|
|
785
|
+
};
|
|
786
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-foreground", "data-vector-envelope-param": s.key, children: [
|
|
787
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: labelClass2, children: s.label }),
|
|
788
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
789
|
+
"input",
|
|
790
|
+
{
|
|
791
|
+
type: "range",
|
|
792
|
+
min: -100,
|
|
793
|
+
max: 100,
|
|
794
|
+
step: 1,
|
|
795
|
+
"aria-label": `Envelope ${s.label} slider`,
|
|
796
|
+
className: "h-4 min-w-0 flex-1 accent-primary",
|
|
797
|
+
value,
|
|
798
|
+
onChange,
|
|
799
|
+
onPointerUp: end,
|
|
800
|
+
onKeyUp: end,
|
|
801
|
+
onBlur: end
|
|
802
|
+
}
|
|
803
|
+
),
|
|
804
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "number", min: -100, max: 100, step: 1, "aria-label": `Envelope ${s.label}`, className: numberClass2, value, onChange, onBlur: end })
|
|
805
|
+
] }, s.key);
|
|
806
|
+
}),
|
|
807
|
+
env && env.params.style !== "mesh" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-foreground", "data-vector-envelope-param": "orientation", children: [
|
|
808
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: labelClass2, children: "Orientation" }),
|
|
809
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("select", { "aria-label": "Envelope orientation", className: selectClass2, value: env.params.orientation, onChange: (e) => set({ orientation: e.target.value }), children: [
|
|
810
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "horizontal", children: "Horizontal" }),
|
|
811
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "vertical", children: "Vertical" })
|
|
812
|
+
] })
|
|
813
|
+
] }),
|
|
814
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-envelope-param": "mesh", children: [
|
|
815
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "min-w-0 flex-1 truncate text-[11px] text-muted-foreground", children: "Mesh rows \xD7 columns" }),
|
|
816
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "number", min: 1, max: 16, step: 1, "aria-label": "Envelope mesh rows", className: numberClass2, value: rows, onChange: (e) => setCount("rows", e.target.value) }),
|
|
817
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "number", min: 1, max: 16, step: 1, "aria-label": "Envelope mesh columns", className: numberClass2, value: columns, onChange: (e) => setCount("columns", e.target.value) })
|
|
818
|
+
] }),
|
|
819
|
+
panel.count > 1 && !panel.canMakeWithTopObject && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Select one object to edit its envelope." }),
|
|
820
|
+
env && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Edit the mesh with the Envelope tool (U)." })
|
|
821
|
+
] });
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// src/vector/VectorGradientEditor.tsx
|
|
825
|
+
var import_vector6 = require("@pixerate/editor/vector");
|
|
826
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
827
|
+
var selectClass3 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
828
|
+
var numberClass3 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
829
|
+
var buttonClass3 = "inline-flex h-7 min-w-7 items-center justify-center rounded border border-border bg-background px-1.5 text-xs text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40 aria-pressed:bg-primary aria-pressed:text-primary-foreground";
|
|
830
|
+
var percent = (v) => Math.round(v * 1e3) / 10;
|
|
831
|
+
function VectorGradientEditor({ controller, className }) {
|
|
832
|
+
const state = useVectorEditorState(controller);
|
|
833
|
+
const ed = (0, import_vector6.getVectorGradientEditor)(state);
|
|
834
|
+
if (!ed) return null;
|
|
835
|
+
const g = ed.gradient;
|
|
836
|
+
const sel = ed.selected;
|
|
837
|
+
const end = () => controller.endMergedEdit();
|
|
838
|
+
const setType = (value) => {
|
|
839
|
+
if (value === "solid") {
|
|
840
|
+
const first = ed.stops[0];
|
|
841
|
+
controller.setStyle({ [ed.target]: (0, import_vector6.vectorPaintToHex)(first?.color) ?? first?.color ?? "#000000" }, void 0, { label: "Solid Colour" });
|
|
842
|
+
} else controller.setGradient({ type: value });
|
|
843
|
+
};
|
|
844
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `space-y-1.5 ${className ?? ""}`, "data-vector-gradient-editor": ed.target, "aria-label": "Gradient", children: [
|
|
845
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
846
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Gradient" }),
|
|
847
|
+
["fill", "stroke"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: buttonClass3, "aria-pressed": ed.target === t, onClick: () => controller.setGradientTarget(t), children: t === "fill" ? "Fill" : "Stroke" }, t)),
|
|
848
|
+
ed.mixed && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
849
|
+
] }),
|
|
850
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
851
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Type" }),
|
|
852
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("select", { "aria-label": "Gradient type", className: selectClass3, value: ed.type ?? "solid", onChange: (e) => setType(e.target.value), children: [
|
|
853
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "solid", children: "Solid" }),
|
|
854
|
+
import_vector6.VECTOR_GRADIENT_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: t, children: import_vector6.VECTOR_GRADIENT_TYPE_LABELS[t] }, t))
|
|
855
|
+
] }),
|
|
856
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: buttonClass3, "aria-label": "Reverse gradient", title: "Reverse gradient", disabled: !g, onClick: () => controller.reverseGradient(), children: "\u21C4" })
|
|
857
|
+
] }),
|
|
858
|
+
g && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
859
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative h-8", "data-vector-gradient-ramp": "", children: [
|
|
860
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
861
|
+
"div",
|
|
862
|
+
{
|
|
863
|
+
role: "button",
|
|
864
|
+
tabIndex: -1,
|
|
865
|
+
"aria-label": "Add gradient stop",
|
|
866
|
+
className: "absolute inset-x-1.5 top-0 h-4 cursor-copy rounded border border-border",
|
|
867
|
+
style: { backgroundImage: `${ed.preview}, repeating-conic-gradient(#ddd 0% 25%, #fff 0% 50%)`, backgroundSize: "auto, 8px 8px" },
|
|
868
|
+
onClick: (e) => {
|
|
869
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
870
|
+
controller.addGradientStop(r.width > 0 ? Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) : 0.5);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
),
|
|
874
|
+
ed.stops.map((s) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
875
|
+
"button",
|
|
876
|
+
{
|
|
877
|
+
type: "button",
|
|
878
|
+
"data-vector-gradient-stop": s.index,
|
|
879
|
+
"aria-label": `Gradient stop ${s.index + 1} at ${percent(s.offset)}%`,
|
|
880
|
+
"aria-pressed": s.selected,
|
|
881
|
+
className: "absolute top-4 h-3.5 w-3 -translate-x-1/2 rounded-sm border border-border aria-pressed:ring-2 aria-pressed:ring-primary",
|
|
882
|
+
style: { left: `calc(6px + (100% - 12px) * ${s.offset})`, background: s.color, opacity: 0.4 + 0.6 * (s.opacity ?? 1) },
|
|
883
|
+
onClick: () => controller.selectGradientStop(s.selected ? null : s.index)
|
|
884
|
+
},
|
|
885
|
+
s.index
|
|
886
|
+
))
|
|
887
|
+
] }),
|
|
888
|
+
sel && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", "data-vector-gradient-selected-stop": sel.index, children: [
|
|
889
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
890
|
+
"input",
|
|
891
|
+
{
|
|
892
|
+
type: "color",
|
|
893
|
+
"aria-label": "Stop colour",
|
|
894
|
+
className: "h-7 w-9 cursor-pointer rounded border border-border bg-background",
|
|
895
|
+
value: (0, import_vector6.vectorPaintToHex)(sel.color) ?? "#000000",
|
|
896
|
+
onChange: (e) => controller.setGradientStop(sel.index, { color: e.target.value }, { merge: `gradient-stop-color-${sel.index}` }),
|
|
897
|
+
onBlur: end
|
|
898
|
+
}
|
|
899
|
+
),
|
|
900
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
901
|
+
"Opacity",
|
|
902
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
903
|
+
"input",
|
|
904
|
+
{
|
|
905
|
+
type: "number",
|
|
906
|
+
min: 0,
|
|
907
|
+
max: 100,
|
|
908
|
+
step: 5,
|
|
909
|
+
"aria-label": "Stop opacity",
|
|
910
|
+
className: numberClass3,
|
|
911
|
+
value: percent(sel.opacity ?? 1),
|
|
912
|
+
onChange: (e) => {
|
|
913
|
+
const n = parseFloat(e.target.value);
|
|
914
|
+
if (Number.isFinite(n)) controller.setGradientStop(sel.index, { opacity: n / 100 });
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
)
|
|
918
|
+
] }),
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
920
|
+
"At",
|
|
921
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
922
|
+
"input",
|
|
923
|
+
{
|
|
924
|
+
type: "number",
|
|
925
|
+
min: 0,
|
|
926
|
+
max: 100,
|
|
927
|
+
step: 1,
|
|
928
|
+
"aria-label": "Stop position",
|
|
929
|
+
className: numberClass3,
|
|
930
|
+
value: percent(sel.offset),
|
|
931
|
+
onChange: (e) => {
|
|
932
|
+
const n = parseFloat(e.target.value);
|
|
933
|
+
if (Number.isFinite(n)) controller.setGradientStop(sel.index, { offset: n / 100 });
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
)
|
|
937
|
+
] }),
|
|
938
|
+
!sel.last && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
939
|
+
"Midpoint",
|
|
940
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
941
|
+
"input",
|
|
942
|
+
{
|
|
943
|
+
type: "number",
|
|
944
|
+
min: 5,
|
|
945
|
+
max: 95,
|
|
946
|
+
step: 1,
|
|
947
|
+
"aria-label": "Stop midpoint",
|
|
948
|
+
className: numberClass3,
|
|
949
|
+
value: percent(sel.midpoint ?? 0.5),
|
|
950
|
+
onChange: (e) => {
|
|
951
|
+
const n = parseFloat(e.target.value);
|
|
952
|
+
if (Number.isFinite(n)) controller.setGradientStop(sel.index, { midpoint: n / 100 });
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
)
|
|
956
|
+
] }),
|
|
957
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: buttonClass3, "aria-label": "Delete stop", title: "Delete stop", disabled: ed.stops.length <= 2, onClick: () => controller.removeGradientStop(sel.index), children: "\u2715" })
|
|
958
|
+
] }),
|
|
959
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
960
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16", children: "Colours" }),
|
|
961
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("select", { "aria-label": "Gradient interpolation", className: selectClass3, value: ed.interpolation, onChange: (e) => controller.setGradient({ interpolation: e.target.value }), children: import_vector6.VECTOR_GRADIENT_INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: i, children: import_vector6.VECTOR_GRADIENT_INTERPOLATION_LABELS[i] }, i)) })
|
|
962
|
+
] }),
|
|
963
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
964
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16", children: "Smooth" }),
|
|
965
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
966
|
+
"input",
|
|
967
|
+
{
|
|
968
|
+
type: "range",
|
|
969
|
+
min: 0,
|
|
970
|
+
max: 1,
|
|
971
|
+
step: 0.05,
|
|
972
|
+
"aria-label": "Gradient smoothness",
|
|
973
|
+
className: "h-4 flex-1 accent-primary",
|
|
974
|
+
value: ed.smoothness,
|
|
975
|
+
onChange: (e) => controller.setGradient({ smoothness: parseFloat(e.target.value) }, { merge: "gradient-smoothness" }),
|
|
976
|
+
onPointerUp: end,
|
|
977
|
+
onBlur: end
|
|
978
|
+
}
|
|
979
|
+
)
|
|
980
|
+
] }),
|
|
981
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
982
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16", children: "Spread" }),
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("select", { "aria-label": "Gradient spread", className: selectClass3, value: ed.spread, onChange: (e) => controller.setGradient({ spread: e.target.value }), children: import_vector6.VECTOR_GRADIENT_SPREADS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: sp, children: import_vector6.VECTOR_GRADIENT_SPREAD_LABELS[sp] }, sp)) })
|
|
984
|
+
] }),
|
|
985
|
+
ed.target === "stroke" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
986
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16", children: "On stroke" }),
|
|
987
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("select", { "aria-label": "Gradient on stroke", className: selectClass3, value: ed.strokeMode, onChange: (e) => controller.setGradient({ strokeMode: e.target.value }), children: import_vector6.VECTOR_STROKE_GRADIENT_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: m, children: import_vector6.VECTOR_STROKE_GRADIENT_MODE_LABELS[m] }, m)) })
|
|
988
|
+
] })
|
|
989
|
+
] })
|
|
990
|
+
] });
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
// src/vector/VectorToolbar.tsx
|
|
994
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
658
995
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
659
996
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
660
|
-
var
|
|
997
|
+
var buttonClass4 = "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";
|
|
661
998
|
function VectorToolbar({
|
|
662
999
|
controller,
|
|
663
|
-
tools =
|
|
1000
|
+
tools = import_vector7.VECTOR_TOOLS,
|
|
664
1001
|
showHistory = true,
|
|
665
1002
|
showArrange = true,
|
|
666
1003
|
showSnap = true,
|
|
667
1004
|
showPathEdit = true,
|
|
668
1005
|
showBlend = true,
|
|
1006
|
+
showDistort = true,
|
|
669
1007
|
className
|
|
670
1008
|
}) {
|
|
671
1009
|
const state = useVectorEditorState(controller);
|
|
@@ -673,34 +1011,34 @@ function VectorToolbar({
|
|
|
673
1011
|
const points = state.tool === "direct" ? state.selectedAnchors.length : 0;
|
|
674
1012
|
const editing = state.editing;
|
|
675
1013
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
676
|
-
const [live, setLive] =
|
|
1014
|
+
const [live, setLive] = import_react5.default.useState(false);
|
|
677
1015
|
const booleanDisabled = live ? count < 1 : count < 2;
|
|
678
|
-
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0,
|
|
679
|
-
return /* @__PURE__ */ (0,
|
|
680
|
-
/* @__PURE__ */ (0,
|
|
1016
|
+
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: buttonClass4, title, "aria-label": title, disabled, onClick: () => void run(), children: label }, label);
|
|
1017
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { role: "toolbar", "aria-label": "Vector tools", className: `flex flex-wrap items-center gap-1 ${className ?? ""}`, children: [
|
|
1018
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Tools", children: tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
681
1019
|
"button",
|
|
682
1020
|
{
|
|
683
1021
|
type: "button",
|
|
684
1022
|
"data-vector-tool": tool,
|
|
685
|
-
className:
|
|
1023
|
+
className: buttonClass4,
|
|
686
1024
|
"aria-pressed": state.tool === tool,
|
|
687
|
-
title: `${(0,
|
|
688
|
-
"aria-label": (0,
|
|
1025
|
+
title: `${(0, import_vector7.vectorToolLabel)(tool)} (${import_vector7.VECTOR_TOOL_SHORTCUTS[tool]})`,
|
|
1026
|
+
"aria-label": (0, import_vector7.vectorToolLabel)(tool),
|
|
689
1027
|
onClick: () => controller.setTool(tool),
|
|
690
|
-
children:
|
|
1028
|
+
children: import_vector7.VECTOR_TOOL_GLYPHS[tool]
|
|
691
1029
|
},
|
|
692
1030
|
tool
|
|
693
1031
|
)) }),
|
|
694
|
-
showHistory && /* @__PURE__ */ (0,
|
|
1032
|
+
showHistory && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "History", children: [
|
|
695
1033
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
696
1034
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
697
1035
|
] }),
|
|
698
|
-
showSnap && /* @__PURE__ */ (0,
|
|
1036
|
+
showSnap && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Snapping", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
699
1037
|
"button",
|
|
700
1038
|
{
|
|
701
1039
|
type: "button",
|
|
702
1040
|
"data-vector-snap": "",
|
|
703
|
-
className:
|
|
1041
|
+
className: buttonClass4,
|
|
704
1042
|
"aria-pressed": state.snap.objects,
|
|
705
1043
|
title: `${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`,
|
|
706
1044
|
"aria-label": VECTOR_SNAP_TITLE,
|
|
@@ -708,13 +1046,13 @@ function VectorToolbar({
|
|
|
708
1046
|
children: "Snap"
|
|
709
1047
|
}
|
|
710
1048
|
) }),
|
|
711
|
-
showPathEdit && /* @__PURE__ */ (0,
|
|
712
|
-
|
|
1049
|
+
showPathEdit && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Path editing", children: [
|
|
1050
|
+
import_vector7.VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
713
1051
|
"button",
|
|
714
1052
|
{
|
|
715
1053
|
type: "button",
|
|
716
1054
|
"data-vector-path-action": a.id,
|
|
717
|
-
className:
|
|
1055
|
+
className: buttonClass4,
|
|
718
1056
|
title: a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title,
|
|
719
1057
|
"aria-label": a.title,
|
|
720
1058
|
disabled: !a.enabled(count, points),
|
|
@@ -723,12 +1061,12 @@ function VectorToolbar({
|
|
|
723
1061
|
},
|
|
724
1062
|
a.id
|
|
725
1063
|
)),
|
|
726
|
-
|
|
1064
|
+
import_vector7.VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
727
1065
|
"button",
|
|
728
1066
|
{
|
|
729
1067
|
type: "button",
|
|
730
1068
|
"data-vector-edit": t.key,
|
|
731
|
-
className:
|
|
1069
|
+
className: buttonClass4,
|
|
732
1070
|
"aria-pressed": editing[t.key],
|
|
733
1071
|
title: t.title,
|
|
734
1072
|
"aria-label": t.title,
|
|
@@ -737,9 +1075,9 @@ function VectorToolbar({
|
|
|
737
1075
|
},
|
|
738
1076
|
t.key
|
|
739
1077
|
)),
|
|
740
|
-
state.tool === "pencil" && /* @__PURE__ */ (0,
|
|
1078
|
+
state.tool === "pencil" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
741
1079
|
"Smoothing",
|
|
742
|
-
/* @__PURE__ */ (0,
|
|
1080
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
743
1081
|
"input",
|
|
744
1082
|
{
|
|
745
1083
|
type: "range",
|
|
@@ -753,9 +1091,9 @@ function VectorToolbar({
|
|
|
753
1091
|
}
|
|
754
1092
|
)
|
|
755
1093
|
] }),
|
|
756
|
-
state.tool === "eraser" && /* @__PURE__ */ (0,
|
|
1094
|
+
state.tool === "eraser" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
757
1095
|
"Size",
|
|
758
|
-
/* @__PURE__ */ (0,
|
|
1096
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
759
1097
|
"input",
|
|
760
1098
|
{
|
|
761
1099
|
type: "number",
|
|
@@ -771,29 +1109,42 @@ function VectorToolbar({
|
|
|
771
1109
|
}
|
|
772
1110
|
)
|
|
773
1111
|
] }),
|
|
774
|
-
state.tool === "paintBucket" && /* @__PURE__ */ (0,
|
|
1112
|
+
state.tool === "paintBucket" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
775
1113
|
"button",
|
|
776
1114
|
{
|
|
777
1115
|
type: "button",
|
|
778
1116
|
"data-vector-fill-gap": "",
|
|
779
|
-
className:
|
|
1117
|
+
className: buttonClass4,
|
|
780
1118
|
"aria-pressed": editing.fillGap > 0,
|
|
781
1119
|
title: "Close small gaps between path ends when filling",
|
|
782
1120
|
"aria-label": "Close gaps",
|
|
783
|
-
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 :
|
|
1121
|
+
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : import_vector7.VECTOR_FILL_GAP }),
|
|
784
1122
|
children: "Gaps"
|
|
785
1123
|
}
|
|
786
1124
|
)
|
|
787
1125
|
] }),
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
1126
|
+
showDistort && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Distort", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1127
|
+
"button",
|
|
1128
|
+
{
|
|
1129
|
+
type: "button",
|
|
1130
|
+
"data-vector-free-distort": "",
|
|
1131
|
+
className: buttonClass4,
|
|
1132
|
+
"aria-pressed": state.freeDistort,
|
|
1133
|
+
title: `Free Distort: drag a corner of the selection box to distort in perspective (Shift+Alt+${modKeyLabel()}: symmetric perspective; ${modKeyLabel()}-drag a side to skew)`,
|
|
1134
|
+
"aria-label": "Free Distort",
|
|
1135
|
+
onClick: () => controller.setFreeDistort(!state.freeDistort),
|
|
1136
|
+
children: "Distort"
|
|
1137
|
+
}
|
|
1138
|
+
) }),
|
|
1139
|
+
showBlend && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VectorBlendControls, { controller }),
|
|
1140
|
+
showArrange && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1141
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
|
|
1142
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
792
1143
|
"button",
|
|
793
1144
|
{
|
|
794
1145
|
type: "button",
|
|
795
1146
|
"data-vector-live-boolean": "",
|
|
796
|
-
className:
|
|
1147
|
+
className: buttonClass4,
|
|
797
1148
|
"aria-pressed": live,
|
|
798
1149
|
title: "Live booleans: keep the shapes editable",
|
|
799
1150
|
"aria-label": "Live booleans",
|
|
@@ -808,12 +1159,12 @@ function VectorToolbar({
|
|
|
808
1159
|
act("G", "Group", () => controller.group(), count < 1),
|
|
809
1160
|
act("U", "Ungroup", () => controller.ungroup(), !groupSelected)
|
|
810
1161
|
] }),
|
|
811
|
-
/* @__PURE__ */ (0,
|
|
1162
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: import_vector7.VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
812
1163
|
"button",
|
|
813
1164
|
{
|
|
814
1165
|
type: "button",
|
|
815
1166
|
"data-vector-pathfinder": a.id,
|
|
816
|
-
className:
|
|
1167
|
+
className: buttonClass4,
|
|
817
1168
|
title: a.title,
|
|
818
1169
|
"aria-label": a.title,
|
|
819
1170
|
disabled: count < a.min,
|
|
@@ -822,7 +1173,7 @@ function VectorToolbar({
|
|
|
822
1173
|
},
|
|
823
1174
|
a.id
|
|
824
1175
|
)) }),
|
|
825
|
-
/* @__PURE__ */ (0,
|
|
1176
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
826
1177
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
827
1178
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
828
1179
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -837,22 +1188,22 @@ function VectorToolbar({
|
|
|
837
1188
|
}
|
|
838
1189
|
function VectorBlendControls({ controller }) {
|
|
839
1190
|
const state = useVectorEditorState(controller);
|
|
840
|
-
const blend = (0,
|
|
1191
|
+
const blend = (0, import_vector7.getVectorBlendControls)(state);
|
|
841
1192
|
const o = blend.options;
|
|
842
1193
|
const selected = blend.ids.length > 0;
|
|
843
|
-
return /* @__PURE__ */ (0,
|
|
844
|
-
/* @__PURE__ */ (0,
|
|
845
|
-
/* @__PURE__ */ (0,
|
|
1194
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Blend", "data-vector-blend-controls": "", children: [
|
|
1195
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", "data-vector-blend-action": "make", className: buttonClass4, title: "Make Blend", "aria-label": "Make Blend", disabled: !blend.canBlend, onClick: () => controller.blend(), children: "\u29D3" }),
|
|
1196
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
846
1197
|
"select",
|
|
847
1198
|
{
|
|
848
1199
|
"aria-label": "Blend spacing",
|
|
849
1200
|
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
850
1201
|
value: o.spacing,
|
|
851
|
-
onChange: (e) => (0,
|
|
852
|
-
children:
|
|
1202
|
+
onChange: (e) => (0, import_vector7.applyVectorBlendOptions)(controller, { spacing: e.target.value }),
|
|
1203
|
+
children: import_vector7.VECTOR_BLEND_SPACINGS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: sp, children: import_vector7.VECTOR_BLEND_SPACING_LABELS[sp] }, sp))
|
|
853
1204
|
}
|
|
854
1205
|
),
|
|
855
|
-
o.spacing !== "smoothColor" && /* @__PURE__ */ (0,
|
|
1206
|
+
o.spacing !== "smoothColor" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
856
1207
|
"input",
|
|
857
1208
|
{
|
|
858
1209
|
type: "number",
|
|
@@ -864,29 +1215,29 @@ function VectorBlendControls({ controller }) {
|
|
|
864
1215
|
onChange: (e) => {
|
|
865
1216
|
const n = parseFloat(e.target.value);
|
|
866
1217
|
if (!Number.isFinite(n) || n <= 0) return;
|
|
867
|
-
(0,
|
|
1218
|
+
(0, import_vector7.applyVectorBlendOptions)(controller, o.spacing === "steps" ? { steps: n } : { distance: n });
|
|
868
1219
|
}
|
|
869
1220
|
}
|
|
870
1221
|
),
|
|
871
|
-
/* @__PURE__ */ (0,
|
|
1222
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
872
1223
|
"button",
|
|
873
1224
|
{
|
|
874
1225
|
type: "button",
|
|
875
1226
|
"data-vector-blend-action": "orient",
|
|
876
|
-
className:
|
|
1227
|
+
className: buttonClass4,
|
|
877
1228
|
"aria-pressed": o.orientToSpine,
|
|
878
1229
|
title: "Orient steps to the spine",
|
|
879
1230
|
"aria-label": "Orient to spine",
|
|
880
|
-
onClick: () => (0,
|
|
1231
|
+
onClick: () => (0, import_vector7.applyVectorBlendOptions)(controller, { orientToSpine: !o.orientToSpine }),
|
|
881
1232
|
children: "\u293F"
|
|
882
1233
|
}
|
|
883
1234
|
),
|
|
884
|
-
/* @__PURE__ */ (0,
|
|
1235
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
885
1236
|
"button",
|
|
886
1237
|
{
|
|
887
1238
|
type: "button",
|
|
888
1239
|
"data-vector-blend-action": "spine",
|
|
889
|
-
className:
|
|
1240
|
+
className: buttonClass4,
|
|
890
1241
|
title: "Replace Spine (select a blend and a path)",
|
|
891
1242
|
"aria-label": "Replace Spine",
|
|
892
1243
|
disabled: !blend.canReplaceSpine,
|
|
@@ -894,15 +1245,15 @@ function VectorBlendControls({ controller }) {
|
|
|
894
1245
|
children: "\u2307"
|
|
895
1246
|
}
|
|
896
1247
|
),
|
|
897
|
-
/* @__PURE__ */ (0,
|
|
898
|
-
/* @__PURE__ */ (0,
|
|
1248
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", "data-vector-blend-action": "expand", className: buttonClass4, title: "Expand Blend", "aria-label": "Expand Blend", disabled: !selected, onClick: () => controller.expandBlend(), children: "\u29C9" }),
|
|
1249
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", "data-vector-blend-action": "release", className: buttonClass4, title: "Release Blend", "aria-label": "Release Blend", disabled: !selected, onClick: () => controller.releaseBlend(), children: "\u29C4" })
|
|
899
1250
|
] });
|
|
900
1251
|
}
|
|
901
|
-
var
|
|
902
|
-
var
|
|
1252
|
+
var selectClass4 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
1253
|
+
var numberClass4 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
903
1254
|
function VectorStylePanel({ controller, className }) {
|
|
904
1255
|
const state = useVectorEditorState(controller);
|
|
905
|
-
const style = (0,
|
|
1256
|
+
const style = (0, import_vector7.getVectorSelectionStyle)(state);
|
|
906
1257
|
const d = state.defaults;
|
|
907
1258
|
const source = style ?? {
|
|
908
1259
|
fill: d.fill ?? null,
|
|
@@ -915,7 +1266,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
915
1266
|
arrowAlign: d.arrowAlign ?? "extend",
|
|
916
1267
|
startArrowScale: d.startArrowScale ?? 1,
|
|
917
1268
|
endArrowScale: d.endArrowScale ?? 1,
|
|
918
|
-
widthProfile: (0,
|
|
1269
|
+
widthProfile: (0, import_vector7.widthProfilePresetId)(d.strokeWidthProfile),
|
|
919
1270
|
cornerRadius: d.cornerRadius,
|
|
920
1271
|
cornerKind: d.cornerKind ?? "round",
|
|
921
1272
|
corners: 1,
|
|
@@ -928,19 +1279,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
928
1279
|
};
|
|
929
1280
|
const setProfile = (id) => {
|
|
930
1281
|
if (style) controller.setWidthProfile(id);
|
|
931
|
-
else controller.setDefaults({ strokeWidthProfile: (0,
|
|
1282
|
+
else controller.setDefaults({ strokeWidthProfile: (0, import_vector7.widthProfilePreset)(id)?.length ? (0, import_vector7.widthProfilePreset)(id) : null });
|
|
932
1283
|
};
|
|
933
|
-
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0,
|
|
1284
|
+
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
|
|
934
1285
|
const arrowRow = (end, label) => {
|
|
935
1286
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
936
1287
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
937
|
-
return /* @__PURE__ */ (0,
|
|
938
|
-
/* @__PURE__ */ (0,
|
|
939
|
-
/* @__PURE__ */ (0,
|
|
940
|
-
/* @__PURE__ */ (0,
|
|
941
|
-
|
|
1288
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
1289
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16 text-xs text-foreground", children: label }),
|
|
1290
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("select", { "aria-label": `${label} arrowhead`, className: selectClass4, value: source[key] ?? "", onChange: (e) => apply({ [key]: e.target.value || null }), children: [
|
|
1291
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "", children: "None" }),
|
|
1292
|
+
import_vector7.VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: h, children: import_vector7.VECTOR_ARROWHEAD_LABELS[h] }, h))
|
|
942
1293
|
] }),
|
|
943
|
-
/* @__PURE__ */ (0,
|
|
1294
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
944
1295
|
"input",
|
|
945
1296
|
{
|
|
946
1297
|
type: "number",
|
|
@@ -948,7 +1299,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
948
1299
|
step: 0.25,
|
|
949
1300
|
"aria-label": `${label} arrowhead scale`,
|
|
950
1301
|
title: "Scale (\xD7 stroke width)",
|
|
951
|
-
className:
|
|
1302
|
+
className: numberClass4,
|
|
952
1303
|
value: source[scaleKey],
|
|
953
1304
|
onChange: (e) => {
|
|
954
1305
|
const n = parseFloat(e.target.value);
|
|
@@ -964,14 +1315,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
964
1315
|
};
|
|
965
1316
|
const paintRow = (key, label) => {
|
|
966
1317
|
const paint = source[key];
|
|
967
|
-
const hex = (0,
|
|
1318
|
+
const hex = (0, import_vector7.vectorPaintToHex)(paint);
|
|
968
1319
|
const on = paint !== null && paint !== "none";
|
|
969
|
-
return /* @__PURE__ */ (0,
|
|
970
|
-
/* @__PURE__ */ (0,
|
|
971
|
-
/* @__PURE__ */ (0,
|
|
1320
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
1321
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex w-16 items-center gap-1.5 text-xs text-foreground", children: [
|
|
1322
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("input", { type: "checkbox", checked: on, "aria-label": `${label} on`, onChange: (e) => apply({ [key]: e.target.checked ? hex ?? "#000000" : null }) }),
|
|
972
1323
|
label
|
|
973
1324
|
] }),
|
|
974
|
-
/* @__PURE__ */ (0,
|
|
1325
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
975
1326
|
"input",
|
|
976
1327
|
{
|
|
977
1328
|
type: "color",
|
|
@@ -982,17 +1333,18 @@ function VectorStylePanel({ controller, className }) {
|
|
|
982
1333
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
983
1334
|
}
|
|
984
1335
|
),
|
|
985
|
-
on && !hex && /* @__PURE__ */ (0,
|
|
986
|
-
style?.mixed[key] && /* @__PURE__ */ (0,
|
|
1336
|
+
on && !hex && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "truncate text-[11px] text-muted-foreground", children: typeof paint === "string" ? paint : "Gradient" }),
|
|
1337
|
+
style?.mixed[key] && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
987
1338
|
] });
|
|
988
1339
|
};
|
|
989
|
-
return /* @__PURE__ */ (0,
|
|
990
|
-
/* @__PURE__ */ (0,
|
|
1340
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "aria-label": style ? "Selection style" : "New shape style", children: [
|
|
1341
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: style ? "Selection" : "New shapes" }),
|
|
991
1342
|
paintRow("fill", "Fill"),
|
|
992
1343
|
paintRow("stroke", "Stroke"),
|
|
993
|
-
/* @__PURE__ */ (0,
|
|
994
|
-
|
|
995
|
-
/* @__PURE__ */ (0,
|
|
1344
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VectorGradientEditor, { controller }),
|
|
1345
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
1346
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16", children: "Width" }),
|
|
1347
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
996
1348
|
"input",
|
|
997
1349
|
{
|
|
998
1350
|
type: "number",
|
|
@@ -1008,33 +1360,33 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1008
1360
|
}
|
|
1009
1361
|
)
|
|
1010
1362
|
] }),
|
|
1011
|
-
/* @__PURE__ */ (0,
|
|
1012
|
-
/* @__PURE__ */ (0,
|
|
1013
|
-
/* @__PURE__ */ (0,
|
|
1363
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "strokeAlign", children: [
|
|
1364
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16", children: "Align" }),
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("select", { "aria-label": "Stroke alignment", className: selectClass4, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(import_vector7.VECTOR_STROKE_ALIGN_LABELS).map((a) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: a, children: import_vector7.VECTOR_STROKE_ALIGN_LABELS[a] }, a)) }),
|
|
1014
1366
|
mixed("strokeAlign")
|
|
1015
1367
|
] }),
|
|
1016
|
-
/* @__PURE__ */ (0,
|
|
1017
|
-
/* @__PURE__ */ (0,
|
|
1018
|
-
/* @__PURE__ */ (0,
|
|
1368
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
|
|
1369
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16", children: "Profile" }),
|
|
1370
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
1019
1371
|
"select",
|
|
1020
1372
|
{
|
|
1021
1373
|
"aria-label": "Width profile",
|
|
1022
|
-
className:
|
|
1374
|
+
className: selectClass4,
|
|
1023
1375
|
value: source.widthProfile,
|
|
1024
1376
|
onChange: (e) => {
|
|
1025
1377
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
1026
1378
|
},
|
|
1027
1379
|
children: [
|
|
1028
|
-
|
|
1029
|
-
source.widthProfile === "custom" && /* @__PURE__ */ (0,
|
|
1380
|
+
import_vector7.VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: p.id, children: p.label }, p.id)),
|
|
1381
|
+
source.widthProfile === "custom" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "custom", disabled: true, children: "Custom" })
|
|
1030
1382
|
]
|
|
1031
1383
|
}
|
|
1032
1384
|
),
|
|
1033
|
-
/* @__PURE__ */ (0,
|
|
1385
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1034
1386
|
"button",
|
|
1035
1387
|
{
|
|
1036
1388
|
type: "button",
|
|
1037
|
-
className:
|
|
1389
|
+
className: buttonClass4,
|
|
1038
1390
|
title: "Reset to uniform width",
|
|
1039
1391
|
"aria-label": "Reset to uniform width",
|
|
1040
1392
|
disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
|
|
@@ -1044,27 +1396,27 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1044
1396
|
),
|
|
1045
1397
|
mixed("widthProfile")
|
|
1046
1398
|
] }),
|
|
1047
|
-
source.hasOpenPath && /* @__PURE__ */ (0,
|
|
1399
|
+
source.hasOpenPath && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1048
1400
|
arrowRow("start", "Start"),
|
|
1049
1401
|
arrowRow("end", "End"),
|
|
1050
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0,
|
|
1051
|
-
/* @__PURE__ */ (0,
|
|
1052
|
-
/* @__PURE__ */ (0,
|
|
1053
|
-
/* @__PURE__ */ (0,
|
|
1054
|
-
/* @__PURE__ */ (0,
|
|
1402
|
+
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "arrowAlign", children: [
|
|
1403
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16", children: "Heads" }),
|
|
1404
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("select", { "aria-label": "Arrowhead alignment", className: selectClass4, value: source.arrowAlign, onChange: (e) => apply({ arrowAlign: e.target.value }), children: [
|
|
1405
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "extend", children: "Tip past end" }),
|
|
1406
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "tip", children: "Tip at end" })
|
|
1055
1407
|
] })
|
|
1056
1408
|
] })
|
|
1057
1409
|
] }),
|
|
1058
|
-
source.corners > 0 && /* @__PURE__ */ (0,
|
|
1059
|
-
/* @__PURE__ */ (0,
|
|
1060
|
-
/* @__PURE__ */ (0,
|
|
1410
|
+
source.corners > 0 && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": "corners", children: [
|
|
1411
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Corners" }),
|
|
1412
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1061
1413
|
"input",
|
|
1062
1414
|
{
|
|
1063
1415
|
type: "number",
|
|
1064
1416
|
min: 0,
|
|
1065
1417
|
step: 1,
|
|
1066
1418
|
"aria-label": "Corner radius",
|
|
1067
|
-
className:
|
|
1419
|
+
className: numberClass4,
|
|
1068
1420
|
value: Math.round(source.cornerRadius * 100) / 100,
|
|
1069
1421
|
onChange: (e) => {
|
|
1070
1422
|
const n = parseFloat(e.target.value);
|
|
@@ -1072,12 +1424,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1072
1424
|
}
|
|
1073
1425
|
}
|
|
1074
1426
|
),
|
|
1075
|
-
/* @__PURE__ */ (0,
|
|
1427
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("select", { "aria-label": "Corner kind", className: selectClass4, value: source.cornerKind, onChange: (e) => setCorners({ kind: e.target.value }), children: import_vector7.VECTOR_CORNER_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: k, children: import_vector7.VECTOR_CORNER_KIND_LABELS[k] }, k)) }),
|
|
1076
1428
|
mixed("cornerRadius")
|
|
1077
1429
|
] }),
|
|
1078
|
-
style && /* @__PURE__ */ (0,
|
|
1079
|
-
/* @__PURE__ */ (0,
|
|
1080
|
-
/* @__PURE__ */ (0,
|
|
1430
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
1431
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16", children: "Opacity" }),
|
|
1432
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1081
1433
|
"input",
|
|
1082
1434
|
{
|
|
1083
1435
|
type: "range",
|
|
@@ -1091,18 +1443,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1091
1443
|
}
|
|
1092
1444
|
)
|
|
1093
1445
|
] }),
|
|
1094
|
-
style && /* @__PURE__ */ (0,
|
|
1446
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VectorEffectsPanel, { controller }),
|
|
1447
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VectorEnvelopePanel, { controller })
|
|
1095
1448
|
] });
|
|
1096
1449
|
}
|
|
1097
1450
|
|
|
1098
1451
|
// src/vector/VectorEditor.tsx
|
|
1099
|
-
var
|
|
1452
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1100
1453
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }) {
|
|
1101
|
-
return /* @__PURE__ */ (0,
|
|
1102
|
-
/* @__PURE__ */ (0,
|
|
1103
|
-
/* @__PURE__ */ (0,
|
|
1104
|
-
/* @__PURE__ */ (0,
|
|
1105
|
-
showStylePanel && /* @__PURE__ */ (0,
|
|
1454
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `flex flex-col gap-2 ${className ?? ""}`, "data-vector-editor": "", children: [
|
|
1455
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VectorToolbar, { controller, tools }),
|
|
1456
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex min-h-0 flex-col gap-2 md:flex-row", children: [
|
|
1457
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "relative min-h-[320px] flex-1 overflow-hidden rounded-md border border-border bg-muted/40", style: { height }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VectorCanvas, { controller, ...canvasProps }) }),
|
|
1458
|
+
showStylePanel && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VectorStylePanel, { controller, className: "w-full shrink-0 rounded-md border border-border p-3 md:w-56" })
|
|
1106
1459
|
] })
|
|
1107
1460
|
] });
|
|
1108
1461
|
}
|
|
@@ -1111,7 +1464,10 @@ function VectorEditor({ controller, tools, showStylePanel = true, height = 520,
|
|
|
1111
1464
|
VectorCanvas,
|
|
1112
1465
|
VectorEditor,
|
|
1113
1466
|
VectorEffectsPanel,
|
|
1467
|
+
VectorEnvelopePanel,
|
|
1468
|
+
VectorGradientAnnotator,
|
|
1114
1469
|
VectorGradientDefs,
|
|
1470
|
+
VectorGradientEditor,
|
|
1115
1471
|
VectorSceneNodes,
|
|
1116
1472
|
VectorStylePanel,
|
|
1117
1473
|
VectorToolbar,
|