@pixerate/editor-react 0.32.0 → 0.33.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 +323 -110
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +24 -5
- package/dist/vector/index.d.ts +24 -5
- package/dist/vector/index.js +320 -98
- package/dist/vector/index.js.map +1 -1
- package/package.json +3 -3
package/dist/vector/index.js
CHANGED
|
@@ -140,12 +140,50 @@ function VectorWidthPointEditor({ controller, edit, accentColor = THEME.accent,
|
|
|
140
140
|
|
|
141
141
|
// src/vector/VectorCanvas.tsx
|
|
142
142
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
143
|
+
function GradientElement({ def }) {
|
|
144
|
+
const stops = def.stops.map((s, i) => /* @__PURE__ */ jsx2("stop", { offset: s.offset, stopColor: s.stopColor, stopOpacity: s.stopOpacity }, i));
|
|
145
|
+
return def.type === "radial" ? /* @__PURE__ */ jsx2("radialGradient", { id: def.id, ...def.attrs, children: stops }) : /* @__PURE__ */ jsx2("linearGradient", { id: def.id, ...def.attrs, children: stops });
|
|
146
|
+
}
|
|
143
147
|
function VectorGradientDefs({ defs }) {
|
|
144
148
|
if (!defs.length) return null;
|
|
145
|
-
return /* @__PURE__ */ jsx2("defs", { children: defs.map(
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
+
return /* @__PURE__ */ jsx2("defs", { children: defs.map(
|
|
150
|
+
(def) => def.type === "pattern" ? /* @__PURE__ */ jsxs2("pattern", { id: def.id, ...def.attrs, children: [
|
|
151
|
+
def.gradients.map((g) => /* @__PURE__ */ jsx2(GradientElement, { def: g }, g.id)),
|
|
152
|
+
def.tiles.map((t, i) => /* @__PURE__ */ jsx2("path", { d: t.d, fill: t.fill }, i))
|
|
153
|
+
] }, def.id) : /* @__PURE__ */ jsx2(GradientElement, { def }, def.id)
|
|
154
|
+
) });
|
|
155
|
+
}
|
|
156
|
+
function VectorGradientAnnotator({ annotator: g, accentColor = THEME2.accent }) {
|
|
157
|
+
const r = THEME2.handleRadius + 1.5;
|
|
158
|
+
const ring = (p, part, size = r) => /* @__PURE__ */ jsx2("circle", { "data-vector-gradient-handle": part, cx: p.x, cy: p.y, r: size + (p.hovered ? 1 : 0), fill: THEME2.handleFill, stroke: accentColor, strokeWidth: p.hovered ? 2 : 1 });
|
|
159
|
+
return /* @__PURE__ */ jsxs2("g", { "data-vector-gradient-annotator": g.type, children: [
|
|
160
|
+
g.extent && /* @__PURE__ */ jsx2("path", { "data-vector-gradient-extent": "", d: g.extent, fill: "none", stroke: accentColor, strokeDasharray: "4 3" }),
|
|
161
|
+
/* @__PURE__ */ jsx2("line", { x1: g.start.x, y1: g.start.y, x2: g.end.x, y2: g.end.y, stroke: "#ffffff", strokeWidth: 3 }),
|
|
162
|
+
/* @__PURE__ */ jsx2("line", { "data-vector-gradient-bar": "", x1: g.start.x, y1: g.start.y, x2: g.end.x, y2: g.end.y, stroke: accentColor }),
|
|
163
|
+
g.aspect && /* @__PURE__ */ jsx2("line", { x1: g.start.x, y1: g.start.y, x2: g.aspect.x, y2: g.aspect.y, stroke: accentColor, strokeDasharray: "2 2" }),
|
|
164
|
+
ring(g.start, "start"),
|
|
165
|
+
/* @__PURE__ */ jsx2(
|
|
166
|
+
"rect",
|
|
167
|
+
{
|
|
168
|
+
"data-vector-gradient-handle": g.end.handle,
|
|
169
|
+
x: g.end.x - r,
|
|
170
|
+
y: g.end.y - r,
|
|
171
|
+
width: 2 * r,
|
|
172
|
+
height: 2 * r,
|
|
173
|
+
fill: THEME2.handleFill,
|
|
174
|
+
stroke: accentColor,
|
|
175
|
+
strokeWidth: g.end.hovered ? 2 : 1
|
|
176
|
+
}
|
|
177
|
+
),
|
|
178
|
+
g.aspect && ring(g.aspect, "aspect", THEME2.handleRadius),
|
|
179
|
+
g.focal && /* @__PURE__ */ jsx2("g", { "data-vector-gradient-handle": "focal", children: /* @__PURE__ */ jsx2("circle", { cx: g.focal.x, cy: g.focal.y, r: THEME2.handleRadius - 1 + (g.focal.hovered ? 1 : 0), fill: accentColor, stroke: THEME2.handleFill }) }),
|
|
180
|
+
g.midpoints.map((m) => /* @__PURE__ */ jsx2("path", { "data-vector-gradient-midpoint": m.index, d: vectorDiamondPath(m.x, m.y, 4 + (m.hovered ? 1 : 0)), fill: THEME2.handleFill, stroke: accentColor }, m.index)),
|
|
181
|
+
g.stops.map((s) => /* @__PURE__ */ jsxs2("g", { "data-vector-gradient-stop": s.index, "data-selected": s.selected || void 0, opacity: g.removing && s.selected ? 0.35 : 1, children: [
|
|
182
|
+
/* @__PURE__ */ jsx2("line", { x1: s.barX, y1: s.barY, x2: s.x, y2: s.y, stroke: accentColor }),
|
|
183
|
+
/* @__PURE__ */ jsx2("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 }),
|
|
184
|
+
/* @__PURE__ */ jsx2("rect", { x: s.x - 6.5, y: s.y - 6.5, width: 13, height: 13, rx: 3, fill: "none", stroke: s.selected ? "#ffffff" : accentColor })
|
|
185
|
+
] }, s.index))
|
|
186
|
+
] });
|
|
149
187
|
}
|
|
150
188
|
function VectorSceneNodes({ nodes }) {
|
|
151
189
|
return /* @__PURE__ */ jsx2(Fragment, { children: nodes.map(
|
|
@@ -369,6 +407,7 @@ function VectorCanvas({
|
|
|
369
407
|
},
|
|
370
408
|
`blend-anchor:${i}`
|
|
371
409
|
)),
|
|
410
|
+
overlay.gradient && /* @__PURE__ */ jsx2(VectorGradientAnnotator, { annotator: overlay.gradient, accentColor }),
|
|
372
411
|
overlay.widthSpot && /* @__PURE__ */ jsxs2("g", { "data-vector-width-spot": "", children: [
|
|
373
412
|
/* @__PURE__ */ jsx2("line", { x1: overlay.widthSpot.left.x, y1: overlay.widthSpot.left.y, x2: overlay.widthSpot.right.x, y2: overlay.widthSpot.right.y, stroke: accentColor, strokeDasharray: "3 2" }),
|
|
374
413
|
/* @__PURE__ */ jsx2("path", { d: vectorDiamondPath(overlay.widthSpot.x, overlay.widthSpot.y), fill: "none", stroke: accentColor })
|
|
@@ -496,7 +535,7 @@ import {
|
|
|
496
535
|
getVectorSelectionStyle,
|
|
497
536
|
widthProfilePreset,
|
|
498
537
|
widthProfilePresetId,
|
|
499
|
-
vectorPaintToHex,
|
|
538
|
+
vectorPaintToHex as vectorPaintToHex2,
|
|
500
539
|
vectorToolLabel
|
|
501
540
|
} from "@pixerate/editor/vector";
|
|
502
541
|
|
|
@@ -643,11 +682,191 @@ function VectorEffectsPanel({ controller, className }) {
|
|
|
643
682
|
] });
|
|
644
683
|
}
|
|
645
684
|
|
|
646
|
-
// src/vector/
|
|
685
|
+
// src/vector/VectorGradientEditor.tsx
|
|
686
|
+
import {
|
|
687
|
+
VECTOR_GRADIENT_TYPES,
|
|
688
|
+
VECTOR_GRADIENT_SPREADS,
|
|
689
|
+
VECTOR_GRADIENT_INTERPOLATIONS,
|
|
690
|
+
VECTOR_STROKE_GRADIENT_MODES,
|
|
691
|
+
VECTOR_GRADIENT_TYPE_LABELS,
|
|
692
|
+
VECTOR_GRADIENT_SPREAD_LABELS,
|
|
693
|
+
VECTOR_GRADIENT_INTERPOLATION_LABELS,
|
|
694
|
+
VECTOR_STROKE_GRADIENT_MODE_LABELS,
|
|
695
|
+
getVectorGradientEditor,
|
|
696
|
+
vectorPaintToHex
|
|
697
|
+
} from "@pixerate/editor/vector";
|
|
647
698
|
import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
699
|
+
var selectClass2 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
700
|
+
var numberClass2 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
701
|
+
var buttonClass2 = "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";
|
|
702
|
+
var percent = (v) => Math.round(v * 1e3) / 10;
|
|
703
|
+
function VectorGradientEditor({ controller, className }) {
|
|
704
|
+
const state = useVectorEditorState(controller);
|
|
705
|
+
const ed = getVectorGradientEditor(state);
|
|
706
|
+
if (!ed) return null;
|
|
707
|
+
const g = ed.gradient;
|
|
708
|
+
const sel = ed.selected;
|
|
709
|
+
const end = () => controller.endMergedEdit();
|
|
710
|
+
const setType = (value) => {
|
|
711
|
+
if (value === "solid") {
|
|
712
|
+
const first = ed.stops[0];
|
|
713
|
+
controller.setStyle({ [ed.target]: vectorPaintToHex(first?.color) ?? first?.color ?? "#000000" }, void 0, { label: "Solid Colour" });
|
|
714
|
+
} else controller.setGradient({ type: value });
|
|
715
|
+
};
|
|
716
|
+
return /* @__PURE__ */ jsxs4("div", { className: `space-y-1.5 ${className ?? ""}`, "data-vector-gradient-editor": ed.target, "aria-label": "Gradient", children: [
|
|
717
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5", children: [
|
|
718
|
+
/* @__PURE__ */ jsx4("span", { className: "w-16 text-xs text-foreground", children: "Gradient" }),
|
|
719
|
+
["fill", "stroke"].map((t) => /* @__PURE__ */ jsx4("button", { type: "button", className: buttonClass2, "aria-pressed": ed.target === t, onClick: () => controller.setGradientTarget(t), children: t === "fill" ? "Fill" : "Stroke" }, t)),
|
|
720
|
+
ed.mixed && /* @__PURE__ */ jsx4("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
721
|
+
] }),
|
|
722
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-1.5", children: [
|
|
723
|
+
/* @__PURE__ */ jsx4("span", { className: "w-16 text-xs text-foreground", children: "Type" }),
|
|
724
|
+
/* @__PURE__ */ jsxs4("select", { "aria-label": "Gradient type", className: selectClass2, value: ed.type ?? "solid", onChange: (e) => setType(e.target.value), children: [
|
|
725
|
+
/* @__PURE__ */ jsx4("option", { value: "solid", children: "Solid" }),
|
|
726
|
+
VECTOR_GRADIENT_TYPES.map((t) => /* @__PURE__ */ jsx4("option", { value: t, children: VECTOR_GRADIENT_TYPE_LABELS[t] }, t))
|
|
727
|
+
] }),
|
|
728
|
+
/* @__PURE__ */ jsx4("button", { type: "button", className: buttonClass2, "aria-label": "Reverse gradient", title: "Reverse gradient", disabled: !g, onClick: () => controller.reverseGradient(), children: "\u21C4" })
|
|
729
|
+
] }),
|
|
730
|
+
g && /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
731
|
+
/* @__PURE__ */ jsxs4("div", { className: "relative h-8", "data-vector-gradient-ramp": "", children: [
|
|
732
|
+
/* @__PURE__ */ jsx4(
|
|
733
|
+
"div",
|
|
734
|
+
{
|
|
735
|
+
role: "button",
|
|
736
|
+
tabIndex: -1,
|
|
737
|
+
"aria-label": "Add gradient stop",
|
|
738
|
+
className: "absolute inset-x-1.5 top-0 h-4 cursor-copy rounded border border-border",
|
|
739
|
+
style: { backgroundImage: `${ed.preview}, repeating-conic-gradient(#ddd 0% 25%, #fff 0% 50%)`, backgroundSize: "auto, 8px 8px" },
|
|
740
|
+
onClick: (e) => {
|
|
741
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
742
|
+
controller.addGradientStop(r.width > 0 ? Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) : 0.5);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
),
|
|
746
|
+
ed.stops.map((s) => /* @__PURE__ */ jsx4(
|
|
747
|
+
"button",
|
|
748
|
+
{
|
|
749
|
+
type: "button",
|
|
750
|
+
"data-vector-gradient-stop": s.index,
|
|
751
|
+
"aria-label": `Gradient stop ${s.index + 1} at ${percent(s.offset)}%`,
|
|
752
|
+
"aria-pressed": s.selected,
|
|
753
|
+
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",
|
|
754
|
+
style: { left: `calc(6px + (100% - 12px) * ${s.offset})`, background: s.color, opacity: 0.4 + 0.6 * (s.opacity ?? 1) },
|
|
755
|
+
onClick: () => controller.selectGradientStop(s.selected ? null : s.index)
|
|
756
|
+
},
|
|
757
|
+
s.index
|
|
758
|
+
))
|
|
759
|
+
] }),
|
|
760
|
+
sel && /* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center gap-1.5", "data-vector-gradient-selected-stop": sel.index, children: [
|
|
761
|
+
/* @__PURE__ */ jsx4(
|
|
762
|
+
"input",
|
|
763
|
+
{
|
|
764
|
+
type: "color",
|
|
765
|
+
"aria-label": "Stop colour",
|
|
766
|
+
className: "h-7 w-9 cursor-pointer rounded border border-border bg-background",
|
|
767
|
+
value: vectorPaintToHex(sel.color) ?? "#000000",
|
|
768
|
+
onChange: (e) => controller.setGradientStop(sel.index, { color: e.target.value }, { merge: `gradient-stop-color-${sel.index}` }),
|
|
769
|
+
onBlur: end
|
|
770
|
+
}
|
|
771
|
+
),
|
|
772
|
+
/* @__PURE__ */ jsxs4("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
773
|
+
"Opacity",
|
|
774
|
+
/* @__PURE__ */ jsx4(
|
|
775
|
+
"input",
|
|
776
|
+
{
|
|
777
|
+
type: "number",
|
|
778
|
+
min: 0,
|
|
779
|
+
max: 100,
|
|
780
|
+
step: 5,
|
|
781
|
+
"aria-label": "Stop opacity",
|
|
782
|
+
className: numberClass2,
|
|
783
|
+
value: percent(sel.opacity ?? 1),
|
|
784
|
+
onChange: (e) => {
|
|
785
|
+
const n = parseFloat(e.target.value);
|
|
786
|
+
if (Number.isFinite(n)) controller.setGradientStop(sel.index, { opacity: n / 100 });
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
)
|
|
790
|
+
] }),
|
|
791
|
+
/* @__PURE__ */ jsxs4("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
792
|
+
"At",
|
|
793
|
+
/* @__PURE__ */ jsx4(
|
|
794
|
+
"input",
|
|
795
|
+
{
|
|
796
|
+
type: "number",
|
|
797
|
+
min: 0,
|
|
798
|
+
max: 100,
|
|
799
|
+
step: 1,
|
|
800
|
+
"aria-label": "Stop position",
|
|
801
|
+
className: numberClass2,
|
|
802
|
+
value: percent(sel.offset),
|
|
803
|
+
onChange: (e) => {
|
|
804
|
+
const n = parseFloat(e.target.value);
|
|
805
|
+
if (Number.isFinite(n)) controller.setGradientStop(sel.index, { offset: n / 100 });
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
)
|
|
809
|
+
] }),
|
|
810
|
+
!sel.last && /* @__PURE__ */ jsxs4("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
811
|
+
"Midpoint",
|
|
812
|
+
/* @__PURE__ */ jsx4(
|
|
813
|
+
"input",
|
|
814
|
+
{
|
|
815
|
+
type: "number",
|
|
816
|
+
min: 5,
|
|
817
|
+
max: 95,
|
|
818
|
+
step: 1,
|
|
819
|
+
"aria-label": "Stop midpoint",
|
|
820
|
+
className: numberClass2,
|
|
821
|
+
value: percent(sel.midpoint ?? 0.5),
|
|
822
|
+
onChange: (e) => {
|
|
823
|
+
const n = parseFloat(e.target.value);
|
|
824
|
+
if (Number.isFinite(n)) controller.setGradientStop(sel.index, { midpoint: n / 100 });
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
)
|
|
828
|
+
] }),
|
|
829
|
+
/* @__PURE__ */ jsx4("button", { type: "button", className: buttonClass2, "aria-label": "Delete stop", title: "Delete stop", disabled: ed.stops.length <= 2, onClick: () => controller.removeGradientStop(sel.index), children: "\u2715" })
|
|
830
|
+
] }),
|
|
831
|
+
/* @__PURE__ */ jsxs4("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
832
|
+
/* @__PURE__ */ jsx4("span", { className: "w-16", children: "Colours" }),
|
|
833
|
+
/* @__PURE__ */ jsx4("select", { "aria-label": "Gradient interpolation", className: selectClass2, value: ed.interpolation, onChange: (e) => controller.setGradient({ interpolation: e.target.value }), children: VECTOR_GRADIENT_INTERPOLATIONS.map((i) => /* @__PURE__ */ jsx4("option", { value: i, children: VECTOR_GRADIENT_INTERPOLATION_LABELS[i] }, i)) })
|
|
834
|
+
] }),
|
|
835
|
+
/* @__PURE__ */ jsxs4("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
836
|
+
/* @__PURE__ */ jsx4("span", { className: "w-16", children: "Smooth" }),
|
|
837
|
+
/* @__PURE__ */ jsx4(
|
|
838
|
+
"input",
|
|
839
|
+
{
|
|
840
|
+
type: "range",
|
|
841
|
+
min: 0,
|
|
842
|
+
max: 1,
|
|
843
|
+
step: 0.05,
|
|
844
|
+
"aria-label": "Gradient smoothness",
|
|
845
|
+
className: "h-4 flex-1 accent-primary",
|
|
846
|
+
value: ed.smoothness,
|
|
847
|
+
onChange: (e) => controller.setGradient({ smoothness: parseFloat(e.target.value) }, { merge: "gradient-smoothness" }),
|
|
848
|
+
onPointerUp: end,
|
|
849
|
+
onBlur: end
|
|
850
|
+
}
|
|
851
|
+
)
|
|
852
|
+
] }),
|
|
853
|
+
/* @__PURE__ */ jsxs4("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
854
|
+
/* @__PURE__ */ jsx4("span", { className: "w-16", children: "Spread" }),
|
|
855
|
+
/* @__PURE__ */ jsx4("select", { "aria-label": "Gradient spread", className: selectClass2, value: ed.spread, onChange: (e) => controller.setGradient({ spread: e.target.value }), children: VECTOR_GRADIENT_SPREADS.map((sp) => /* @__PURE__ */ jsx4("option", { value: sp, children: VECTOR_GRADIENT_SPREAD_LABELS[sp] }, sp)) })
|
|
856
|
+
] }),
|
|
857
|
+
ed.target === "stroke" && /* @__PURE__ */ jsxs4("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
858
|
+
/* @__PURE__ */ jsx4("span", { className: "w-16", children: "On stroke" }),
|
|
859
|
+
/* @__PURE__ */ jsx4("select", { "aria-label": "Gradient on stroke", className: selectClass2, value: ed.strokeMode, onChange: (e) => controller.setGradient({ strokeMode: e.target.value }), children: VECTOR_STROKE_GRADIENT_MODES.map((m) => /* @__PURE__ */ jsx4("option", { value: m, children: VECTOR_STROKE_GRADIENT_MODE_LABELS[m] }, m)) })
|
|
860
|
+
] })
|
|
861
|
+
] })
|
|
862
|
+
] });
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
// src/vector/VectorToolbar.tsx
|
|
866
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
648
867
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
649
868
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
650
|
-
var
|
|
869
|
+
var buttonClass3 = "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";
|
|
651
870
|
function VectorToolbar({
|
|
652
871
|
controller,
|
|
653
872
|
tools = VECTOR_TOOLS,
|
|
@@ -665,14 +884,14 @@ function VectorToolbar({
|
|
|
665
884
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
666
885
|
const [live, setLive] = React3.useState(false);
|
|
667
886
|
const booleanDisabled = live ? count < 1 : count < 2;
|
|
668
|
-
const act = (label, title, run, disabled = false) => /* @__PURE__ */
|
|
669
|
-
return /* @__PURE__ */
|
|
670
|
-
/* @__PURE__ */
|
|
887
|
+
const act = (label, title, run, disabled = false) => /* @__PURE__ */ jsx5("button", { type: "button", className: buttonClass3, title, "aria-label": title, disabled, onClick: () => void run(), children: label }, label);
|
|
888
|
+
return /* @__PURE__ */ jsxs5("div", { role: "toolbar", "aria-label": "Vector tools", className: `flex flex-wrap items-center gap-1 ${className ?? ""}`, children: [
|
|
889
|
+
/* @__PURE__ */ jsx5("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Tools", children: tools.map((tool) => /* @__PURE__ */ jsx5(
|
|
671
890
|
"button",
|
|
672
891
|
{
|
|
673
892
|
type: "button",
|
|
674
893
|
"data-vector-tool": tool,
|
|
675
|
-
className:
|
|
894
|
+
className: buttonClass3,
|
|
676
895
|
"aria-pressed": state.tool === tool,
|
|
677
896
|
title: `${vectorToolLabel(tool)} (${VECTOR_TOOL_SHORTCUTS[tool]})`,
|
|
678
897
|
"aria-label": vectorToolLabel(tool),
|
|
@@ -681,16 +900,16 @@ function VectorToolbar({
|
|
|
681
900
|
},
|
|
682
901
|
tool
|
|
683
902
|
)) }),
|
|
684
|
-
showHistory && /* @__PURE__ */
|
|
903
|
+
showHistory && /* @__PURE__ */ jsxs5("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "History", children: [
|
|
685
904
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
686
905
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
687
906
|
] }),
|
|
688
|
-
showSnap && /* @__PURE__ */
|
|
907
|
+
showSnap && /* @__PURE__ */ jsx5("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Snapping", children: /* @__PURE__ */ jsx5(
|
|
689
908
|
"button",
|
|
690
909
|
{
|
|
691
910
|
type: "button",
|
|
692
911
|
"data-vector-snap": "",
|
|
693
|
-
className:
|
|
912
|
+
className: buttonClass3,
|
|
694
913
|
"aria-pressed": state.snap.objects,
|
|
695
914
|
title: `${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`,
|
|
696
915
|
"aria-label": VECTOR_SNAP_TITLE,
|
|
@@ -698,13 +917,13 @@ function VectorToolbar({
|
|
|
698
917
|
children: "Snap"
|
|
699
918
|
}
|
|
700
919
|
) }),
|
|
701
|
-
showPathEdit && /* @__PURE__ */
|
|
702
|
-
VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */
|
|
920
|
+
showPathEdit && /* @__PURE__ */ jsxs5("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Path editing", children: [
|
|
921
|
+
VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */ jsx5(
|
|
703
922
|
"button",
|
|
704
923
|
{
|
|
705
924
|
type: "button",
|
|
706
925
|
"data-vector-path-action": a.id,
|
|
707
|
-
className:
|
|
926
|
+
className: buttonClass3,
|
|
708
927
|
title: a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title,
|
|
709
928
|
"aria-label": a.title,
|
|
710
929
|
disabled: !a.enabled(count, points),
|
|
@@ -713,12 +932,12 @@ function VectorToolbar({
|
|
|
713
932
|
},
|
|
714
933
|
a.id
|
|
715
934
|
)),
|
|
716
|
-
VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */
|
|
935
|
+
VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ jsx5(
|
|
717
936
|
"button",
|
|
718
937
|
{
|
|
719
938
|
type: "button",
|
|
720
939
|
"data-vector-edit": t.key,
|
|
721
|
-
className:
|
|
940
|
+
className: buttonClass3,
|
|
722
941
|
"aria-pressed": editing[t.key],
|
|
723
942
|
title: t.title,
|
|
724
943
|
"aria-label": t.title,
|
|
@@ -727,9 +946,9 @@ function VectorToolbar({
|
|
|
727
946
|
},
|
|
728
947
|
t.key
|
|
729
948
|
)),
|
|
730
|
-
state.tool === "pencil" && /* @__PURE__ */
|
|
949
|
+
state.tool === "pencil" && /* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
731
950
|
"Smoothing",
|
|
732
|
-
/* @__PURE__ */
|
|
951
|
+
/* @__PURE__ */ jsx5(
|
|
733
952
|
"input",
|
|
734
953
|
{
|
|
735
954
|
type: "range",
|
|
@@ -743,9 +962,9 @@ function VectorToolbar({
|
|
|
743
962
|
}
|
|
744
963
|
)
|
|
745
964
|
] }),
|
|
746
|
-
state.tool === "eraser" && /* @__PURE__ */
|
|
965
|
+
state.tool === "eraser" && /* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
747
966
|
"Size",
|
|
748
|
-
/* @__PURE__ */
|
|
967
|
+
/* @__PURE__ */ jsx5(
|
|
749
968
|
"input",
|
|
750
969
|
{
|
|
751
970
|
type: "number",
|
|
@@ -761,12 +980,12 @@ function VectorToolbar({
|
|
|
761
980
|
}
|
|
762
981
|
)
|
|
763
982
|
] }),
|
|
764
|
-
state.tool === "paintBucket" && /* @__PURE__ */
|
|
983
|
+
state.tool === "paintBucket" && /* @__PURE__ */ jsx5(
|
|
765
984
|
"button",
|
|
766
985
|
{
|
|
767
986
|
type: "button",
|
|
768
987
|
"data-vector-fill-gap": "",
|
|
769
|
-
className:
|
|
988
|
+
className: buttonClass3,
|
|
770
989
|
"aria-pressed": editing.fillGap > 0,
|
|
771
990
|
title: "Close small gaps between path ends when filling",
|
|
772
991
|
"aria-label": "Close gaps",
|
|
@@ -775,15 +994,15 @@ function VectorToolbar({
|
|
|
775
994
|
}
|
|
776
995
|
)
|
|
777
996
|
] }),
|
|
778
|
-
showBlend && /* @__PURE__ */
|
|
779
|
-
showArrange && /* @__PURE__ */
|
|
780
|
-
/* @__PURE__ */
|
|
781
|
-
/* @__PURE__ */
|
|
997
|
+
showBlend && /* @__PURE__ */ jsx5(VectorBlendControls, { controller }),
|
|
998
|
+
showArrange && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
999
|
+
/* @__PURE__ */ jsxs5("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
|
|
1000
|
+
/* @__PURE__ */ jsx5(
|
|
782
1001
|
"button",
|
|
783
1002
|
{
|
|
784
1003
|
type: "button",
|
|
785
1004
|
"data-vector-live-boolean": "",
|
|
786
|
-
className:
|
|
1005
|
+
className: buttonClass3,
|
|
787
1006
|
"aria-pressed": live,
|
|
788
1007
|
title: "Live booleans: keep the shapes editable",
|
|
789
1008
|
"aria-label": "Live booleans",
|
|
@@ -798,12 +1017,12 @@ function VectorToolbar({
|
|
|
798
1017
|
act("G", "Group", () => controller.group(), count < 1),
|
|
799
1018
|
act("U", "Ungroup", () => controller.ungroup(), !groupSelected)
|
|
800
1019
|
] }),
|
|
801
|
-
/* @__PURE__ */
|
|
1020
|
+
/* @__PURE__ */ jsx5("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ jsx5(
|
|
802
1021
|
"button",
|
|
803
1022
|
{
|
|
804
1023
|
type: "button",
|
|
805
1024
|
"data-vector-pathfinder": a.id,
|
|
806
|
-
className:
|
|
1025
|
+
className: buttonClass3,
|
|
807
1026
|
title: a.title,
|
|
808
1027
|
"aria-label": a.title,
|
|
809
1028
|
disabled: count < a.min,
|
|
@@ -812,7 +1031,7 @@ function VectorToolbar({
|
|
|
812
1031
|
},
|
|
813
1032
|
a.id
|
|
814
1033
|
)) }),
|
|
815
|
-
/* @__PURE__ */
|
|
1034
|
+
/* @__PURE__ */ jsxs5("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
816
1035
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
817
1036
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
818
1037
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -830,19 +1049,19 @@ function VectorBlendControls({ controller }) {
|
|
|
830
1049
|
const blend = getVectorBlendControls(state);
|
|
831
1050
|
const o = blend.options;
|
|
832
1051
|
const selected = blend.ids.length > 0;
|
|
833
|
-
return /* @__PURE__ */
|
|
834
|
-
/* @__PURE__ */
|
|
835
|
-
/* @__PURE__ */
|
|
1052
|
+
return /* @__PURE__ */ jsxs5("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Blend", "data-vector-blend-controls": "", children: [
|
|
1053
|
+
/* @__PURE__ */ jsx5("button", { type: "button", "data-vector-blend-action": "make", className: buttonClass3, title: "Make Blend", "aria-label": "Make Blend", disabled: !blend.canBlend, onClick: () => controller.blend(), children: "\u29D3" }),
|
|
1054
|
+
/* @__PURE__ */ jsx5(
|
|
836
1055
|
"select",
|
|
837
1056
|
{
|
|
838
1057
|
"aria-label": "Blend spacing",
|
|
839
1058
|
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
840
1059
|
value: o.spacing,
|
|
841
1060
|
onChange: (e) => applyVectorBlendOptions(controller, { spacing: e.target.value }),
|
|
842
|
-
children: VECTOR_BLEND_SPACINGS.map((sp) => /* @__PURE__ */
|
|
1061
|
+
children: VECTOR_BLEND_SPACINGS.map((sp) => /* @__PURE__ */ jsx5("option", { value: sp, children: VECTOR_BLEND_SPACING_LABELS[sp] }, sp))
|
|
843
1062
|
}
|
|
844
1063
|
),
|
|
845
|
-
o.spacing !== "smoothColor" && /* @__PURE__ */
|
|
1064
|
+
o.spacing !== "smoothColor" && /* @__PURE__ */ jsx5(
|
|
846
1065
|
"input",
|
|
847
1066
|
{
|
|
848
1067
|
type: "number",
|
|
@@ -858,12 +1077,12 @@ function VectorBlendControls({ controller }) {
|
|
|
858
1077
|
}
|
|
859
1078
|
}
|
|
860
1079
|
),
|
|
861
|
-
/* @__PURE__ */
|
|
1080
|
+
/* @__PURE__ */ jsx5(
|
|
862
1081
|
"button",
|
|
863
1082
|
{
|
|
864
1083
|
type: "button",
|
|
865
1084
|
"data-vector-blend-action": "orient",
|
|
866
|
-
className:
|
|
1085
|
+
className: buttonClass3,
|
|
867
1086
|
"aria-pressed": o.orientToSpine,
|
|
868
1087
|
title: "Orient steps to the spine",
|
|
869
1088
|
"aria-label": "Orient to spine",
|
|
@@ -871,12 +1090,12 @@ function VectorBlendControls({ controller }) {
|
|
|
871
1090
|
children: "\u293F"
|
|
872
1091
|
}
|
|
873
1092
|
),
|
|
874
|
-
/* @__PURE__ */
|
|
1093
|
+
/* @__PURE__ */ jsx5(
|
|
875
1094
|
"button",
|
|
876
1095
|
{
|
|
877
1096
|
type: "button",
|
|
878
1097
|
"data-vector-blend-action": "spine",
|
|
879
|
-
className:
|
|
1098
|
+
className: buttonClass3,
|
|
880
1099
|
title: "Replace Spine (select a blend and a path)",
|
|
881
1100
|
"aria-label": "Replace Spine",
|
|
882
1101
|
disabled: !blend.canReplaceSpine,
|
|
@@ -884,12 +1103,12 @@ function VectorBlendControls({ controller }) {
|
|
|
884
1103
|
children: "\u2307"
|
|
885
1104
|
}
|
|
886
1105
|
),
|
|
887
|
-
/* @__PURE__ */
|
|
888
|
-
/* @__PURE__ */
|
|
1106
|
+
/* @__PURE__ */ jsx5("button", { type: "button", "data-vector-blend-action": "expand", className: buttonClass3, title: "Expand Blend", "aria-label": "Expand Blend", disabled: !selected, onClick: () => controller.expandBlend(), children: "\u29C9" }),
|
|
1107
|
+
/* @__PURE__ */ jsx5("button", { type: "button", "data-vector-blend-action": "release", className: buttonClass3, title: "Release Blend", "aria-label": "Release Blend", disabled: !selected, onClick: () => controller.releaseBlend(), children: "\u29C4" })
|
|
889
1108
|
] });
|
|
890
1109
|
}
|
|
891
|
-
var
|
|
892
|
-
var
|
|
1110
|
+
var selectClass3 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
1111
|
+
var numberClass3 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
893
1112
|
function VectorStylePanel({ controller, className }) {
|
|
894
1113
|
const state = useVectorEditorState(controller);
|
|
895
1114
|
const style = getVectorSelectionStyle(state);
|
|
@@ -920,17 +1139,17 @@ function VectorStylePanel({ controller, className }) {
|
|
|
920
1139
|
if (style) controller.setWidthProfile(id);
|
|
921
1140
|
else controller.setDefaults({ strokeWidthProfile: widthProfilePreset(id)?.length ? widthProfilePreset(id) : null });
|
|
922
1141
|
};
|
|
923
|
-
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */
|
|
1142
|
+
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ jsx5("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
|
|
924
1143
|
const arrowRow = (end, label) => {
|
|
925
1144
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
926
1145
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
927
|
-
return /* @__PURE__ */
|
|
928
|
-
/* @__PURE__ */
|
|
929
|
-
/* @__PURE__ */
|
|
930
|
-
/* @__PURE__ */
|
|
931
|
-
VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */
|
|
1146
|
+
return /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
1147
|
+
/* @__PURE__ */ jsx5("span", { className: "w-16 text-xs text-foreground", children: label }),
|
|
1148
|
+
/* @__PURE__ */ jsxs5("select", { "aria-label": `${label} arrowhead`, className: selectClass3, value: source[key] ?? "", onChange: (e) => apply({ [key]: e.target.value || null }), children: [
|
|
1149
|
+
/* @__PURE__ */ jsx5("option", { value: "", children: "None" }),
|
|
1150
|
+
VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */ jsx5("option", { value: h, children: VECTOR_ARROWHEAD_LABELS[h] }, h))
|
|
932
1151
|
] }),
|
|
933
|
-
/* @__PURE__ */
|
|
1152
|
+
/* @__PURE__ */ jsx5(
|
|
934
1153
|
"input",
|
|
935
1154
|
{
|
|
936
1155
|
type: "number",
|
|
@@ -938,7 +1157,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
938
1157
|
step: 0.25,
|
|
939
1158
|
"aria-label": `${label} arrowhead scale`,
|
|
940
1159
|
title: "Scale (\xD7 stroke width)",
|
|
941
|
-
className:
|
|
1160
|
+
className: numberClass3,
|
|
942
1161
|
value: source[scaleKey],
|
|
943
1162
|
onChange: (e) => {
|
|
944
1163
|
const n = parseFloat(e.target.value);
|
|
@@ -954,14 +1173,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
954
1173
|
};
|
|
955
1174
|
const paintRow = (key, label) => {
|
|
956
1175
|
const paint = source[key];
|
|
957
|
-
const hex =
|
|
1176
|
+
const hex = vectorPaintToHex2(paint);
|
|
958
1177
|
const on = paint !== null && paint !== "none";
|
|
959
|
-
return /* @__PURE__ */
|
|
960
|
-
/* @__PURE__ */
|
|
961
|
-
/* @__PURE__ */
|
|
1178
|
+
return /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
1179
|
+
/* @__PURE__ */ jsxs5("label", { className: "flex w-16 items-center gap-1.5 text-xs text-foreground", children: [
|
|
1180
|
+
/* @__PURE__ */ jsx5("input", { type: "checkbox", checked: on, "aria-label": `${label} on`, onChange: (e) => apply({ [key]: e.target.checked ? hex ?? "#000000" : null }) }),
|
|
962
1181
|
label
|
|
963
1182
|
] }),
|
|
964
|
-
/* @__PURE__ */
|
|
1183
|
+
/* @__PURE__ */ jsx5(
|
|
965
1184
|
"input",
|
|
966
1185
|
{
|
|
967
1186
|
type: "color",
|
|
@@ -972,17 +1191,18 @@ function VectorStylePanel({ controller, className }) {
|
|
|
972
1191
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
973
1192
|
}
|
|
974
1193
|
),
|
|
975
|
-
on && !hex && /* @__PURE__ */
|
|
976
|
-
style?.mixed[key] && /* @__PURE__ */
|
|
1194
|
+
on && !hex && /* @__PURE__ */ jsx5("span", { className: "truncate text-[11px] text-muted-foreground", children: typeof paint === "string" ? paint : "Gradient" }),
|
|
1195
|
+
style?.mixed[key] && /* @__PURE__ */ jsx5("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
977
1196
|
] });
|
|
978
1197
|
};
|
|
979
|
-
return /* @__PURE__ */
|
|
980
|
-
/* @__PURE__ */
|
|
1198
|
+
return /* @__PURE__ */ jsxs5("div", { className: `space-y-2 ${className ?? ""}`, "aria-label": style ? "Selection style" : "New shape style", children: [
|
|
1199
|
+
/* @__PURE__ */ jsx5("p", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: style ? "Selection" : "New shapes" }),
|
|
981
1200
|
paintRow("fill", "Fill"),
|
|
982
1201
|
paintRow("stroke", "Stroke"),
|
|
983
|
-
/* @__PURE__ */
|
|
984
|
-
|
|
985
|
-
/* @__PURE__ */
|
|
1202
|
+
style && /* @__PURE__ */ jsx5(VectorGradientEditor, { controller }),
|
|
1203
|
+
/* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
1204
|
+
/* @__PURE__ */ jsx5("span", { className: "w-16", children: "Width" }),
|
|
1205
|
+
/* @__PURE__ */ jsx5(
|
|
986
1206
|
"input",
|
|
987
1207
|
{
|
|
988
1208
|
type: "number",
|
|
@@ -998,33 +1218,33 @@ function VectorStylePanel({ controller, className }) {
|
|
|
998
1218
|
}
|
|
999
1219
|
)
|
|
1000
1220
|
] }),
|
|
1001
|
-
/* @__PURE__ */
|
|
1002
|
-
/* @__PURE__ */
|
|
1003
|
-
/* @__PURE__ */
|
|
1221
|
+
/* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "strokeAlign", children: [
|
|
1222
|
+
/* @__PURE__ */ jsx5("span", { className: "w-16", children: "Align" }),
|
|
1223
|
+
/* @__PURE__ */ jsx5("select", { "aria-label": "Stroke alignment", className: selectClass3, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(VECTOR_STROKE_ALIGN_LABELS).map((a) => /* @__PURE__ */ jsx5("option", { value: a, children: VECTOR_STROKE_ALIGN_LABELS[a] }, a)) }),
|
|
1004
1224
|
mixed("strokeAlign")
|
|
1005
1225
|
] }),
|
|
1006
|
-
/* @__PURE__ */
|
|
1007
|
-
/* @__PURE__ */
|
|
1008
|
-
/* @__PURE__ */
|
|
1226
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
|
|
1227
|
+
/* @__PURE__ */ jsx5("span", { className: "w-16", children: "Profile" }),
|
|
1228
|
+
/* @__PURE__ */ jsxs5(
|
|
1009
1229
|
"select",
|
|
1010
1230
|
{
|
|
1011
1231
|
"aria-label": "Width profile",
|
|
1012
|
-
className:
|
|
1232
|
+
className: selectClass3,
|
|
1013
1233
|
value: source.widthProfile,
|
|
1014
1234
|
onChange: (e) => {
|
|
1015
1235
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
1016
1236
|
},
|
|
1017
1237
|
children: [
|
|
1018
|
-
VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */
|
|
1019
|
-
source.widthProfile === "custom" && /* @__PURE__ */
|
|
1238
|
+
VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ jsx5("option", { value: p.id, children: p.label }, p.id)),
|
|
1239
|
+
source.widthProfile === "custom" && /* @__PURE__ */ jsx5("option", { value: "custom", disabled: true, children: "Custom" })
|
|
1020
1240
|
]
|
|
1021
1241
|
}
|
|
1022
1242
|
),
|
|
1023
|
-
/* @__PURE__ */
|
|
1243
|
+
/* @__PURE__ */ jsx5(
|
|
1024
1244
|
"button",
|
|
1025
1245
|
{
|
|
1026
1246
|
type: "button",
|
|
1027
|
-
className:
|
|
1247
|
+
className: buttonClass3,
|
|
1028
1248
|
title: "Reset to uniform width",
|
|
1029
1249
|
"aria-label": "Reset to uniform width",
|
|
1030
1250
|
disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
|
|
@@ -1034,27 +1254,27 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1034
1254
|
),
|
|
1035
1255
|
mixed("widthProfile")
|
|
1036
1256
|
] }),
|
|
1037
|
-
source.hasOpenPath && /* @__PURE__ */
|
|
1257
|
+
source.hasOpenPath && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1038
1258
|
arrowRow("start", "Start"),
|
|
1039
1259
|
arrowRow("end", "End"),
|
|
1040
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */
|
|
1041
|
-
/* @__PURE__ */
|
|
1042
|
-
/* @__PURE__ */
|
|
1043
|
-
/* @__PURE__ */
|
|
1044
|
-
/* @__PURE__ */
|
|
1260
|
+
(source.startArrow || source.endArrow) && /* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "arrowAlign", children: [
|
|
1261
|
+
/* @__PURE__ */ jsx5("span", { className: "w-16", children: "Heads" }),
|
|
1262
|
+
/* @__PURE__ */ jsxs5("select", { "aria-label": "Arrowhead alignment", className: selectClass3, value: source.arrowAlign, onChange: (e) => apply({ arrowAlign: e.target.value }), children: [
|
|
1263
|
+
/* @__PURE__ */ jsx5("option", { value: "extend", children: "Tip past end" }),
|
|
1264
|
+
/* @__PURE__ */ jsx5("option", { value: "tip", children: "Tip at end" })
|
|
1045
1265
|
] })
|
|
1046
1266
|
] })
|
|
1047
1267
|
] }),
|
|
1048
|
-
source.corners > 0 && /* @__PURE__ */
|
|
1049
|
-
/* @__PURE__ */
|
|
1050
|
-
/* @__PURE__ */
|
|
1268
|
+
source.corners > 0 && /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", "data-vector-style": "corners", children: [
|
|
1269
|
+
/* @__PURE__ */ jsx5("span", { className: "w-16 text-xs text-foreground", children: "Corners" }),
|
|
1270
|
+
/* @__PURE__ */ jsx5(
|
|
1051
1271
|
"input",
|
|
1052
1272
|
{
|
|
1053
1273
|
type: "number",
|
|
1054
1274
|
min: 0,
|
|
1055
1275
|
step: 1,
|
|
1056
1276
|
"aria-label": "Corner radius",
|
|
1057
|
-
className:
|
|
1277
|
+
className: numberClass3,
|
|
1058
1278
|
value: Math.round(source.cornerRadius * 100) / 100,
|
|
1059
1279
|
onChange: (e) => {
|
|
1060
1280
|
const n = parseFloat(e.target.value);
|
|
@@ -1062,12 +1282,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1062
1282
|
}
|
|
1063
1283
|
}
|
|
1064
1284
|
),
|
|
1065
|
-
/* @__PURE__ */
|
|
1285
|
+
/* @__PURE__ */ jsx5("select", { "aria-label": "Corner kind", className: selectClass3, value: source.cornerKind, onChange: (e) => setCorners({ kind: e.target.value }), children: VECTOR_CORNER_KINDS.map((k) => /* @__PURE__ */ jsx5("option", { value: k, children: VECTOR_CORNER_KIND_LABELS[k] }, k)) }),
|
|
1066
1286
|
mixed("cornerRadius")
|
|
1067
1287
|
] }),
|
|
1068
|
-
style && /* @__PURE__ */
|
|
1069
|
-
/* @__PURE__ */
|
|
1070
|
-
/* @__PURE__ */
|
|
1288
|
+
style && /* @__PURE__ */ jsxs5("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
1289
|
+
/* @__PURE__ */ jsx5("span", { className: "w-16", children: "Opacity" }),
|
|
1290
|
+
/* @__PURE__ */ jsx5(
|
|
1071
1291
|
"input",
|
|
1072
1292
|
{
|
|
1073
1293
|
type: "range",
|
|
@@ -1081,18 +1301,18 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1081
1301
|
}
|
|
1082
1302
|
)
|
|
1083
1303
|
] }),
|
|
1084
|
-
style && /* @__PURE__ */
|
|
1304
|
+
style && /* @__PURE__ */ jsx5(VectorEffectsPanel, { controller })
|
|
1085
1305
|
] });
|
|
1086
1306
|
}
|
|
1087
1307
|
|
|
1088
1308
|
// src/vector/VectorEditor.tsx
|
|
1089
|
-
import { jsx as
|
|
1309
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1090
1310
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }) {
|
|
1091
|
-
return /* @__PURE__ */
|
|
1092
|
-
/* @__PURE__ */
|
|
1093
|
-
/* @__PURE__ */
|
|
1094
|
-
/* @__PURE__ */
|
|
1095
|
-
showStylePanel && /* @__PURE__ */
|
|
1311
|
+
return /* @__PURE__ */ jsxs6("div", { className: `flex flex-col gap-2 ${className ?? ""}`, "data-vector-editor": "", children: [
|
|
1312
|
+
/* @__PURE__ */ jsx6(VectorToolbar, { controller, tools }),
|
|
1313
|
+
/* @__PURE__ */ jsxs6("div", { className: "flex min-h-0 flex-col gap-2 md:flex-row", children: [
|
|
1314
|
+
/* @__PURE__ */ jsx6("div", { className: "relative min-h-[320px] flex-1 overflow-hidden rounded-md border border-border bg-muted/40", style: { height }, children: /* @__PURE__ */ jsx6(VectorCanvas, { controller, ...canvasProps }) }),
|
|
1315
|
+
showStylePanel && /* @__PURE__ */ jsx6(VectorStylePanel, { controller, className: "w-full shrink-0 rounded-md border border-border p-3 md:w-56" })
|
|
1096
1316
|
] })
|
|
1097
1317
|
] });
|
|
1098
1318
|
}
|
|
@@ -1100,7 +1320,9 @@ export {
|
|
|
1100
1320
|
VectorCanvas,
|
|
1101
1321
|
VectorEditor,
|
|
1102
1322
|
VectorEffectsPanel,
|
|
1323
|
+
VectorGradientAnnotator,
|
|
1103
1324
|
VectorGradientDefs,
|
|
1325
|
+
VectorGradientEditor,
|
|
1104
1326
|
VectorSceneNodes,
|
|
1105
1327
|
VectorStylePanel,
|
|
1106
1328
|
VectorToolbar,
|