@pixerate/editor-react 0.33.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 +298 -155
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +17 -3
- package/dist/vector/index.d.ts +17 -3
- package/dist/vector/index.js +281 -139
- package/dist/vector/index.js.map +1 -1
- package/package.json +3 -3
package/dist/vector/index.cjs
CHANGED
|
@@ -33,6 +33,7 @@ __export(vector_exports, {
|
|
|
33
33
|
VectorCanvas: () => VectorCanvas,
|
|
34
34
|
VectorEditor: () => VectorEditor,
|
|
35
35
|
VectorEffectsPanel: () => VectorEffectsPanel,
|
|
36
|
+
VectorEnvelopePanel: () => VectorEnvelopePanel,
|
|
36
37
|
VectorGradientAnnotator: () => VectorGradientAnnotator,
|
|
37
38
|
VectorGradientDefs: () => VectorGradientDefs,
|
|
38
39
|
VectorGradientEditor: () => VectorGradientEditor,
|
|
@@ -403,13 +404,28 @@ function VectorCanvas({
|
|
|
403
404
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-overlay": "", pointerEvents: "none", fill: "none", children: [
|
|
404
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)),
|
|
405
406
|
overlay.penPreview && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: overlay.penPreview, stroke: accentColor, strokeDasharray: "4 3" }),
|
|
406
|
-
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: [
|
|
407
408
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: box.x, y: box.y, width: box.width, height: box.height, stroke: accentColor }),
|
|
408
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 }),
|
|
409
410
|
box.handles.map(
|
|
410
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)
|
|
411
412
|
)
|
|
412
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
|
+
] }),
|
|
413
429
|
overlay.handles.map((h) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-handle": h.ref.handle, children: [
|
|
414
430
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: h.anchorX, y1: h.anchorY, x2: h.x, y2: h.y, stroke: accentColor }),
|
|
415
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 })
|
|
@@ -551,8 +567,8 @@ function VectorCanvas({
|
|
|
551
567
|
}
|
|
552
568
|
|
|
553
569
|
// src/vector/VectorToolbar.tsx
|
|
554
|
-
var
|
|
555
|
-
var
|
|
570
|
+
var import_react5 = __toESM(require("react"), 1);
|
|
571
|
+
var import_vector7 = require("@pixerate/editor/vector");
|
|
556
572
|
|
|
557
573
|
// src/vector/VectorEffectsPanel.tsx
|
|
558
574
|
var import_vector4 = require("@pixerate/editor/vector");
|
|
@@ -694,16 +710,127 @@ function VectorEffectsPanel({ controller, className }) {
|
|
|
694
710
|
] });
|
|
695
711
|
}
|
|
696
712
|
|
|
697
|
-
// src/vector/
|
|
713
|
+
// src/vector/VectorEnvelopePanel.tsx
|
|
714
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
698
715
|
var import_vector5 = require("@pixerate/editor/vector");
|
|
699
716
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
700
|
-
var
|
|
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";
|
|
701
718
|
var numberClass2 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
702
|
-
var
|
|
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";
|
|
703
830
|
var percent = (v) => Math.round(v * 1e3) / 10;
|
|
704
831
|
function VectorGradientEditor({ controller, className }) {
|
|
705
832
|
const state = useVectorEditorState(controller);
|
|
706
|
-
const ed = (0,
|
|
833
|
+
const ed = (0, import_vector6.getVectorGradientEditor)(state);
|
|
707
834
|
if (!ed) return null;
|
|
708
835
|
const g = ed.gradient;
|
|
709
836
|
const sel = ed.selected;
|
|
@@ -711,26 +838,26 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
711
838
|
const setType = (value) => {
|
|
712
839
|
if (value === "solid") {
|
|
713
840
|
const first = ed.stops[0];
|
|
714
|
-
controller.setStyle({ [ed.target]: (0,
|
|
841
|
+
controller.setStyle({ [ed.target]: (0, import_vector6.vectorPaintToHex)(first?.color) ?? first?.color ?? "#000000" }, void 0, { label: "Solid Colour" });
|
|
715
842
|
} else controller.setGradient({ type: value });
|
|
716
843
|
};
|
|
717
|
-
return /* @__PURE__ */ (0,
|
|
718
|
-
/* @__PURE__ */ (0,
|
|
719
|
-
/* @__PURE__ */ (0,
|
|
720
|
-
["fill", "stroke"].map((t) => /* @__PURE__ */ (0,
|
|
721
|
-
ed.mixed && /* @__PURE__ */ (0,
|
|
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" })
|
|
722
849
|
] }),
|
|
723
|
-
/* @__PURE__ */ (0,
|
|
724
|
-
/* @__PURE__ */ (0,
|
|
725
|
-
/* @__PURE__ */ (0,
|
|
726
|
-
/* @__PURE__ */ (0,
|
|
727
|
-
|
|
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))
|
|
728
855
|
] }),
|
|
729
|
-
/* @__PURE__ */ (0,
|
|
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" })
|
|
730
857
|
] }),
|
|
731
|
-
g && /* @__PURE__ */ (0,
|
|
732
|
-
/* @__PURE__ */ (0,
|
|
733
|
-
/* @__PURE__ */ (0,
|
|
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)(
|
|
734
861
|
"div",
|
|
735
862
|
{
|
|
736
863
|
role: "button",
|
|
@@ -744,7 +871,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
744
871
|
}
|
|
745
872
|
}
|
|
746
873
|
),
|
|
747
|
-
ed.stops.map((s) => /* @__PURE__ */ (0,
|
|
874
|
+
ed.stops.map((s) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
748
875
|
"button",
|
|
749
876
|
{
|
|
750
877
|
type: "button",
|
|
@@ -758,21 +885,21 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
758
885
|
s.index
|
|
759
886
|
))
|
|
760
887
|
] }),
|
|
761
|
-
sel && /* @__PURE__ */ (0,
|
|
762
|
-
/* @__PURE__ */ (0,
|
|
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)(
|
|
763
890
|
"input",
|
|
764
891
|
{
|
|
765
892
|
type: "color",
|
|
766
893
|
"aria-label": "Stop colour",
|
|
767
894
|
className: "h-7 w-9 cursor-pointer rounded border border-border bg-background",
|
|
768
|
-
value: (0,
|
|
895
|
+
value: (0, import_vector6.vectorPaintToHex)(sel.color) ?? "#000000",
|
|
769
896
|
onChange: (e) => controller.setGradientStop(sel.index, { color: e.target.value }, { merge: `gradient-stop-color-${sel.index}` }),
|
|
770
897
|
onBlur: end
|
|
771
898
|
}
|
|
772
899
|
),
|
|
773
|
-
/* @__PURE__ */ (0,
|
|
900
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
774
901
|
"Opacity",
|
|
775
|
-
/* @__PURE__ */ (0,
|
|
902
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
776
903
|
"input",
|
|
777
904
|
{
|
|
778
905
|
type: "number",
|
|
@@ -780,7 +907,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
780
907
|
max: 100,
|
|
781
908
|
step: 5,
|
|
782
909
|
"aria-label": "Stop opacity",
|
|
783
|
-
className:
|
|
910
|
+
className: numberClass3,
|
|
784
911
|
value: percent(sel.opacity ?? 1),
|
|
785
912
|
onChange: (e) => {
|
|
786
913
|
const n = parseFloat(e.target.value);
|
|
@@ -789,9 +916,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
789
916
|
}
|
|
790
917
|
)
|
|
791
918
|
] }),
|
|
792
|
-
/* @__PURE__ */ (0,
|
|
919
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
793
920
|
"At",
|
|
794
|
-
/* @__PURE__ */ (0,
|
|
921
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
795
922
|
"input",
|
|
796
923
|
{
|
|
797
924
|
type: "number",
|
|
@@ -799,7 +926,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
799
926
|
max: 100,
|
|
800
927
|
step: 1,
|
|
801
928
|
"aria-label": "Stop position",
|
|
802
|
-
className:
|
|
929
|
+
className: numberClass3,
|
|
803
930
|
value: percent(sel.offset),
|
|
804
931
|
onChange: (e) => {
|
|
805
932
|
const n = parseFloat(e.target.value);
|
|
@@ -808,9 +935,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
808
935
|
}
|
|
809
936
|
)
|
|
810
937
|
] }),
|
|
811
|
-
!sel.last && /* @__PURE__ */ (0,
|
|
938
|
+
!sel.last && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
812
939
|
"Midpoint",
|
|
813
|
-
/* @__PURE__ */ (0,
|
|
940
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
814
941
|
"input",
|
|
815
942
|
{
|
|
816
943
|
type: "number",
|
|
@@ -818,7 +945,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
818
945
|
max: 95,
|
|
819
946
|
step: 1,
|
|
820
947
|
"aria-label": "Stop midpoint",
|
|
821
|
-
className:
|
|
948
|
+
className: numberClass3,
|
|
822
949
|
value: percent(sel.midpoint ?? 0.5),
|
|
823
950
|
onChange: (e) => {
|
|
824
951
|
const n = parseFloat(e.target.value);
|
|
@@ -827,15 +954,15 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
827
954
|
}
|
|
828
955
|
)
|
|
829
956
|
] }),
|
|
830
|
-
/* @__PURE__ */ (0,
|
|
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" })
|
|
831
958
|
] }),
|
|
832
|
-
/* @__PURE__ */ (0,
|
|
833
|
-
/* @__PURE__ */ (0,
|
|
834
|
-
/* @__PURE__ */ (0,
|
|
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)) })
|
|
835
962
|
] }),
|
|
836
|
-
/* @__PURE__ */ (0,
|
|
837
|
-
/* @__PURE__ */ (0,
|
|
838
|
-
/* @__PURE__ */ (0,
|
|
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)(
|
|
839
966
|
"input",
|
|
840
967
|
{
|
|
841
968
|
type: "range",
|
|
@@ -851,31 +978,32 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
851
978
|
}
|
|
852
979
|
)
|
|
853
980
|
] }),
|
|
854
|
-
/* @__PURE__ */ (0,
|
|
855
|
-
/* @__PURE__ */ (0,
|
|
856
|
-
/* @__PURE__ */ (0,
|
|
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)) })
|
|
857
984
|
] }),
|
|
858
|
-
ed.target === "stroke" && /* @__PURE__ */ (0,
|
|
859
|
-
/* @__PURE__ */ (0,
|
|
860
|
-
/* @__PURE__ */ (0,
|
|
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)) })
|
|
861
988
|
] })
|
|
862
989
|
] })
|
|
863
990
|
] });
|
|
864
991
|
}
|
|
865
992
|
|
|
866
993
|
// src/vector/VectorToolbar.tsx
|
|
867
|
-
var
|
|
994
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
868
995
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
869
996
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
870
|
-
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";
|
|
871
998
|
function VectorToolbar({
|
|
872
999
|
controller,
|
|
873
|
-
tools =
|
|
1000
|
+
tools = import_vector7.VECTOR_TOOLS,
|
|
874
1001
|
showHistory = true,
|
|
875
1002
|
showArrange = true,
|
|
876
1003
|
showSnap = true,
|
|
877
1004
|
showPathEdit = true,
|
|
878
1005
|
showBlend = true,
|
|
1006
|
+
showDistort = true,
|
|
879
1007
|
className
|
|
880
1008
|
}) {
|
|
881
1009
|
const state = useVectorEditorState(controller);
|
|
@@ -883,34 +1011,34 @@ function VectorToolbar({
|
|
|
883
1011
|
const points = state.tool === "direct" ? state.selectedAnchors.length : 0;
|
|
884
1012
|
const editing = state.editing;
|
|
885
1013
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
886
|
-
const [live, setLive] =
|
|
1014
|
+
const [live, setLive] = import_react5.default.useState(false);
|
|
887
1015
|
const booleanDisabled = live ? count < 1 : count < 2;
|
|
888
|
-
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0,
|
|
889
|
-
return /* @__PURE__ */ (0,
|
|
890
|
-
/* @__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)(
|
|
891
1019
|
"button",
|
|
892
1020
|
{
|
|
893
1021
|
type: "button",
|
|
894
1022
|
"data-vector-tool": tool,
|
|
895
|
-
className:
|
|
1023
|
+
className: buttonClass4,
|
|
896
1024
|
"aria-pressed": state.tool === tool,
|
|
897
|
-
title: `${(0,
|
|
898
|
-
"aria-label": (0,
|
|
1025
|
+
title: `${(0, import_vector7.vectorToolLabel)(tool)} (${import_vector7.VECTOR_TOOL_SHORTCUTS[tool]})`,
|
|
1026
|
+
"aria-label": (0, import_vector7.vectorToolLabel)(tool),
|
|
899
1027
|
onClick: () => controller.setTool(tool),
|
|
900
|
-
children:
|
|
1028
|
+
children: import_vector7.VECTOR_TOOL_GLYPHS[tool]
|
|
901
1029
|
},
|
|
902
1030
|
tool
|
|
903
1031
|
)) }),
|
|
904
|
-
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: [
|
|
905
1033
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
906
1034
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
907
1035
|
] }),
|
|
908
|
-
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)(
|
|
909
1037
|
"button",
|
|
910
1038
|
{
|
|
911
1039
|
type: "button",
|
|
912
1040
|
"data-vector-snap": "",
|
|
913
|
-
className:
|
|
1041
|
+
className: buttonClass4,
|
|
914
1042
|
"aria-pressed": state.snap.objects,
|
|
915
1043
|
title: `${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`,
|
|
916
1044
|
"aria-label": VECTOR_SNAP_TITLE,
|
|
@@ -918,13 +1046,13 @@ function VectorToolbar({
|
|
|
918
1046
|
children: "Snap"
|
|
919
1047
|
}
|
|
920
1048
|
) }),
|
|
921
|
-
showPathEdit && /* @__PURE__ */ (0,
|
|
922
|
-
|
|
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)(
|
|
923
1051
|
"button",
|
|
924
1052
|
{
|
|
925
1053
|
type: "button",
|
|
926
1054
|
"data-vector-path-action": a.id,
|
|
927
|
-
className:
|
|
1055
|
+
className: buttonClass4,
|
|
928
1056
|
title: a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title,
|
|
929
1057
|
"aria-label": a.title,
|
|
930
1058
|
disabled: !a.enabled(count, points),
|
|
@@ -933,12 +1061,12 @@ function VectorToolbar({
|
|
|
933
1061
|
},
|
|
934
1062
|
a.id
|
|
935
1063
|
)),
|
|
936
|
-
|
|
1064
|
+
import_vector7.VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
937
1065
|
"button",
|
|
938
1066
|
{
|
|
939
1067
|
type: "button",
|
|
940
1068
|
"data-vector-edit": t.key,
|
|
941
|
-
className:
|
|
1069
|
+
className: buttonClass4,
|
|
942
1070
|
"aria-pressed": editing[t.key],
|
|
943
1071
|
title: t.title,
|
|
944
1072
|
"aria-label": t.title,
|
|
@@ -947,9 +1075,9 @@ function VectorToolbar({
|
|
|
947
1075
|
},
|
|
948
1076
|
t.key
|
|
949
1077
|
)),
|
|
950
|
-
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: [
|
|
951
1079
|
"Smoothing",
|
|
952
|
-
/* @__PURE__ */ (0,
|
|
1080
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
953
1081
|
"input",
|
|
954
1082
|
{
|
|
955
1083
|
type: "range",
|
|
@@ -963,9 +1091,9 @@ function VectorToolbar({
|
|
|
963
1091
|
}
|
|
964
1092
|
)
|
|
965
1093
|
] }),
|
|
966
|
-
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: [
|
|
967
1095
|
"Size",
|
|
968
|
-
/* @__PURE__ */ (0,
|
|
1096
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
969
1097
|
"input",
|
|
970
1098
|
{
|
|
971
1099
|
type: "number",
|
|
@@ -981,29 +1109,42 @@ function VectorToolbar({
|
|
|
981
1109
|
}
|
|
982
1110
|
)
|
|
983
1111
|
] }),
|
|
984
|
-
state.tool === "paintBucket" && /* @__PURE__ */ (0,
|
|
1112
|
+
state.tool === "paintBucket" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
985
1113
|
"button",
|
|
986
1114
|
{
|
|
987
1115
|
type: "button",
|
|
988
1116
|
"data-vector-fill-gap": "",
|
|
989
|
-
className:
|
|
1117
|
+
className: buttonClass4,
|
|
990
1118
|
"aria-pressed": editing.fillGap > 0,
|
|
991
1119
|
title: "Close small gaps between path ends when filling",
|
|
992
1120
|
"aria-label": "Close gaps",
|
|
993
|
-
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 :
|
|
1121
|
+
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : import_vector7.VECTOR_FILL_GAP }),
|
|
994
1122
|
children: "Gaps"
|
|
995
1123
|
}
|
|
996
1124
|
)
|
|
997
1125
|
] }),
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
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)(
|
|
1002
1143
|
"button",
|
|
1003
1144
|
{
|
|
1004
1145
|
type: "button",
|
|
1005
1146
|
"data-vector-live-boolean": "",
|
|
1006
|
-
className:
|
|
1147
|
+
className: buttonClass4,
|
|
1007
1148
|
"aria-pressed": live,
|
|
1008
1149
|
title: "Live booleans: keep the shapes editable",
|
|
1009
1150
|
"aria-label": "Live booleans",
|
|
@@ -1018,12 +1159,12 @@ function VectorToolbar({
|
|
|
1018
1159
|
act("G", "Group", () => controller.group(), count < 1),
|
|
1019
1160
|
act("U", "Ungroup", () => controller.ungroup(), !groupSelected)
|
|
1020
1161
|
] }),
|
|
1021
|
-
/* @__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)(
|
|
1022
1163
|
"button",
|
|
1023
1164
|
{
|
|
1024
1165
|
type: "button",
|
|
1025
1166
|
"data-vector-pathfinder": a.id,
|
|
1026
|
-
className:
|
|
1167
|
+
className: buttonClass4,
|
|
1027
1168
|
title: a.title,
|
|
1028
1169
|
"aria-label": a.title,
|
|
1029
1170
|
disabled: count < a.min,
|
|
@@ -1032,7 +1173,7 @@ function VectorToolbar({
|
|
|
1032
1173
|
},
|
|
1033
1174
|
a.id
|
|
1034
1175
|
)) }),
|
|
1035
|
-
/* @__PURE__ */ (0,
|
|
1176
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
1036
1177
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
1037
1178
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
1038
1179
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -1047,22 +1188,22 @@ function VectorToolbar({
|
|
|
1047
1188
|
}
|
|
1048
1189
|
function VectorBlendControls({ controller }) {
|
|
1049
1190
|
const state = useVectorEditorState(controller);
|
|
1050
|
-
const blend = (0,
|
|
1191
|
+
const blend = (0, import_vector7.getVectorBlendControls)(state);
|
|
1051
1192
|
const o = blend.options;
|
|
1052
1193
|
const selected = blend.ids.length > 0;
|
|
1053
|
-
return /* @__PURE__ */ (0,
|
|
1054
|
-
/* @__PURE__ */ (0,
|
|
1055
|
-
/* @__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)(
|
|
1056
1197
|
"select",
|
|
1057
1198
|
{
|
|
1058
1199
|
"aria-label": "Blend spacing",
|
|
1059
1200
|
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
1060
1201
|
value: o.spacing,
|
|
1061
|
-
onChange: (e) => (0,
|
|
1062
|
-
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))
|
|
1063
1204
|
}
|
|
1064
1205
|
),
|
|
1065
|
-
o.spacing !== "smoothColor" && /* @__PURE__ */ (0,
|
|
1206
|
+
o.spacing !== "smoothColor" && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1066
1207
|
"input",
|
|
1067
1208
|
{
|
|
1068
1209
|
type: "number",
|
|
@@ -1074,29 +1215,29 @@ function VectorBlendControls({ controller }) {
|
|
|
1074
1215
|
onChange: (e) => {
|
|
1075
1216
|
const n = parseFloat(e.target.value);
|
|
1076
1217
|
if (!Number.isFinite(n) || n <= 0) return;
|
|
1077
|
-
(0,
|
|
1218
|
+
(0, import_vector7.applyVectorBlendOptions)(controller, o.spacing === "steps" ? { steps: n } : { distance: n });
|
|
1078
1219
|
}
|
|
1079
1220
|
}
|
|
1080
1221
|
),
|
|
1081
|
-
/* @__PURE__ */ (0,
|
|
1222
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1082
1223
|
"button",
|
|
1083
1224
|
{
|
|
1084
1225
|
type: "button",
|
|
1085
1226
|
"data-vector-blend-action": "orient",
|
|
1086
|
-
className:
|
|
1227
|
+
className: buttonClass4,
|
|
1087
1228
|
"aria-pressed": o.orientToSpine,
|
|
1088
1229
|
title: "Orient steps to the spine",
|
|
1089
1230
|
"aria-label": "Orient to spine",
|
|
1090
|
-
onClick: () => (0,
|
|
1231
|
+
onClick: () => (0, import_vector7.applyVectorBlendOptions)(controller, { orientToSpine: !o.orientToSpine }),
|
|
1091
1232
|
children: "\u293F"
|
|
1092
1233
|
}
|
|
1093
1234
|
),
|
|
1094
|
-
/* @__PURE__ */ (0,
|
|
1235
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1095
1236
|
"button",
|
|
1096
1237
|
{
|
|
1097
1238
|
type: "button",
|
|
1098
1239
|
"data-vector-blend-action": "spine",
|
|
1099
|
-
className:
|
|
1240
|
+
className: buttonClass4,
|
|
1100
1241
|
title: "Replace Spine (select a blend and a path)",
|
|
1101
1242
|
"aria-label": "Replace Spine",
|
|
1102
1243
|
disabled: !blend.canReplaceSpine,
|
|
@@ -1104,15 +1245,15 @@ function VectorBlendControls({ controller }) {
|
|
|
1104
1245
|
children: "\u2307"
|
|
1105
1246
|
}
|
|
1106
1247
|
),
|
|
1107
|
-
/* @__PURE__ */ (0,
|
|
1108
|
-
/* @__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" })
|
|
1109
1250
|
] });
|
|
1110
1251
|
}
|
|
1111
|
-
var
|
|
1112
|
-
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";
|
|
1113
1254
|
function VectorStylePanel({ controller, className }) {
|
|
1114
1255
|
const state = useVectorEditorState(controller);
|
|
1115
|
-
const style = (0,
|
|
1256
|
+
const style = (0, import_vector7.getVectorSelectionStyle)(state);
|
|
1116
1257
|
const d = state.defaults;
|
|
1117
1258
|
const source = style ?? {
|
|
1118
1259
|
fill: d.fill ?? null,
|
|
@@ -1125,7 +1266,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1125
1266
|
arrowAlign: d.arrowAlign ?? "extend",
|
|
1126
1267
|
startArrowScale: d.startArrowScale ?? 1,
|
|
1127
1268
|
endArrowScale: d.endArrowScale ?? 1,
|
|
1128
|
-
widthProfile: (0,
|
|
1269
|
+
widthProfile: (0, import_vector7.widthProfilePresetId)(d.strokeWidthProfile),
|
|
1129
1270
|
cornerRadius: d.cornerRadius,
|
|
1130
1271
|
cornerKind: d.cornerKind ?? "round",
|
|
1131
1272
|
corners: 1,
|
|
@@ -1138,19 +1279,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1138
1279
|
};
|
|
1139
1280
|
const setProfile = (id) => {
|
|
1140
1281
|
if (style) controller.setWidthProfile(id);
|
|
1141
|
-
else controller.setDefaults({ strokeWidthProfile: (0,
|
|
1282
|
+
else controller.setDefaults({ strokeWidthProfile: (0, import_vector7.widthProfilePreset)(id)?.length ? (0, import_vector7.widthProfilePreset)(id) : null });
|
|
1142
1283
|
};
|
|
1143
|
-
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;
|
|
1144
1285
|
const arrowRow = (end, label) => {
|
|
1145
1286
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
1146
1287
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
1147
|
-
return /* @__PURE__ */ (0,
|
|
1148
|
-
/* @__PURE__ */ (0,
|
|
1149
|
-
/* @__PURE__ */ (0,
|
|
1150
|
-
/* @__PURE__ */ (0,
|
|
1151
|
-
|
|
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))
|
|
1152
1293
|
] }),
|
|
1153
|
-
/* @__PURE__ */ (0,
|
|
1294
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1154
1295
|
"input",
|
|
1155
1296
|
{
|
|
1156
1297
|
type: "number",
|
|
@@ -1158,7 +1299,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1158
1299
|
step: 0.25,
|
|
1159
1300
|
"aria-label": `${label} arrowhead scale`,
|
|
1160
1301
|
title: "Scale (\xD7 stroke width)",
|
|
1161
|
-
className:
|
|
1302
|
+
className: numberClass4,
|
|
1162
1303
|
value: source[scaleKey],
|
|
1163
1304
|
onChange: (e) => {
|
|
1164
1305
|
const n = parseFloat(e.target.value);
|
|
@@ -1174,14 +1315,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1174
1315
|
};
|
|
1175
1316
|
const paintRow = (key, label) => {
|
|
1176
1317
|
const paint = source[key];
|
|
1177
|
-
const hex = (0,
|
|
1318
|
+
const hex = (0, import_vector7.vectorPaintToHex)(paint);
|
|
1178
1319
|
const on = paint !== null && paint !== "none";
|
|
1179
|
-
return /* @__PURE__ */ (0,
|
|
1180
|
-
/* @__PURE__ */ (0,
|
|
1181
|
-
/* @__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 }) }),
|
|
1182
1323
|
label
|
|
1183
1324
|
] }),
|
|
1184
|
-
/* @__PURE__ */ (0,
|
|
1325
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1185
1326
|
"input",
|
|
1186
1327
|
{
|
|
1187
1328
|
type: "color",
|
|
@@ -1192,18 +1333,18 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1192
1333
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
1193
1334
|
}
|
|
1194
1335
|
),
|
|
1195
|
-
on && !hex && /* @__PURE__ */ (0,
|
|
1196
|
-
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" })
|
|
1197
1338
|
] });
|
|
1198
1339
|
};
|
|
1199
|
-
return /* @__PURE__ */ (0,
|
|
1200
|
-
/* @__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" }),
|
|
1201
1342
|
paintRow("fill", "Fill"),
|
|
1202
1343
|
paintRow("stroke", "Stroke"),
|
|
1203
|
-
style && /* @__PURE__ */ (0,
|
|
1204
|
-
/* @__PURE__ */ (0,
|
|
1205
|
-
/* @__PURE__ */ (0,
|
|
1206
|
-
/* @__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)(
|
|
1207
1348
|
"input",
|
|
1208
1349
|
{
|
|
1209
1350
|
type: "number",
|
|
@@ -1219,33 +1360,33 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1219
1360
|
}
|
|
1220
1361
|
)
|
|
1221
1362
|
] }),
|
|
1222
|
-
/* @__PURE__ */ (0,
|
|
1223
|
-
/* @__PURE__ */ (0,
|
|
1224
|
-
/* @__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)) }),
|
|
1225
1366
|
mixed("strokeAlign")
|
|
1226
1367
|
] }),
|
|
1227
|
-
/* @__PURE__ */ (0,
|
|
1228
|
-
/* @__PURE__ */ (0,
|
|
1229
|
-
/* @__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)(
|
|
1230
1371
|
"select",
|
|
1231
1372
|
{
|
|
1232
1373
|
"aria-label": "Width profile",
|
|
1233
|
-
className:
|
|
1374
|
+
className: selectClass4,
|
|
1234
1375
|
value: source.widthProfile,
|
|
1235
1376
|
onChange: (e) => {
|
|
1236
1377
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
1237
1378
|
},
|
|
1238
1379
|
children: [
|
|
1239
|
-
|
|
1240
|
-
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" })
|
|
1241
1382
|
]
|
|
1242
1383
|
}
|
|
1243
1384
|
),
|
|
1244
|
-
/* @__PURE__ */ (0,
|
|
1385
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
1245
1386
|
"button",
|
|
1246
1387
|
{
|
|
1247
1388
|
type: "button",
|
|
1248
|
-
className:
|
|
1389
|
+
className: buttonClass4,
|
|
1249
1390
|
title: "Reset to uniform width",
|
|
1250
1391
|
"aria-label": "Reset to uniform width",
|
|
1251
1392
|
disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
|
|
@@ -1255,27 +1396,27 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1255
1396
|
),
|
|
1256
1397
|
mixed("widthProfile")
|
|
1257
1398
|
] }),
|
|
1258
|
-
source.hasOpenPath && /* @__PURE__ */ (0,
|
|
1399
|
+
source.hasOpenPath && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1259
1400
|
arrowRow("start", "Start"),
|
|
1260
1401
|
arrowRow("end", "End"),
|
|
1261
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0,
|
|
1262
|
-
/* @__PURE__ */ (0,
|
|
1263
|
-
/* @__PURE__ */ (0,
|
|
1264
|
-
/* @__PURE__ */ (0,
|
|
1265
|
-
/* @__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" })
|
|
1266
1407
|
] })
|
|
1267
1408
|
] })
|
|
1268
1409
|
] }),
|
|
1269
|
-
source.corners > 0 && /* @__PURE__ */ (0,
|
|
1270
|
-
/* @__PURE__ */ (0,
|
|
1271
|
-
/* @__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)(
|
|
1272
1413
|
"input",
|
|
1273
1414
|
{
|
|
1274
1415
|
type: "number",
|
|
1275
1416
|
min: 0,
|
|
1276
1417
|
step: 1,
|
|
1277
1418
|
"aria-label": "Corner radius",
|
|
1278
|
-
className:
|
|
1419
|
+
className: numberClass4,
|
|
1279
1420
|
value: Math.round(source.cornerRadius * 100) / 100,
|
|
1280
1421
|
onChange: (e) => {
|
|
1281
1422
|
const n = parseFloat(e.target.value);
|
|
@@ -1283,12 +1424,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1283
1424
|
}
|
|
1284
1425
|
}
|
|
1285
1426
|
),
|
|
1286
|
-
/* @__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)) }),
|
|
1287
1428
|
mixed("cornerRadius")
|
|
1288
1429
|
] }),
|
|
1289
|
-
style && /* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1291
|
-
/* @__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)(
|
|
1292
1433
|
"input",
|
|
1293
1434
|
{
|
|
1294
1435
|
type: "range",
|
|
@@ -1302,18 +1443,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1302
1443
|
}
|
|
1303
1444
|
)
|
|
1304
1445
|
] }),
|
|
1305
|
-
style && /* @__PURE__ */ (0,
|
|
1446
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VectorEffectsPanel, { controller }),
|
|
1447
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VectorEnvelopePanel, { controller })
|
|
1306
1448
|
] });
|
|
1307
1449
|
}
|
|
1308
1450
|
|
|
1309
1451
|
// src/vector/VectorEditor.tsx
|
|
1310
|
-
var
|
|
1452
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
1311
1453
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }) {
|
|
1312
|
-
return /* @__PURE__ */ (0,
|
|
1313
|
-
/* @__PURE__ */ (0,
|
|
1314
|
-
/* @__PURE__ */ (0,
|
|
1315
|
-
/* @__PURE__ */ (0,
|
|
1316
|
-
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" })
|
|
1317
1459
|
] })
|
|
1318
1460
|
] });
|
|
1319
1461
|
}
|
|
@@ -1322,6 +1464,7 @@ function VectorEditor({ controller, tools, showStylePanel = true, height = 520,
|
|
|
1322
1464
|
VectorCanvas,
|
|
1323
1465
|
VectorEditor,
|
|
1324
1466
|
VectorEffectsPanel,
|
|
1467
|
+
VectorEnvelopePanel,
|
|
1325
1468
|
VectorGradientAnnotator,
|
|
1326
1469
|
VectorGradientDefs,
|
|
1327
1470
|
VectorGradientEditor,
|