@pixerate/editor-react 0.31.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 +494 -110
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +36 -5
- package/dist/vector/index.d.ts +36 -5
- package/dist/vector/index.js +485 -100
- package/dist/vector/index.js.map +1 -1
- package/package.json +3 -3
package/dist/vector/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/vector/index.ts
|
|
@@ -22,7 +32,10 @@ var vector_exports = {};
|
|
|
22
32
|
__export(vector_exports, {
|
|
23
33
|
VectorCanvas: () => VectorCanvas,
|
|
24
34
|
VectorEditor: () => VectorEditor,
|
|
35
|
+
VectorEffectsPanel: () => VectorEffectsPanel,
|
|
36
|
+
VectorGradientAnnotator: () => VectorGradientAnnotator,
|
|
25
37
|
VectorGradientDefs: () => VectorGradientDefs,
|
|
38
|
+
VectorGradientEditor: () => VectorGradientEditor,
|
|
26
39
|
VectorSceneNodes: () => VectorSceneNodes,
|
|
27
40
|
VectorStylePanel: () => VectorStylePanel,
|
|
28
41
|
VectorToolbar: () => VectorToolbar,
|
|
@@ -165,12 +178,50 @@ function VectorWidthPointEditor({ controller, edit, accentColor = import_vector2
|
|
|
165
178
|
|
|
166
179
|
// src/vector/VectorCanvas.tsx
|
|
167
180
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
181
|
+
function GradientElement({ def }) {
|
|
182
|
+
const stops = def.stops.map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("stop", { offset: s.offset, stopColor: s.stopColor, stopOpacity: s.stopOpacity }, i));
|
|
183
|
+
return def.type === "radial" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("radialGradient", { id: def.id, ...def.attrs, children: stops }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("linearGradient", { id: def.id, ...def.attrs, children: stops });
|
|
184
|
+
}
|
|
168
185
|
function VectorGradientDefs({ defs }) {
|
|
169
186
|
if (!defs.length) return null;
|
|
170
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: defs.map(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
187
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: defs.map(
|
|
188
|
+
(def) => def.type === "pattern" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("pattern", { id: def.id, ...def.attrs, children: [
|
|
189
|
+
def.gradients.map((g) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GradientElement, { def: g }, g.id)),
|
|
190
|
+
def.tiles.map((t, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: t.d, fill: t.fill }, i))
|
|
191
|
+
] }, def.id) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GradientElement, { def }, def.id)
|
|
192
|
+
) });
|
|
193
|
+
}
|
|
194
|
+
function VectorGradientAnnotator({ annotator: g, accentColor = import_vector3.VECTOR_OVERLAY_THEME.accent }) {
|
|
195
|
+
const r = import_vector3.VECTOR_OVERLAY_THEME.handleRadius + 1.5;
|
|
196
|
+
const ring = (p, part, size = r) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { "data-vector-gradient-handle": part, cx: p.x, cy: p.y, r: size + (p.hovered ? 1 : 0), fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor, strokeWidth: p.hovered ? 2 : 1 });
|
|
197
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-gradient-annotator": g.type, children: [
|
|
198
|
+
g.extent && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-gradient-extent": "", d: g.extent, fill: "none", stroke: accentColor, strokeDasharray: "4 3" }),
|
|
199
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: g.start.x, y1: g.start.y, x2: g.end.x, y2: g.end.y, stroke: "#ffffff", strokeWidth: 3 }),
|
|
200
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { "data-vector-gradient-bar": "", x1: g.start.x, y1: g.start.y, x2: g.end.x, y2: g.end.y, stroke: accentColor }),
|
|
201
|
+
g.aspect && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: g.start.x, y1: g.start.y, x2: g.aspect.x, y2: g.aspect.y, stroke: accentColor, strokeDasharray: "2 2" }),
|
|
202
|
+
ring(g.start, "start"),
|
|
203
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
204
|
+
"rect",
|
|
205
|
+
{
|
|
206
|
+
"data-vector-gradient-handle": g.end.handle,
|
|
207
|
+
x: g.end.x - r,
|
|
208
|
+
y: g.end.y - r,
|
|
209
|
+
width: 2 * r,
|
|
210
|
+
height: 2 * r,
|
|
211
|
+
fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill,
|
|
212
|
+
stroke: accentColor,
|
|
213
|
+
strokeWidth: g.end.hovered ? 2 : 1
|
|
214
|
+
}
|
|
215
|
+
),
|
|
216
|
+
g.aspect && ring(g.aspect, "aspect", import_vector3.VECTOR_OVERLAY_THEME.handleRadius),
|
|
217
|
+
g.focal && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("g", { "data-vector-gradient-handle": "focal", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: g.focal.x, cy: g.focal.y, r: import_vector3.VECTOR_OVERLAY_THEME.handleRadius - 1 + (g.focal.hovered ? 1 : 0), fill: accentColor, stroke: import_vector3.VECTOR_OVERLAY_THEME.handleFill }) }),
|
|
218
|
+
g.midpoints.map((m) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-gradient-midpoint": m.index, d: (0, import_vector3.vectorDiamondPath)(m.x, m.y, 4 + (m.hovered ? 1 : 0)), fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor }, m.index)),
|
|
219
|
+
g.stops.map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-gradient-stop": s.index, "data-selected": s.selected || void 0, opacity: g.removing && s.selected ? 0.35 : 1, children: [
|
|
220
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: s.barX, y1: s.barY, x2: s.x, y2: s.y, stroke: accentColor }),
|
|
221
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: s.x - 5, y: s.y - 5, width: 10, height: 10, rx: 2, fill: s.color, fillOpacity: s.opacity, stroke: s.selected ? accentColor : "#ffffff", strokeWidth: s.selected || s.hovered ? 2 : 1 }),
|
|
222
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: s.x - 6.5, y: s.y - 6.5, width: 13, height: 13, rx: 3, fill: "none", stroke: s.selected ? "#ffffff" : accentColor })
|
|
223
|
+
] }, s.index))
|
|
224
|
+
] });
|
|
174
225
|
}
|
|
175
226
|
function VectorSceneNodes({ nodes }) {
|
|
176
227
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: nodes.map(
|
|
@@ -394,6 +445,7 @@ function VectorCanvas({
|
|
|
394
445
|
},
|
|
395
446
|
`blend-anchor:${i}`
|
|
396
447
|
)),
|
|
448
|
+
overlay.gradient && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(VectorGradientAnnotator, { annotator: overlay.gradient, accentColor }),
|
|
397
449
|
overlay.widthSpot && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-width-spot": "", children: [
|
|
398
450
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: overlay.widthSpot.left.x, y1: overlay.widthSpot.left.y, x2: overlay.widthSpot.right.x, y2: overlay.widthSpot.right.y, stroke: accentColor, strokeDasharray: "3 2" }),
|
|
399
451
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: (0, import_vector3.vectorDiamondPath)(overlay.widthSpot.x, overlay.widthSpot.y), fill: "none", stroke: accentColor })
|
|
@@ -499,14 +551,326 @@ function VectorCanvas({
|
|
|
499
551
|
}
|
|
500
552
|
|
|
501
553
|
// src/vector/VectorToolbar.tsx
|
|
554
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
555
|
+
var import_vector6 = require("@pixerate/editor/vector");
|
|
556
|
+
|
|
557
|
+
// src/vector/VectorEffectsPanel.tsx
|
|
502
558
|
var import_vector4 = require("@pixerate/editor/vector");
|
|
503
559
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
560
|
+
var buttonClass = "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";
|
|
561
|
+
var numberClass = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
562
|
+
var selectClass = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
563
|
+
var labelClass = "w-full truncate text-[11px] text-muted-foreground";
|
|
564
|
+
function VectorEffectsPanel({ controller, className }) {
|
|
565
|
+
const state = useVectorEditorState(controller);
|
|
566
|
+
const panel = (0, import_vector4.getVectorEffectsPanel)(state);
|
|
567
|
+
if (!panel) return null;
|
|
568
|
+
const nodeId = panel.nodeId;
|
|
569
|
+
const end = () => controller.endMergedEdit();
|
|
570
|
+
const set = (e, key, value, merge) => {
|
|
571
|
+
if (nodeId) controller.updateEffect(nodeId, e.id, { params: { [key]: value } }, { merge });
|
|
572
|
+
};
|
|
573
|
+
const number = (e, spec) => {
|
|
574
|
+
const value = Number(e.params[spec.key] ?? 0);
|
|
575
|
+
const label = `${e.label} ${spec.label}`;
|
|
576
|
+
const onChange = (ev) => {
|
|
577
|
+
const n = parseFloat(ev.target.value);
|
|
578
|
+
if (Number.isFinite(n)) set(e, spec.key, n, true);
|
|
579
|
+
};
|
|
580
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-foreground", "data-vector-effect-param": spec.key, children: [
|
|
581
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: labelClass, children: spec.label }),
|
|
582
|
+
spec.slider && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
583
|
+
"input",
|
|
584
|
+
{
|
|
585
|
+
type: "range",
|
|
586
|
+
min: spec.min,
|
|
587
|
+
max: spec.max,
|
|
588
|
+
step: spec.step,
|
|
589
|
+
"aria-label": `${label} slider`,
|
|
590
|
+
className: "h-4 min-w-0 flex-1 accent-primary",
|
|
591
|
+
value,
|
|
592
|
+
onChange,
|
|
593
|
+
onPointerUp: end,
|
|
594
|
+
onKeyUp: end,
|
|
595
|
+
onBlur: end
|
|
596
|
+
}
|
|
597
|
+
),
|
|
598
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
599
|
+
"input",
|
|
600
|
+
{
|
|
601
|
+
type: "number",
|
|
602
|
+
min: spec.min,
|
|
603
|
+
max: spec.max,
|
|
604
|
+
step: spec.step,
|
|
605
|
+
"aria-label": label,
|
|
606
|
+
className: numberClass,
|
|
607
|
+
value: Math.round(value * 1e3) / 1e3,
|
|
608
|
+
onChange,
|
|
609
|
+
onBlur: end
|
|
610
|
+
}
|
|
611
|
+
)
|
|
612
|
+
] }, spec.key);
|
|
613
|
+
};
|
|
614
|
+
const vec2 = (e, spec) => {
|
|
615
|
+
const v = e.params[spec.key] ?? { x: 0, y: 0 };
|
|
616
|
+
const field = (axis) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
617
|
+
"input",
|
|
618
|
+
{
|
|
619
|
+
type: "number",
|
|
620
|
+
step: spec.kind === "vec2" ? spec.step : 1,
|
|
621
|
+
"aria-label": `${e.label} ${spec.label} ${axis}`,
|
|
622
|
+
className: numberClass,
|
|
623
|
+
value: Math.round(v[axis] * 1e3) / 1e3,
|
|
624
|
+
onChange: (ev) => {
|
|
625
|
+
const n = parseFloat(ev.target.value);
|
|
626
|
+
if (Number.isFinite(n)) set(e, spec.key, { ...v, [axis]: n }, true);
|
|
627
|
+
},
|
|
628
|
+
onBlur: end
|
|
629
|
+
}
|
|
630
|
+
);
|
|
631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-foreground", "data-vector-effect-param": spec.key, children: [
|
|
632
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: labelClass, children: spec.label }),
|
|
633
|
+
field("x"),
|
|
634
|
+
field("y")
|
|
635
|
+
] }, spec.key);
|
|
636
|
+
};
|
|
637
|
+
const param = (e, spec) => {
|
|
638
|
+
if (spec.kind === "number") return number(e, spec);
|
|
639
|
+
if (spec.kind === "vec2") return vec2(e, spec);
|
|
640
|
+
if (spec.kind === "boolean")
|
|
641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-effect-param": spec.key, children: [
|
|
642
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "min-w-0 flex-1 truncate", children: spec.label }),
|
|
643
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", "aria-label": `${e.label} ${spec.label}`, checked: !!e.params[spec.key], onChange: (ev) => set(e, spec.key, ev.target.checked, false) })
|
|
644
|
+
] }, spec.key);
|
|
645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-foreground", "data-vector-effect-param": spec.key, children: [
|
|
646
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: labelClass, children: spec.label }),
|
|
647
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("select", { "aria-label": `${e.label} ${spec.label}`, className: selectClass, value: String(e.params[spec.key] ?? ""), onChange: (ev) => set(e, spec.key, ev.target.value, false), children: spec.options.map((o) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: o.value, children: o.label }, o.value)) })
|
|
648
|
+
] }, spec.key);
|
|
649
|
+
};
|
|
650
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-effects": "", "aria-label": "Effects", children: [
|
|
651
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
652
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Effects" }),
|
|
653
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
654
|
+
"select",
|
|
655
|
+
{
|
|
656
|
+
"aria-label": "Add effect",
|
|
657
|
+
className: selectClass,
|
|
658
|
+
value: "",
|
|
659
|
+
onChange: (ev) => {
|
|
660
|
+
if (ev.target.value) controller.addEffect(ev.target.value);
|
|
661
|
+
},
|
|
662
|
+
children: [
|
|
663
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: "Add effect\u2026" }),
|
|
664
|
+
import_vector4.VECTOR_EFFECT_MENU.map((m) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: m.type, children: m.label }, m.type))
|
|
665
|
+
]
|
|
666
|
+
}
|
|
667
|
+
),
|
|
668
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: buttonClass, title: "Expand Appearance", "aria-label": "Expand Appearance", disabled: !panel.expandable, onClick: () => controller.expandAppearance(), children: "Expand" })
|
|
669
|
+
] }),
|
|
670
|
+
panel.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Select one object to edit its effects." }),
|
|
671
|
+
nodeId && panel.effects.map((e, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "space-y-1 rounded border border-border p-1.5", "data-vector-effect": e.id, "data-vector-effect-type": e.type, children: [
|
|
672
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
673
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-xs font-medium text-foreground", children: [
|
|
674
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", "aria-label": `${e.label} on`, checked: e.enabled, onChange: (ev) => controller.updateEffect(nodeId, e.id, { enabled: ev.target.checked }) }),
|
|
675
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "truncate", children: e.label })
|
|
676
|
+
] }),
|
|
677
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: buttonClass, title: "Move up", "aria-label": `Move ${e.label} up`, disabled: i === 0, onClick: () => controller.moveEffect(nodeId, e.id, i - 1), children: "\u2191" }),
|
|
678
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
679
|
+
"button",
|
|
680
|
+
{
|
|
681
|
+
type: "button",
|
|
682
|
+
className: buttonClass,
|
|
683
|
+
title: "Move down",
|
|
684
|
+
"aria-label": `Move ${e.label} down`,
|
|
685
|
+
disabled: i === panel.effects.length - 1,
|
|
686
|
+
onClick: () => controller.moveEffect(nodeId, e.id, i + 1),
|
|
687
|
+
children: "\u2193"
|
|
688
|
+
}
|
|
689
|
+
),
|
|
690
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: buttonClass, title: "Remove", "aria-label": `Remove ${e.label}`, onClick: () => controller.removeEffect(nodeId, e.id), children: "\xD7" })
|
|
691
|
+
] }),
|
|
692
|
+
e.specs.map((spec) => param(e, spec))
|
|
693
|
+
] }, e.id))
|
|
694
|
+
] });
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// src/vector/VectorGradientEditor.tsx
|
|
698
|
+
var import_vector5 = require("@pixerate/editor/vector");
|
|
699
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
700
|
+
var selectClass2 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
701
|
+
var numberClass2 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
702
|
+
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";
|
|
703
|
+
var percent = (v) => Math.round(v * 1e3) / 10;
|
|
704
|
+
function VectorGradientEditor({ controller, className }) {
|
|
705
|
+
const state = useVectorEditorState(controller);
|
|
706
|
+
const ed = (0, import_vector5.getVectorGradientEditor)(state);
|
|
707
|
+
if (!ed) return null;
|
|
708
|
+
const g = ed.gradient;
|
|
709
|
+
const sel = ed.selected;
|
|
710
|
+
const end = () => controller.endMergedEdit();
|
|
711
|
+
const setType = (value) => {
|
|
712
|
+
if (value === "solid") {
|
|
713
|
+
const first = ed.stops[0];
|
|
714
|
+
controller.setStyle({ [ed.target]: (0, import_vector5.vectorPaintToHex)(first?.color) ?? first?.color ?? "#000000" }, void 0, { label: "Solid Colour" });
|
|
715
|
+
} else controller.setGradient({ type: value });
|
|
716
|
+
};
|
|
717
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `space-y-1.5 ${className ?? ""}`, "data-vector-gradient-editor": ed.target, "aria-label": "Gradient", children: [
|
|
718
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
719
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Gradient" }),
|
|
720
|
+
["fill", "stroke"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, "aria-pressed": ed.target === t, onClick: () => controller.setGradientTarget(t), children: t === "fill" ? "Fill" : "Stroke" }, t)),
|
|
721
|
+
ed.mixed && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
722
|
+
] }),
|
|
723
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
724
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Type" }),
|
|
725
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("select", { "aria-label": "Gradient type", className: selectClass2, value: ed.type ?? "solid", onChange: (e) => setType(e.target.value), children: [
|
|
726
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "solid", children: "Solid" }),
|
|
727
|
+
import_vector5.VECTOR_GRADIENT_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: t, children: import_vector5.VECTOR_GRADIENT_TYPE_LABELS[t] }, t))
|
|
728
|
+
] }),
|
|
729
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, "aria-label": "Reverse gradient", title: "Reverse gradient", disabled: !g, onClick: () => controller.reverseGradient(), children: "\u21C4" })
|
|
730
|
+
] }),
|
|
731
|
+
g && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
732
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative h-8", "data-vector-gradient-ramp": "", children: [
|
|
733
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
734
|
+
"div",
|
|
735
|
+
{
|
|
736
|
+
role: "button",
|
|
737
|
+
tabIndex: -1,
|
|
738
|
+
"aria-label": "Add gradient stop",
|
|
739
|
+
className: "absolute inset-x-1.5 top-0 h-4 cursor-copy rounded border border-border",
|
|
740
|
+
style: { backgroundImage: `${ed.preview}, repeating-conic-gradient(#ddd 0% 25%, #fff 0% 50%)`, backgroundSize: "auto, 8px 8px" },
|
|
741
|
+
onClick: (e) => {
|
|
742
|
+
const r = e.currentTarget.getBoundingClientRect();
|
|
743
|
+
controller.addGradientStop(r.width > 0 ? Math.min(1, Math.max(0, (e.clientX - r.left) / r.width)) : 0.5);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
),
|
|
747
|
+
ed.stops.map((s) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
748
|
+
"button",
|
|
749
|
+
{
|
|
750
|
+
type: "button",
|
|
751
|
+
"data-vector-gradient-stop": s.index,
|
|
752
|
+
"aria-label": `Gradient stop ${s.index + 1} at ${percent(s.offset)}%`,
|
|
753
|
+
"aria-pressed": s.selected,
|
|
754
|
+
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",
|
|
755
|
+
style: { left: `calc(6px + (100% - 12px) * ${s.offset})`, background: s.color, opacity: 0.4 + 0.6 * (s.opacity ?? 1) },
|
|
756
|
+
onClick: () => controller.selectGradientStop(s.selected ? null : s.index)
|
|
757
|
+
},
|
|
758
|
+
s.index
|
|
759
|
+
))
|
|
760
|
+
] }),
|
|
761
|
+
sel && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", "data-vector-gradient-selected-stop": sel.index, children: [
|
|
762
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
763
|
+
"input",
|
|
764
|
+
{
|
|
765
|
+
type: "color",
|
|
766
|
+
"aria-label": "Stop colour",
|
|
767
|
+
className: "h-7 w-9 cursor-pointer rounded border border-border bg-background",
|
|
768
|
+
value: (0, import_vector5.vectorPaintToHex)(sel.color) ?? "#000000",
|
|
769
|
+
onChange: (e) => controller.setGradientStop(sel.index, { color: e.target.value }, { merge: `gradient-stop-color-${sel.index}` }),
|
|
770
|
+
onBlur: end
|
|
771
|
+
}
|
|
772
|
+
),
|
|
773
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
774
|
+
"Opacity",
|
|
775
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
776
|
+
"input",
|
|
777
|
+
{
|
|
778
|
+
type: "number",
|
|
779
|
+
min: 0,
|
|
780
|
+
max: 100,
|
|
781
|
+
step: 5,
|
|
782
|
+
"aria-label": "Stop opacity",
|
|
783
|
+
className: numberClass2,
|
|
784
|
+
value: percent(sel.opacity ?? 1),
|
|
785
|
+
onChange: (e) => {
|
|
786
|
+
const n = parseFloat(e.target.value);
|
|
787
|
+
if (Number.isFinite(n)) controller.setGradientStop(sel.index, { opacity: n / 100 });
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
)
|
|
791
|
+
] }),
|
|
792
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
793
|
+
"At",
|
|
794
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
795
|
+
"input",
|
|
796
|
+
{
|
|
797
|
+
type: "number",
|
|
798
|
+
min: 0,
|
|
799
|
+
max: 100,
|
|
800
|
+
step: 1,
|
|
801
|
+
"aria-label": "Stop position",
|
|
802
|
+
className: numberClass2,
|
|
803
|
+
value: percent(sel.offset),
|
|
804
|
+
onChange: (e) => {
|
|
805
|
+
const n = parseFloat(e.target.value);
|
|
806
|
+
if (Number.isFinite(n)) controller.setGradientStop(sel.index, { offset: n / 100 });
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
)
|
|
810
|
+
] }),
|
|
811
|
+
!sel.last && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
812
|
+
"Midpoint",
|
|
813
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
814
|
+
"input",
|
|
815
|
+
{
|
|
816
|
+
type: "number",
|
|
817
|
+
min: 5,
|
|
818
|
+
max: 95,
|
|
819
|
+
step: 1,
|
|
820
|
+
"aria-label": "Stop midpoint",
|
|
821
|
+
className: numberClass2,
|
|
822
|
+
value: percent(sel.midpoint ?? 0.5),
|
|
823
|
+
onChange: (e) => {
|
|
824
|
+
const n = parseFloat(e.target.value);
|
|
825
|
+
if (Number.isFinite(n)) controller.setGradientStop(sel.index, { midpoint: n / 100 });
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
)
|
|
829
|
+
] }),
|
|
830
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, "aria-label": "Delete stop", title: "Delete stop", disabled: ed.stops.length <= 2, onClick: () => controller.removeGradientStop(sel.index), children: "\u2715" })
|
|
831
|
+
] }),
|
|
832
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
833
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16", children: "Colours" }),
|
|
834
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { "aria-label": "Gradient interpolation", className: selectClass2, value: ed.interpolation, onChange: (e) => controller.setGradient({ interpolation: e.target.value }), children: import_vector5.VECTOR_GRADIENT_INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: i, children: import_vector5.VECTOR_GRADIENT_INTERPOLATION_LABELS[i] }, i)) })
|
|
835
|
+
] }),
|
|
836
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
837
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16", children: "Smooth" }),
|
|
838
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
839
|
+
"input",
|
|
840
|
+
{
|
|
841
|
+
type: "range",
|
|
842
|
+
min: 0,
|
|
843
|
+
max: 1,
|
|
844
|
+
step: 0.05,
|
|
845
|
+
"aria-label": "Gradient smoothness",
|
|
846
|
+
className: "h-4 flex-1 accent-primary",
|
|
847
|
+
value: ed.smoothness,
|
|
848
|
+
onChange: (e) => controller.setGradient({ smoothness: parseFloat(e.target.value) }, { merge: "gradient-smoothness" }),
|
|
849
|
+
onPointerUp: end,
|
|
850
|
+
onBlur: end
|
|
851
|
+
}
|
|
852
|
+
)
|
|
853
|
+
] }),
|
|
854
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
855
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16", children: "Spread" }),
|
|
856
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { "aria-label": "Gradient spread", className: selectClass2, value: ed.spread, onChange: (e) => controller.setGradient({ spread: e.target.value }), children: import_vector5.VECTOR_GRADIENT_SPREADS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: sp, children: import_vector5.VECTOR_GRADIENT_SPREAD_LABELS[sp] }, sp)) })
|
|
857
|
+
] }),
|
|
858
|
+
ed.target === "stroke" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
859
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16", children: "On stroke" }),
|
|
860
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { "aria-label": "Gradient on stroke", className: selectClass2, value: ed.strokeMode, onChange: (e) => controller.setGradient({ strokeMode: e.target.value }), children: import_vector5.VECTOR_STROKE_GRADIENT_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: m, children: import_vector5.VECTOR_STROKE_GRADIENT_MODE_LABELS[m] }, m)) })
|
|
861
|
+
] })
|
|
862
|
+
] })
|
|
863
|
+
] });
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// src/vector/VectorToolbar.tsx
|
|
867
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
504
868
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
505
869
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
506
|
-
var
|
|
870
|
+
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";
|
|
507
871
|
function VectorToolbar({
|
|
508
872
|
controller,
|
|
509
|
-
tools =
|
|
873
|
+
tools = import_vector6.VECTOR_TOOLS,
|
|
510
874
|
showHistory = true,
|
|
511
875
|
showArrange = true,
|
|
512
876
|
showSnap = true,
|
|
@@ -519,32 +883,34 @@ function VectorToolbar({
|
|
|
519
883
|
const points = state.tool === "direct" ? state.selectedAnchors.length : 0;
|
|
520
884
|
const editing = state.editing;
|
|
521
885
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
|
|
886
|
+
const [live, setLive] = import_react4.default.useState(false);
|
|
887
|
+
const booleanDisabled = live ? count < 1 : count < 2;
|
|
888
|
+
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: buttonClass3, title, "aria-label": title, disabled, onClick: () => void run(), children: label }, label);
|
|
889
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { role: "toolbar", "aria-label": "Vector tools", className: `flex flex-wrap items-center gap-1 ${className ?? ""}`, children: [
|
|
890
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Tools", children: tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
525
891
|
"button",
|
|
526
892
|
{
|
|
527
893
|
type: "button",
|
|
528
894
|
"data-vector-tool": tool,
|
|
529
|
-
className:
|
|
895
|
+
className: buttonClass3,
|
|
530
896
|
"aria-pressed": state.tool === tool,
|
|
531
|
-
title: `${(0,
|
|
532
|
-
"aria-label": (0,
|
|
897
|
+
title: `${(0, import_vector6.vectorToolLabel)(tool)} (${import_vector6.VECTOR_TOOL_SHORTCUTS[tool]})`,
|
|
898
|
+
"aria-label": (0, import_vector6.vectorToolLabel)(tool),
|
|
533
899
|
onClick: () => controller.setTool(tool),
|
|
534
|
-
children:
|
|
900
|
+
children: import_vector6.VECTOR_TOOL_GLYPHS[tool]
|
|
535
901
|
},
|
|
536
902
|
tool
|
|
537
903
|
)) }),
|
|
538
|
-
showHistory && /* @__PURE__ */ (0,
|
|
904
|
+
showHistory && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "History", children: [
|
|
539
905
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
540
906
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
541
907
|
] }),
|
|
542
|
-
showSnap && /* @__PURE__ */ (0,
|
|
908
|
+
showSnap && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Snapping", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
543
909
|
"button",
|
|
544
910
|
{
|
|
545
911
|
type: "button",
|
|
546
912
|
"data-vector-snap": "",
|
|
547
|
-
className:
|
|
913
|
+
className: buttonClass3,
|
|
548
914
|
"aria-pressed": state.snap.objects,
|
|
549
915
|
title: `${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`,
|
|
550
916
|
"aria-label": VECTOR_SNAP_TITLE,
|
|
@@ -552,13 +918,13 @@ function VectorToolbar({
|
|
|
552
918
|
children: "Snap"
|
|
553
919
|
}
|
|
554
920
|
) }),
|
|
555
|
-
showPathEdit && /* @__PURE__ */ (0,
|
|
556
|
-
|
|
921
|
+
showPathEdit && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Path editing", children: [
|
|
922
|
+
import_vector6.VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
557
923
|
"button",
|
|
558
924
|
{
|
|
559
925
|
type: "button",
|
|
560
926
|
"data-vector-path-action": a.id,
|
|
561
|
-
className:
|
|
927
|
+
className: buttonClass3,
|
|
562
928
|
title: a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title,
|
|
563
929
|
"aria-label": a.title,
|
|
564
930
|
disabled: !a.enabled(count, points),
|
|
@@ -567,12 +933,12 @@ function VectorToolbar({
|
|
|
567
933
|
},
|
|
568
934
|
a.id
|
|
569
935
|
)),
|
|
570
|
-
|
|
936
|
+
import_vector6.VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
571
937
|
"button",
|
|
572
938
|
{
|
|
573
939
|
type: "button",
|
|
574
940
|
"data-vector-edit": t.key,
|
|
575
|
-
className:
|
|
941
|
+
className: buttonClass3,
|
|
576
942
|
"aria-pressed": editing[t.key],
|
|
577
943
|
title: t.title,
|
|
578
944
|
"aria-label": t.title,
|
|
@@ -581,9 +947,9 @@ function VectorToolbar({
|
|
|
581
947
|
},
|
|
582
948
|
t.key
|
|
583
949
|
)),
|
|
584
|
-
state.tool === "pencil" && /* @__PURE__ */ (0,
|
|
950
|
+
state.tool === "pencil" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
585
951
|
"Smoothing",
|
|
586
|
-
/* @__PURE__ */ (0,
|
|
952
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
587
953
|
"input",
|
|
588
954
|
{
|
|
589
955
|
type: "range",
|
|
@@ -597,9 +963,9 @@ function VectorToolbar({
|
|
|
597
963
|
}
|
|
598
964
|
)
|
|
599
965
|
] }),
|
|
600
|
-
state.tool === "eraser" && /* @__PURE__ */ (0,
|
|
966
|
+
state.tool === "eraser" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
601
967
|
"Size",
|
|
602
|
-
/* @__PURE__ */ (0,
|
|
968
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
603
969
|
"input",
|
|
604
970
|
{
|
|
605
971
|
type: "number",
|
|
@@ -615,36 +981,49 @@ function VectorToolbar({
|
|
|
615
981
|
}
|
|
616
982
|
)
|
|
617
983
|
] }),
|
|
618
|
-
state.tool === "paintBucket" && /* @__PURE__ */ (0,
|
|
984
|
+
state.tool === "paintBucket" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
619
985
|
"button",
|
|
620
986
|
{
|
|
621
987
|
type: "button",
|
|
622
988
|
"data-vector-fill-gap": "",
|
|
623
|
-
className:
|
|
989
|
+
className: buttonClass3,
|
|
624
990
|
"aria-pressed": editing.fillGap > 0,
|
|
625
991
|
title: "Close small gaps between path ends when filling",
|
|
626
992
|
"aria-label": "Close gaps",
|
|
627
|
-
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 :
|
|
993
|
+
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : import_vector6.VECTOR_FILL_GAP }),
|
|
628
994
|
children: "Gaps"
|
|
629
995
|
}
|
|
630
996
|
)
|
|
631
997
|
] }),
|
|
632
|
-
showBlend && /* @__PURE__ */ (0,
|
|
633
|
-
showArrange && /* @__PURE__ */ (0,
|
|
634
|
-
/* @__PURE__ */ (0,
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
998
|
+
showBlend && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VectorBlendControls, { controller }),
|
|
999
|
+
showArrange && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
1000
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
|
|
1001
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
1002
|
+
"button",
|
|
1003
|
+
{
|
|
1004
|
+
type: "button",
|
|
1005
|
+
"data-vector-live-boolean": "",
|
|
1006
|
+
className: buttonClass3,
|
|
1007
|
+
"aria-pressed": live,
|
|
1008
|
+
title: "Live booleans: keep the shapes editable",
|
|
1009
|
+
"aria-label": "Live booleans",
|
|
1010
|
+
onClick: () => setLive(!live),
|
|
1011
|
+
children: "Live"
|
|
1012
|
+
}
|
|
1013
|
+
),
|
|
1014
|
+
act("\u222A", "Union", () => controller.booleanOp("union", { live }), booleanDisabled),
|
|
1015
|
+
act("\u2212", "Subtract", () => controller.booleanOp("subtract", { live }), booleanDisabled),
|
|
1016
|
+
act("\u2229", "Intersect", () => controller.booleanOp("intersect", { live }), booleanDisabled),
|
|
1017
|
+
act("\u22BB", "Exclude", () => controller.booleanOp("exclude", { live }), booleanDisabled),
|
|
639
1018
|
act("G", "Group", () => controller.group(), count < 1),
|
|
640
1019
|
act("U", "Ungroup", () => controller.ungroup(), !groupSelected)
|
|
641
1020
|
] }),
|
|
642
|
-
/* @__PURE__ */ (0,
|
|
1021
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: import_vector6.VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
643
1022
|
"button",
|
|
644
1023
|
{
|
|
645
1024
|
type: "button",
|
|
646
1025
|
"data-vector-pathfinder": a.id,
|
|
647
|
-
className:
|
|
1026
|
+
className: buttonClass3,
|
|
648
1027
|
title: a.title,
|
|
649
1028
|
"aria-label": a.title,
|
|
650
1029
|
disabled: count < a.min,
|
|
@@ -653,7 +1032,7 @@ function VectorToolbar({
|
|
|
653
1032
|
},
|
|
654
1033
|
a.id
|
|
655
1034
|
)) }),
|
|
656
|
-
/* @__PURE__ */ (0,
|
|
1035
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
657
1036
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
658
1037
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
659
1038
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -668,22 +1047,22 @@ function VectorToolbar({
|
|
|
668
1047
|
}
|
|
669
1048
|
function VectorBlendControls({ controller }) {
|
|
670
1049
|
const state = useVectorEditorState(controller);
|
|
671
|
-
const blend = (0,
|
|
1050
|
+
const blend = (0, import_vector6.getVectorBlendControls)(state);
|
|
672
1051
|
const o = blend.options;
|
|
673
1052
|
const selected = blend.ids.length > 0;
|
|
674
|
-
return /* @__PURE__ */ (0,
|
|
675
|
-
/* @__PURE__ */ (0,
|
|
676
|
-
/* @__PURE__ */ (0,
|
|
1053
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Blend", "data-vector-blend-controls": "", children: [
|
|
1054
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("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" }),
|
|
1055
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
677
1056
|
"select",
|
|
678
1057
|
{
|
|
679
1058
|
"aria-label": "Blend spacing",
|
|
680
1059
|
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
681
1060
|
value: o.spacing,
|
|
682
|
-
onChange: (e) => (0,
|
|
683
|
-
children:
|
|
1061
|
+
onChange: (e) => (0, import_vector6.applyVectorBlendOptions)(controller, { spacing: e.target.value }),
|
|
1062
|
+
children: import_vector6.VECTOR_BLEND_SPACINGS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: sp, children: import_vector6.VECTOR_BLEND_SPACING_LABELS[sp] }, sp))
|
|
684
1063
|
}
|
|
685
1064
|
),
|
|
686
|
-
o.spacing !== "smoothColor" && /* @__PURE__ */ (0,
|
|
1065
|
+
o.spacing !== "smoothColor" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
687
1066
|
"input",
|
|
688
1067
|
{
|
|
689
1068
|
type: "number",
|
|
@@ -695,29 +1074,29 @@ function VectorBlendControls({ controller }) {
|
|
|
695
1074
|
onChange: (e) => {
|
|
696
1075
|
const n = parseFloat(e.target.value);
|
|
697
1076
|
if (!Number.isFinite(n) || n <= 0) return;
|
|
698
|
-
(0,
|
|
1077
|
+
(0, import_vector6.applyVectorBlendOptions)(controller, o.spacing === "steps" ? { steps: n } : { distance: n });
|
|
699
1078
|
}
|
|
700
1079
|
}
|
|
701
1080
|
),
|
|
702
|
-
/* @__PURE__ */ (0,
|
|
1081
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
703
1082
|
"button",
|
|
704
1083
|
{
|
|
705
1084
|
type: "button",
|
|
706
1085
|
"data-vector-blend-action": "orient",
|
|
707
|
-
className:
|
|
1086
|
+
className: buttonClass3,
|
|
708
1087
|
"aria-pressed": o.orientToSpine,
|
|
709
1088
|
title: "Orient steps to the spine",
|
|
710
1089
|
"aria-label": "Orient to spine",
|
|
711
|
-
onClick: () => (0,
|
|
1090
|
+
onClick: () => (0, import_vector6.applyVectorBlendOptions)(controller, { orientToSpine: !o.orientToSpine }),
|
|
712
1091
|
children: "\u293F"
|
|
713
1092
|
}
|
|
714
1093
|
),
|
|
715
|
-
/* @__PURE__ */ (0,
|
|
1094
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
716
1095
|
"button",
|
|
717
1096
|
{
|
|
718
1097
|
type: "button",
|
|
719
1098
|
"data-vector-blend-action": "spine",
|
|
720
|
-
className:
|
|
1099
|
+
className: buttonClass3,
|
|
721
1100
|
title: "Replace Spine (select a blend and a path)",
|
|
722
1101
|
"aria-label": "Replace Spine",
|
|
723
1102
|
disabled: !blend.canReplaceSpine,
|
|
@@ -725,15 +1104,15 @@ function VectorBlendControls({ controller }) {
|
|
|
725
1104
|
children: "\u2307"
|
|
726
1105
|
}
|
|
727
1106
|
),
|
|
728
|
-
/* @__PURE__ */ (0,
|
|
729
|
-
/* @__PURE__ */ (0,
|
|
1107
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", "data-vector-blend-action": "expand", className: buttonClass3, title: "Expand Blend", "aria-label": "Expand Blend", disabled: !selected, onClick: () => controller.expandBlend(), children: "\u29C9" }),
|
|
1108
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", "data-vector-blend-action": "release", className: buttonClass3, title: "Release Blend", "aria-label": "Release Blend", disabled: !selected, onClick: () => controller.releaseBlend(), children: "\u29C4" })
|
|
730
1109
|
] });
|
|
731
1110
|
}
|
|
732
|
-
var
|
|
733
|
-
var
|
|
1111
|
+
var selectClass3 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
1112
|
+
var numberClass3 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
734
1113
|
function VectorStylePanel({ controller, className }) {
|
|
735
1114
|
const state = useVectorEditorState(controller);
|
|
736
|
-
const style = (0,
|
|
1115
|
+
const style = (0, import_vector6.getVectorSelectionStyle)(state);
|
|
737
1116
|
const d = state.defaults;
|
|
738
1117
|
const source = style ?? {
|
|
739
1118
|
fill: d.fill ?? null,
|
|
@@ -746,7 +1125,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
746
1125
|
arrowAlign: d.arrowAlign ?? "extend",
|
|
747
1126
|
startArrowScale: d.startArrowScale ?? 1,
|
|
748
1127
|
endArrowScale: d.endArrowScale ?? 1,
|
|
749
|
-
widthProfile: (0,
|
|
1128
|
+
widthProfile: (0, import_vector6.widthProfilePresetId)(d.strokeWidthProfile),
|
|
750
1129
|
cornerRadius: d.cornerRadius,
|
|
751
1130
|
cornerKind: d.cornerKind ?? "round",
|
|
752
1131
|
corners: 1,
|
|
@@ -759,19 +1138,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
759
1138
|
};
|
|
760
1139
|
const setProfile = (id) => {
|
|
761
1140
|
if (style) controller.setWidthProfile(id);
|
|
762
|
-
else controller.setDefaults({ strokeWidthProfile: (0,
|
|
1141
|
+
else controller.setDefaults({ strokeWidthProfile: (0, import_vector6.widthProfilePreset)(id)?.length ? (0, import_vector6.widthProfilePreset)(id) : null });
|
|
763
1142
|
};
|
|
764
|
-
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0,
|
|
1143
|
+
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
|
|
765
1144
|
const arrowRow = (end, label) => {
|
|
766
1145
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
767
1146
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
768
|
-
return /* @__PURE__ */ (0,
|
|
769
|
-
/* @__PURE__ */ (0,
|
|
770
|
-
/* @__PURE__ */ (0,
|
|
771
|
-
/* @__PURE__ */ (0,
|
|
772
|
-
|
|
1147
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
1148
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16 text-xs text-foreground", children: label }),
|
|
1149
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("select", { "aria-label": `${label} arrowhead`, className: selectClass3, value: source[key] ?? "", onChange: (e) => apply({ [key]: e.target.value || null }), children: [
|
|
1150
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "", children: "None" }),
|
|
1151
|
+
import_vector6.VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: h, children: import_vector6.VECTOR_ARROWHEAD_LABELS[h] }, h))
|
|
773
1152
|
] }),
|
|
774
|
-
/* @__PURE__ */ (0,
|
|
1153
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
775
1154
|
"input",
|
|
776
1155
|
{
|
|
777
1156
|
type: "number",
|
|
@@ -779,7 +1158,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
779
1158
|
step: 0.25,
|
|
780
1159
|
"aria-label": `${label} arrowhead scale`,
|
|
781
1160
|
title: "Scale (\xD7 stroke width)",
|
|
782
|
-
className:
|
|
1161
|
+
className: numberClass3,
|
|
783
1162
|
value: source[scaleKey],
|
|
784
1163
|
onChange: (e) => {
|
|
785
1164
|
const n = parseFloat(e.target.value);
|
|
@@ -795,14 +1174,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
795
1174
|
};
|
|
796
1175
|
const paintRow = (key, label) => {
|
|
797
1176
|
const paint = source[key];
|
|
798
|
-
const hex = (0,
|
|
1177
|
+
const hex = (0, import_vector6.vectorPaintToHex)(paint);
|
|
799
1178
|
const on = paint !== null && paint !== "none";
|
|
800
|
-
return /* @__PURE__ */ (0,
|
|
801
|
-
/* @__PURE__ */ (0,
|
|
802
|
-
/* @__PURE__ */ (0,
|
|
1179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
1180
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex w-16 items-center gap-1.5 text-xs text-foreground", children: [
|
|
1181
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "checkbox", checked: on, "aria-label": `${label} on`, onChange: (e) => apply({ [key]: e.target.checked ? hex ?? "#000000" : null }) }),
|
|
803
1182
|
label
|
|
804
1183
|
] }),
|
|
805
|
-
/* @__PURE__ */ (0,
|
|
1184
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
806
1185
|
"input",
|
|
807
1186
|
{
|
|
808
1187
|
type: "color",
|
|
@@ -813,17 +1192,18 @@ function VectorStylePanel({ controller, className }) {
|
|
|
813
1192
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
814
1193
|
}
|
|
815
1194
|
),
|
|
816
|
-
on && !hex && /* @__PURE__ */ (0,
|
|
817
|
-
style?.mixed[key] && /* @__PURE__ */ (0,
|
|
1195
|
+
on && !hex && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "truncate text-[11px] text-muted-foreground", children: typeof paint === "string" ? paint : "Gradient" }),
|
|
1196
|
+
style?.mixed[key] && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
818
1197
|
] });
|
|
819
1198
|
};
|
|
820
|
-
return /* @__PURE__ */ (0,
|
|
821
|
-
/* @__PURE__ */ (0,
|
|
1199
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "aria-label": style ? "Selection style" : "New shape style", children: [
|
|
1200
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: style ? "Selection" : "New shapes" }),
|
|
822
1201
|
paintRow("fill", "Fill"),
|
|
823
1202
|
paintRow("stroke", "Stroke"),
|
|
824
|
-
/* @__PURE__ */ (0,
|
|
825
|
-
|
|
826
|
-
/* @__PURE__ */ (0,
|
|
1203
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VectorGradientEditor, { controller }),
|
|
1204
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
1205
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16", children: "Width" }),
|
|
1206
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
827
1207
|
"input",
|
|
828
1208
|
{
|
|
829
1209
|
type: "number",
|
|
@@ -839,33 +1219,33 @@ function VectorStylePanel({ controller, className }) {
|
|
|
839
1219
|
}
|
|
840
1220
|
)
|
|
841
1221
|
] }),
|
|
842
|
-
/* @__PURE__ */ (0,
|
|
843
|
-
/* @__PURE__ */ (0,
|
|
844
|
-
/* @__PURE__ */ (0,
|
|
1222
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "strokeAlign", children: [
|
|
1223
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16", children: "Align" }),
|
|
1224
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("select", { "aria-label": "Stroke alignment", className: selectClass3, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(import_vector6.VECTOR_STROKE_ALIGN_LABELS).map((a) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: a, children: import_vector6.VECTOR_STROKE_ALIGN_LABELS[a] }, a)) }),
|
|
845
1225
|
mixed("strokeAlign")
|
|
846
1226
|
] }),
|
|
847
|
-
/* @__PURE__ */ (0,
|
|
848
|
-
/* @__PURE__ */ (0,
|
|
849
|
-
/* @__PURE__ */ (0,
|
|
1227
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
|
|
1228
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16", children: "Profile" }),
|
|
1229
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
850
1230
|
"select",
|
|
851
1231
|
{
|
|
852
1232
|
"aria-label": "Width profile",
|
|
853
|
-
className:
|
|
1233
|
+
className: selectClass3,
|
|
854
1234
|
value: source.widthProfile,
|
|
855
1235
|
onChange: (e) => {
|
|
856
1236
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
857
1237
|
},
|
|
858
1238
|
children: [
|
|
859
|
-
|
|
860
|
-
source.widthProfile === "custom" && /* @__PURE__ */ (0,
|
|
1239
|
+
import_vector6.VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: p.id, children: p.label }, p.id)),
|
|
1240
|
+
source.widthProfile === "custom" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "custom", disabled: true, children: "Custom" })
|
|
861
1241
|
]
|
|
862
1242
|
}
|
|
863
1243
|
),
|
|
864
|
-
/* @__PURE__ */ (0,
|
|
1244
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
865
1245
|
"button",
|
|
866
1246
|
{
|
|
867
1247
|
type: "button",
|
|
868
|
-
className:
|
|
1248
|
+
className: buttonClass3,
|
|
869
1249
|
title: "Reset to uniform width",
|
|
870
1250
|
"aria-label": "Reset to uniform width",
|
|
871
1251
|
disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
|
|
@@ -875,27 +1255,27 @@ function VectorStylePanel({ controller, className }) {
|
|
|
875
1255
|
),
|
|
876
1256
|
mixed("widthProfile")
|
|
877
1257
|
] }),
|
|
878
|
-
source.hasOpenPath && /* @__PURE__ */ (0,
|
|
1258
|
+
source.hasOpenPath && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
|
|
879
1259
|
arrowRow("start", "Start"),
|
|
880
1260
|
arrowRow("end", "End"),
|
|
881
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0,
|
|
882
|
-
/* @__PURE__ */ (0,
|
|
883
|
-
/* @__PURE__ */ (0,
|
|
884
|
-
/* @__PURE__ */ (0,
|
|
885
|
-
/* @__PURE__ */ (0,
|
|
1261
|
+
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "arrowAlign", children: [
|
|
1262
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16", children: "Heads" }),
|
|
1263
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("select", { "aria-label": "Arrowhead alignment", className: selectClass3, value: source.arrowAlign, onChange: (e) => apply({ arrowAlign: e.target.value }), children: [
|
|
1264
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "extend", children: "Tip past end" }),
|
|
1265
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "tip", children: "Tip at end" })
|
|
886
1266
|
] })
|
|
887
1267
|
] })
|
|
888
1268
|
] }),
|
|
889
|
-
source.corners > 0 && /* @__PURE__ */ (0,
|
|
890
|
-
/* @__PURE__ */ (0,
|
|
891
|
-
/* @__PURE__ */ (0,
|
|
1269
|
+
source.corners > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": "corners", children: [
|
|
1270
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Corners" }),
|
|
1271
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
892
1272
|
"input",
|
|
893
1273
|
{
|
|
894
1274
|
type: "number",
|
|
895
1275
|
min: 0,
|
|
896
1276
|
step: 1,
|
|
897
1277
|
"aria-label": "Corner radius",
|
|
898
|
-
className:
|
|
1278
|
+
className: numberClass3,
|
|
899
1279
|
value: Math.round(source.cornerRadius * 100) / 100,
|
|
900
1280
|
onChange: (e) => {
|
|
901
1281
|
const n = parseFloat(e.target.value);
|
|
@@ -903,12 +1283,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
903
1283
|
}
|
|
904
1284
|
}
|
|
905
1285
|
),
|
|
906
|
-
/* @__PURE__ */ (0,
|
|
1286
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("select", { "aria-label": "Corner kind", className: selectClass3, value: source.cornerKind, onChange: (e) => setCorners({ kind: e.target.value }), children: import_vector6.VECTOR_CORNER_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: k, children: import_vector6.VECTOR_CORNER_KIND_LABELS[k] }, k)) }),
|
|
907
1287
|
mixed("cornerRadius")
|
|
908
1288
|
] }),
|
|
909
|
-
style && /* @__PURE__ */ (0,
|
|
910
|
-
/* @__PURE__ */ (0,
|
|
911
|
-
/* @__PURE__ */ (0,
|
|
1289
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
1290
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16", children: "Opacity" }),
|
|
1291
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
912
1292
|
"input",
|
|
913
1293
|
{
|
|
914
1294
|
type: "range",
|
|
@@ -921,18 +1301,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
921
1301
|
onChange: (e) => apply({ opacity: parseFloat(e.target.value) })
|
|
922
1302
|
}
|
|
923
1303
|
)
|
|
924
|
-
] })
|
|
1304
|
+
] }),
|
|
1305
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VectorEffectsPanel, { controller })
|
|
925
1306
|
] });
|
|
926
1307
|
}
|
|
927
1308
|
|
|
928
1309
|
// src/vector/VectorEditor.tsx
|
|
929
|
-
var
|
|
1310
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
930
1311
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }) {
|
|
931
|
-
return /* @__PURE__ */ (0,
|
|
932
|
-
/* @__PURE__ */ (0,
|
|
933
|
-
/* @__PURE__ */ (0,
|
|
934
|
-
/* @__PURE__ */ (0,
|
|
935
|
-
showStylePanel && /* @__PURE__ */ (0,
|
|
1312
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `flex flex-col gap-2 ${className ?? ""}`, "data-vector-editor": "", children: [
|
|
1313
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VectorToolbar, { controller, tools }),
|
|
1314
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex min-h-0 flex-col gap-2 md:flex-row", children: [
|
|
1315
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.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_runtime6.jsx)(VectorCanvas, { controller, ...canvasProps }) }),
|
|
1316
|
+
showStylePanel && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(VectorStylePanel, { controller, className: "w-full shrink-0 rounded-md border border-border p-3 md:w-56" })
|
|
936
1317
|
] })
|
|
937
1318
|
] });
|
|
938
1319
|
}
|
|
@@ -940,7 +1321,10 @@ function VectorEditor({ controller, tools, showStylePanel = true, height = 520,
|
|
|
940
1321
|
0 && (module.exports = {
|
|
941
1322
|
VectorCanvas,
|
|
942
1323
|
VectorEditor,
|
|
1324
|
+
VectorEffectsPanel,
|
|
1325
|
+
VectorGradientAnnotator,
|
|
943
1326
|
VectorGradientDefs,
|
|
1327
|
+
VectorGradientEditor,
|
|
944
1328
|
VectorSceneNodes,
|
|
945
1329
|
VectorStylePanel,
|
|
946
1330
|
VectorToolbar,
|