@pixerate/editor-react 0.30.0 → 0.32.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 +355 -90
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +20 -3
- package/dist/vector/index.d.ts +20 -3
- package/dist/vector/index.js +344 -83
- 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,6 +32,7 @@ var vector_exports = {};
|
|
|
22
32
|
__export(vector_exports, {
|
|
23
33
|
VectorCanvas: () => VectorCanvas,
|
|
24
34
|
VectorEditor: () => VectorEditor,
|
|
35
|
+
VectorEffectsPanel: () => VectorEffectsPanel,
|
|
25
36
|
VectorGradientDefs: () => VectorGradientDefs,
|
|
26
37
|
VectorSceneNodes: () => VectorSceneNodes,
|
|
27
38
|
VectorStylePanel: () => VectorStylePanel,
|
|
@@ -373,6 +384,27 @@ function VectorCanvas({
|
|
|
373
384
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: w.x, cy: w.y, r: import_vector3.VECTOR_OVERLAY_THEME.cornerWidgetRadius + (w.hovered ? 1 : 0), fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor }),
|
|
374
385
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: w.x, cy: w.y, r: 1.5, fill: accentColor })
|
|
375
386
|
] }, `corner:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`)),
|
|
387
|
+
overlay.blend.spines.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-blend-spine": sp.id, "data-replaced": sp.replaced || void 0, children: [
|
|
388
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: sp.d, fill: "none", stroke: accentColor, strokeDasharray: "4 3" }),
|
|
389
|
+
sp.keys.map((k, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: k.x, cy: k.y, r: import_vector3.VECTOR_OVERLAY_THEME.handleRadius, fill: import_vector3.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor }, i))
|
|
390
|
+
] }, `blend:${sp.id}`)),
|
|
391
|
+
overlay.blend.start && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-blend-start": "", children: [
|
|
392
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: overlay.blend.start.d, fill: "none", stroke: accentColor, strokeWidth: 2 }),
|
|
393
|
+
overlay.blend.start.anchor && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: overlay.blend.start.anchor.x, cy: overlay.blend.start.anchor.y, r: import_vector3.VECTOR_OVERLAY_THEME.handleRadius + 1, fill: accentColor })
|
|
394
|
+
] }),
|
|
395
|
+
overlay.blend.anchors.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
396
|
+
"rect",
|
|
397
|
+
{
|
|
398
|
+
"data-vector-blend-anchor": i,
|
|
399
|
+
x: a.x - as / 2,
|
|
400
|
+
y: a.y - as / 2,
|
|
401
|
+
width: as,
|
|
402
|
+
height: as,
|
|
403
|
+
fill: a.hovered ? accentColor : import_vector3.VECTOR_OVERLAY_THEME.handleFill,
|
|
404
|
+
stroke: accentColor
|
|
405
|
+
},
|
|
406
|
+
`blend-anchor:${i}`
|
|
407
|
+
)),
|
|
376
408
|
overlay.widthSpot && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-width-spot": "", children: [
|
|
377
409
|
/* @__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" }),
|
|
378
410
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: (0, import_vector3.vectorDiamondPath)(overlay.widthSpot.x, overlay.widthSpot.y), fill: "none", stroke: accentColor })
|
|
@@ -478,43 +510,197 @@ function VectorCanvas({
|
|
|
478
510
|
}
|
|
479
511
|
|
|
480
512
|
// src/vector/VectorToolbar.tsx
|
|
513
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
514
|
+
var import_vector5 = require("@pixerate/editor/vector");
|
|
515
|
+
|
|
516
|
+
// src/vector/VectorEffectsPanel.tsx
|
|
481
517
|
var import_vector4 = require("@pixerate/editor/vector");
|
|
482
518
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
519
|
+
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";
|
|
520
|
+
var numberClass = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
521
|
+
var selectClass = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
522
|
+
var labelClass = "w-full truncate text-[11px] text-muted-foreground";
|
|
523
|
+
function VectorEffectsPanel({ controller, className }) {
|
|
524
|
+
const state = useVectorEditorState(controller);
|
|
525
|
+
const panel = (0, import_vector4.getVectorEffectsPanel)(state);
|
|
526
|
+
if (!panel) return null;
|
|
527
|
+
const nodeId = panel.nodeId;
|
|
528
|
+
const end = () => controller.endMergedEdit();
|
|
529
|
+
const set = (e, key, value, merge) => {
|
|
530
|
+
if (nodeId) controller.updateEffect(nodeId, e.id, { params: { [key]: value } }, { merge });
|
|
531
|
+
};
|
|
532
|
+
const number = (e, spec) => {
|
|
533
|
+
const value = Number(e.params[spec.key] ?? 0);
|
|
534
|
+
const label = `${e.label} ${spec.label}`;
|
|
535
|
+
const onChange = (ev) => {
|
|
536
|
+
const n = parseFloat(ev.target.value);
|
|
537
|
+
if (Number.isFinite(n)) set(e, spec.key, n, true);
|
|
538
|
+
};
|
|
539
|
+
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: [
|
|
540
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: labelClass, children: spec.label }),
|
|
541
|
+
spec.slider && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
542
|
+
"input",
|
|
543
|
+
{
|
|
544
|
+
type: "range",
|
|
545
|
+
min: spec.min,
|
|
546
|
+
max: spec.max,
|
|
547
|
+
step: spec.step,
|
|
548
|
+
"aria-label": `${label} slider`,
|
|
549
|
+
className: "h-4 min-w-0 flex-1 accent-primary",
|
|
550
|
+
value,
|
|
551
|
+
onChange,
|
|
552
|
+
onPointerUp: end,
|
|
553
|
+
onKeyUp: end,
|
|
554
|
+
onBlur: end
|
|
555
|
+
}
|
|
556
|
+
),
|
|
557
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
558
|
+
"input",
|
|
559
|
+
{
|
|
560
|
+
type: "number",
|
|
561
|
+
min: spec.min,
|
|
562
|
+
max: spec.max,
|
|
563
|
+
step: spec.step,
|
|
564
|
+
"aria-label": label,
|
|
565
|
+
className: numberClass,
|
|
566
|
+
value: Math.round(value * 1e3) / 1e3,
|
|
567
|
+
onChange,
|
|
568
|
+
onBlur: end
|
|
569
|
+
}
|
|
570
|
+
)
|
|
571
|
+
] }, spec.key);
|
|
572
|
+
};
|
|
573
|
+
const vec2 = (e, spec) => {
|
|
574
|
+
const v = e.params[spec.key] ?? { x: 0, y: 0 };
|
|
575
|
+
const field = (axis) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
576
|
+
"input",
|
|
577
|
+
{
|
|
578
|
+
type: "number",
|
|
579
|
+
step: spec.kind === "vec2" ? spec.step : 1,
|
|
580
|
+
"aria-label": `${e.label} ${spec.label} ${axis}`,
|
|
581
|
+
className: numberClass,
|
|
582
|
+
value: Math.round(v[axis] * 1e3) / 1e3,
|
|
583
|
+
onChange: (ev) => {
|
|
584
|
+
const n = parseFloat(ev.target.value);
|
|
585
|
+
if (Number.isFinite(n)) set(e, spec.key, { ...v, [axis]: n }, true);
|
|
586
|
+
},
|
|
587
|
+
onBlur: end
|
|
588
|
+
}
|
|
589
|
+
);
|
|
590
|
+
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: [
|
|
591
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: labelClass, children: spec.label }),
|
|
592
|
+
field("x"),
|
|
593
|
+
field("y")
|
|
594
|
+
] }, spec.key);
|
|
595
|
+
};
|
|
596
|
+
const param = (e, spec) => {
|
|
597
|
+
if (spec.kind === "number") return number(e, spec);
|
|
598
|
+
if (spec.kind === "vec2") return vec2(e, spec);
|
|
599
|
+
if (spec.kind === "boolean")
|
|
600
|
+
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: [
|
|
601
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "min-w-0 flex-1 truncate", children: spec.label }),
|
|
602
|
+
/* @__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) })
|
|
603
|
+
] }, spec.key);
|
|
604
|
+
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: [
|
|
605
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: labelClass, children: spec.label }),
|
|
606
|
+
/* @__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)) })
|
|
607
|
+
] }, spec.key);
|
|
608
|
+
};
|
|
609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-effects": "", "aria-label": "Effects", children: [
|
|
610
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
611
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Effects" }),
|
|
612
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
613
|
+
"select",
|
|
614
|
+
{
|
|
615
|
+
"aria-label": "Add effect",
|
|
616
|
+
className: selectClass,
|
|
617
|
+
value: "",
|
|
618
|
+
onChange: (ev) => {
|
|
619
|
+
if (ev.target.value) controller.addEffect(ev.target.value);
|
|
620
|
+
},
|
|
621
|
+
children: [
|
|
622
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: "Add effect\u2026" }),
|
|
623
|
+
import_vector4.VECTOR_EFFECT_MENU.map((m) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: m.type, children: m.label }, m.type))
|
|
624
|
+
]
|
|
625
|
+
}
|
|
626
|
+
),
|
|
627
|
+
/* @__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" })
|
|
628
|
+
] }),
|
|
629
|
+
panel.count > 1 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Select one object to edit its effects." }),
|
|
630
|
+
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: [
|
|
631
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
632
|
+
/* @__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: [
|
|
633
|
+
/* @__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 }) }),
|
|
634
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "truncate", children: e.label })
|
|
635
|
+
] }),
|
|
636
|
+
/* @__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" }),
|
|
637
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
638
|
+
"button",
|
|
639
|
+
{
|
|
640
|
+
type: "button",
|
|
641
|
+
className: buttonClass,
|
|
642
|
+
title: "Move down",
|
|
643
|
+
"aria-label": `Move ${e.label} down`,
|
|
644
|
+
disabled: i === panel.effects.length - 1,
|
|
645
|
+
onClick: () => controller.moveEffect(nodeId, e.id, i + 1),
|
|
646
|
+
children: "\u2193"
|
|
647
|
+
}
|
|
648
|
+
),
|
|
649
|
+
/* @__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" })
|
|
650
|
+
] }),
|
|
651
|
+
e.specs.map((spec) => param(e, spec))
|
|
652
|
+
] }, e.id))
|
|
653
|
+
] });
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
// src/vector/VectorToolbar.tsx
|
|
657
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
483
658
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
484
659
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
485
|
-
var
|
|
486
|
-
function VectorToolbar({
|
|
660
|
+
var buttonClass2 = "inline-flex h-8 min-w-8 items-center justify-center rounded-md border border-border bg-background px-2 text-xs font-medium text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40 aria-pressed:bg-primary aria-pressed:text-primary-foreground";
|
|
661
|
+
function VectorToolbar({
|
|
662
|
+
controller,
|
|
663
|
+
tools = import_vector5.VECTOR_TOOLS,
|
|
664
|
+
showHistory = true,
|
|
665
|
+
showArrange = true,
|
|
666
|
+
showSnap = true,
|
|
667
|
+
showPathEdit = true,
|
|
668
|
+
showBlend = true,
|
|
669
|
+
className
|
|
670
|
+
}) {
|
|
487
671
|
const state = useVectorEditorState(controller);
|
|
488
672
|
const count = state.selection.length;
|
|
489
673
|
const points = state.tool === "direct" ? state.selectedAnchors.length : 0;
|
|
490
674
|
const editing = state.editing;
|
|
491
675
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
492
|
-
const
|
|
493
|
-
|
|
494
|
-
|
|
676
|
+
const [live, setLive] = import_react4.default.useState(false);
|
|
677
|
+
const booleanDisabled = live ? count < 1 : count < 2;
|
|
678
|
+
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, title, "aria-label": title, disabled, onClick: () => void run(), children: label }, label);
|
|
679
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { role: "toolbar", "aria-label": "Vector tools", className: `flex flex-wrap items-center gap-1 ${className ?? ""}`, children: [
|
|
680
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Tools", children: tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
495
681
|
"button",
|
|
496
682
|
{
|
|
497
683
|
type: "button",
|
|
498
684
|
"data-vector-tool": tool,
|
|
499
|
-
className:
|
|
685
|
+
className: buttonClass2,
|
|
500
686
|
"aria-pressed": state.tool === tool,
|
|
501
|
-
title: `${(0,
|
|
502
|
-
"aria-label": (0,
|
|
687
|
+
title: `${(0, import_vector5.vectorToolLabel)(tool)} (${import_vector5.VECTOR_TOOL_SHORTCUTS[tool]})`,
|
|
688
|
+
"aria-label": (0, import_vector5.vectorToolLabel)(tool),
|
|
503
689
|
onClick: () => controller.setTool(tool),
|
|
504
|
-
children:
|
|
690
|
+
children: import_vector5.VECTOR_TOOL_GLYPHS[tool]
|
|
505
691
|
},
|
|
506
692
|
tool
|
|
507
693
|
)) }),
|
|
508
|
-
showHistory && /* @__PURE__ */ (0,
|
|
694
|
+
showHistory && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "History", children: [
|
|
509
695
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
510
696
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
511
697
|
] }),
|
|
512
|
-
showSnap && /* @__PURE__ */ (0,
|
|
698
|
+
showSnap && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Snapping", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
513
699
|
"button",
|
|
514
700
|
{
|
|
515
701
|
type: "button",
|
|
516
702
|
"data-vector-snap": "",
|
|
517
|
-
className:
|
|
703
|
+
className: buttonClass2,
|
|
518
704
|
"aria-pressed": state.snap.objects,
|
|
519
705
|
title: `${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`,
|
|
520
706
|
"aria-label": VECTOR_SNAP_TITLE,
|
|
@@ -522,13 +708,13 @@ function VectorToolbar({ controller, tools = import_vector4.VECTOR_TOOLS, showHi
|
|
|
522
708
|
children: "Snap"
|
|
523
709
|
}
|
|
524
710
|
) }),
|
|
525
|
-
showPathEdit && /* @__PURE__ */ (0,
|
|
526
|
-
|
|
711
|
+
showPathEdit && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Path editing", children: [
|
|
712
|
+
import_vector5.VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
527
713
|
"button",
|
|
528
714
|
{
|
|
529
715
|
type: "button",
|
|
530
716
|
"data-vector-path-action": a.id,
|
|
531
|
-
className:
|
|
717
|
+
className: buttonClass2,
|
|
532
718
|
title: a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title,
|
|
533
719
|
"aria-label": a.title,
|
|
534
720
|
disabled: !a.enabled(count, points),
|
|
@@ -537,12 +723,12 @@ function VectorToolbar({ controller, tools = import_vector4.VECTOR_TOOLS, showHi
|
|
|
537
723
|
},
|
|
538
724
|
a.id
|
|
539
725
|
)),
|
|
540
|
-
|
|
726
|
+
import_vector5.VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
541
727
|
"button",
|
|
542
728
|
{
|
|
543
729
|
type: "button",
|
|
544
730
|
"data-vector-edit": t.key,
|
|
545
|
-
className:
|
|
731
|
+
className: buttonClass2,
|
|
546
732
|
"aria-pressed": editing[t.key],
|
|
547
733
|
title: t.title,
|
|
548
734
|
"aria-label": t.title,
|
|
@@ -551,9 +737,9 @@ function VectorToolbar({ controller, tools = import_vector4.VECTOR_TOOLS, showHi
|
|
|
551
737
|
},
|
|
552
738
|
t.key
|
|
553
739
|
)),
|
|
554
|
-
state.tool === "pencil" && /* @__PURE__ */ (0,
|
|
740
|
+
state.tool === "pencil" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
555
741
|
"Smoothing",
|
|
556
|
-
/* @__PURE__ */ (0,
|
|
742
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
557
743
|
"input",
|
|
558
744
|
{
|
|
559
745
|
type: "range",
|
|
@@ -567,9 +753,9 @@ function VectorToolbar({ controller, tools = import_vector4.VECTOR_TOOLS, showHi
|
|
|
567
753
|
}
|
|
568
754
|
)
|
|
569
755
|
] }),
|
|
570
|
-
state.tool === "eraser" && /* @__PURE__ */ (0,
|
|
756
|
+
state.tool === "eraser" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
571
757
|
"Size",
|
|
572
|
-
/* @__PURE__ */ (0,
|
|
758
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
573
759
|
"input",
|
|
574
760
|
{
|
|
575
761
|
type: "number",
|
|
@@ -585,35 +771,49 @@ function VectorToolbar({ controller, tools = import_vector4.VECTOR_TOOLS, showHi
|
|
|
585
771
|
}
|
|
586
772
|
)
|
|
587
773
|
] }),
|
|
588
|
-
state.tool === "paintBucket" && /* @__PURE__ */ (0,
|
|
774
|
+
state.tool === "paintBucket" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
589
775
|
"button",
|
|
590
776
|
{
|
|
591
777
|
type: "button",
|
|
592
778
|
"data-vector-fill-gap": "",
|
|
593
|
-
className:
|
|
779
|
+
className: buttonClass2,
|
|
594
780
|
"aria-pressed": editing.fillGap > 0,
|
|
595
781
|
title: "Close small gaps between path ends when filling",
|
|
596
782
|
"aria-label": "Close gaps",
|
|
597
|
-
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 :
|
|
783
|
+
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : import_vector5.VECTOR_FILL_GAP }),
|
|
598
784
|
children: "Gaps"
|
|
599
785
|
}
|
|
600
786
|
)
|
|
601
787
|
] }),
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
788
|
+
showBlend && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(VectorBlendControls, { controller }),
|
|
789
|
+
showArrange && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
790
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
|
|
791
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
792
|
+
"button",
|
|
793
|
+
{
|
|
794
|
+
type: "button",
|
|
795
|
+
"data-vector-live-boolean": "",
|
|
796
|
+
className: buttonClass2,
|
|
797
|
+
"aria-pressed": live,
|
|
798
|
+
title: "Live booleans: keep the shapes editable",
|
|
799
|
+
"aria-label": "Live booleans",
|
|
800
|
+
onClick: () => setLive(!live),
|
|
801
|
+
children: "Live"
|
|
802
|
+
}
|
|
803
|
+
),
|
|
804
|
+
act("\u222A", "Union", () => controller.booleanOp("union", { live }), booleanDisabled),
|
|
805
|
+
act("\u2212", "Subtract", () => controller.booleanOp("subtract", { live }), booleanDisabled),
|
|
806
|
+
act("\u2229", "Intersect", () => controller.booleanOp("intersect", { live }), booleanDisabled),
|
|
807
|
+
act("\u22BB", "Exclude", () => controller.booleanOp("exclude", { live }), booleanDisabled),
|
|
608
808
|
act("G", "Group", () => controller.group(), count < 1),
|
|
609
809
|
act("U", "Ungroup", () => controller.ungroup(), !groupSelected)
|
|
610
810
|
] }),
|
|
611
|
-
/* @__PURE__ */ (0,
|
|
811
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: import_vector5.VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
612
812
|
"button",
|
|
613
813
|
{
|
|
614
814
|
type: "button",
|
|
615
815
|
"data-vector-pathfinder": a.id,
|
|
616
|
-
className:
|
|
816
|
+
className: buttonClass2,
|
|
617
817
|
title: a.title,
|
|
618
818
|
"aria-label": a.title,
|
|
619
819
|
disabled: count < a.min,
|
|
@@ -622,7 +822,7 @@ function VectorToolbar({ controller, tools = import_vector4.VECTOR_TOOLS, showHi
|
|
|
622
822
|
},
|
|
623
823
|
a.id
|
|
624
824
|
)) }),
|
|
625
|
-
/* @__PURE__ */ (0,
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
626
826
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
627
827
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
628
828
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -635,11 +835,74 @@ function VectorToolbar({ controller, tools = import_vector4.VECTOR_TOOLS, showHi
|
|
|
635
835
|
] })
|
|
636
836
|
] });
|
|
637
837
|
}
|
|
638
|
-
|
|
639
|
-
|
|
838
|
+
function VectorBlendControls({ controller }) {
|
|
839
|
+
const state = useVectorEditorState(controller);
|
|
840
|
+
const blend = (0, import_vector5.getVectorBlendControls)(state);
|
|
841
|
+
const o = blend.options;
|
|
842
|
+
const selected = blend.ids.length > 0;
|
|
843
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Blend", "data-vector-blend-controls": "", children: [
|
|
844
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", "data-vector-blend-action": "make", className: buttonClass2, title: "Make Blend", "aria-label": "Make Blend", disabled: !blend.canBlend, onClick: () => controller.blend(), children: "\u29D3" }),
|
|
845
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
846
|
+
"select",
|
|
847
|
+
{
|
|
848
|
+
"aria-label": "Blend spacing",
|
|
849
|
+
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
850
|
+
value: o.spacing,
|
|
851
|
+
onChange: (e) => (0, import_vector5.applyVectorBlendOptions)(controller, { spacing: e.target.value }),
|
|
852
|
+
children: import_vector5.VECTOR_BLEND_SPACINGS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: sp, children: import_vector5.VECTOR_BLEND_SPACING_LABELS[sp] }, sp))
|
|
853
|
+
}
|
|
854
|
+
),
|
|
855
|
+
o.spacing !== "smoothColor" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
856
|
+
"input",
|
|
857
|
+
{
|
|
858
|
+
type: "number",
|
|
859
|
+
min: o.spacing === "steps" ? 1 : 0.5,
|
|
860
|
+
step: 1,
|
|
861
|
+
"aria-label": o.spacing === "steps" ? "Blend steps" : "Blend distance",
|
|
862
|
+
className: "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs",
|
|
863
|
+
value: o.spacing === "steps" ? o.steps : o.distance,
|
|
864
|
+
onChange: (e) => {
|
|
865
|
+
const n = parseFloat(e.target.value);
|
|
866
|
+
if (!Number.isFinite(n) || n <= 0) return;
|
|
867
|
+
(0, import_vector5.applyVectorBlendOptions)(controller, o.spacing === "steps" ? { steps: n } : { distance: n });
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
),
|
|
871
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
872
|
+
"button",
|
|
873
|
+
{
|
|
874
|
+
type: "button",
|
|
875
|
+
"data-vector-blend-action": "orient",
|
|
876
|
+
className: buttonClass2,
|
|
877
|
+
"aria-pressed": o.orientToSpine,
|
|
878
|
+
title: "Orient steps to the spine",
|
|
879
|
+
"aria-label": "Orient to spine",
|
|
880
|
+
onClick: () => (0, import_vector5.applyVectorBlendOptions)(controller, { orientToSpine: !o.orientToSpine }),
|
|
881
|
+
children: "\u293F"
|
|
882
|
+
}
|
|
883
|
+
),
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
885
|
+
"button",
|
|
886
|
+
{
|
|
887
|
+
type: "button",
|
|
888
|
+
"data-vector-blend-action": "spine",
|
|
889
|
+
className: buttonClass2,
|
|
890
|
+
title: "Replace Spine (select a blend and a path)",
|
|
891
|
+
"aria-label": "Replace Spine",
|
|
892
|
+
disabled: !blend.canReplaceSpine,
|
|
893
|
+
onClick: () => controller.replaceBlendSpine(),
|
|
894
|
+
children: "\u2307"
|
|
895
|
+
}
|
|
896
|
+
),
|
|
897
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", "data-vector-blend-action": "expand", className: buttonClass2, title: "Expand Blend", "aria-label": "Expand Blend", disabled: !selected, onClick: () => controller.expandBlend(), children: "\u29C9" }),
|
|
898
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", "data-vector-blend-action": "release", className: buttonClass2, title: "Release Blend", "aria-label": "Release Blend", disabled: !selected, onClick: () => controller.releaseBlend(), children: "\u29C4" })
|
|
899
|
+
] });
|
|
900
|
+
}
|
|
901
|
+
var selectClass2 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
902
|
+
var numberClass2 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
640
903
|
function VectorStylePanel({ controller, className }) {
|
|
641
904
|
const state = useVectorEditorState(controller);
|
|
642
|
-
const style = (0,
|
|
905
|
+
const style = (0, import_vector5.getVectorSelectionStyle)(state);
|
|
643
906
|
const d = state.defaults;
|
|
644
907
|
const source = style ?? {
|
|
645
908
|
fill: d.fill ?? null,
|
|
@@ -652,7 +915,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
652
915
|
arrowAlign: d.arrowAlign ?? "extend",
|
|
653
916
|
startArrowScale: d.startArrowScale ?? 1,
|
|
654
917
|
endArrowScale: d.endArrowScale ?? 1,
|
|
655
|
-
widthProfile: (0,
|
|
918
|
+
widthProfile: (0, import_vector5.widthProfilePresetId)(d.strokeWidthProfile),
|
|
656
919
|
cornerRadius: d.cornerRadius,
|
|
657
920
|
cornerKind: d.cornerKind ?? "round",
|
|
658
921
|
corners: 1,
|
|
@@ -665,19 +928,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
665
928
|
};
|
|
666
929
|
const setProfile = (id) => {
|
|
667
930
|
if (style) controller.setWidthProfile(id);
|
|
668
|
-
else controller.setDefaults({ strokeWidthProfile: (0,
|
|
931
|
+
else controller.setDefaults({ strokeWidthProfile: (0, import_vector5.widthProfilePreset)(id)?.length ? (0, import_vector5.widthProfilePreset)(id) : null });
|
|
669
932
|
};
|
|
670
|
-
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0,
|
|
933
|
+
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
|
|
671
934
|
const arrowRow = (end, label) => {
|
|
672
935
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
673
936
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
674
|
-
return /* @__PURE__ */ (0,
|
|
675
|
-
/* @__PURE__ */ (0,
|
|
676
|
-
/* @__PURE__ */ (0,
|
|
677
|
-
/* @__PURE__ */ (0,
|
|
678
|
-
|
|
937
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
938
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16 text-xs text-foreground", children: label }),
|
|
939
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("select", { "aria-label": `${label} arrowhead`, className: selectClass2, value: source[key] ?? "", onChange: (e) => apply({ [key]: e.target.value || null }), children: [
|
|
940
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: "None" }),
|
|
941
|
+
import_vector5.VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: h, children: import_vector5.VECTOR_ARROWHEAD_LABELS[h] }, h))
|
|
679
942
|
] }),
|
|
680
|
-
/* @__PURE__ */ (0,
|
|
943
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
681
944
|
"input",
|
|
682
945
|
{
|
|
683
946
|
type: "number",
|
|
@@ -685,7 +948,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
685
948
|
step: 0.25,
|
|
686
949
|
"aria-label": `${label} arrowhead scale`,
|
|
687
950
|
title: "Scale (\xD7 stroke width)",
|
|
688
|
-
className:
|
|
951
|
+
className: numberClass2,
|
|
689
952
|
value: source[scaleKey],
|
|
690
953
|
onChange: (e) => {
|
|
691
954
|
const n = parseFloat(e.target.value);
|
|
@@ -701,14 +964,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
701
964
|
};
|
|
702
965
|
const paintRow = (key, label) => {
|
|
703
966
|
const paint = source[key];
|
|
704
|
-
const hex = (0,
|
|
967
|
+
const hex = (0, import_vector5.vectorPaintToHex)(paint);
|
|
705
968
|
const on = paint !== null && paint !== "none";
|
|
706
|
-
return /* @__PURE__ */ (0,
|
|
707
|
-
/* @__PURE__ */ (0,
|
|
708
|
-
/* @__PURE__ */ (0,
|
|
969
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
970
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex w-16 items-center gap-1.5 text-xs text-foreground", children: [
|
|
971
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", checked: on, "aria-label": `${label} on`, onChange: (e) => apply({ [key]: e.target.checked ? hex ?? "#000000" : null }) }),
|
|
709
972
|
label
|
|
710
973
|
] }),
|
|
711
|
-
/* @__PURE__ */ (0,
|
|
974
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
712
975
|
"input",
|
|
713
976
|
{
|
|
714
977
|
type: "color",
|
|
@@ -719,17 +982,17 @@ function VectorStylePanel({ controller, className }) {
|
|
|
719
982
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
720
983
|
}
|
|
721
984
|
),
|
|
722
|
-
on && !hex && /* @__PURE__ */ (0,
|
|
723
|
-
style?.mixed[key] && /* @__PURE__ */ (0,
|
|
985
|
+
on && !hex && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "truncate text-[11px] text-muted-foreground", children: typeof paint === "string" ? paint : "Gradient" }),
|
|
986
|
+
style?.mixed[key] && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
724
987
|
] });
|
|
725
988
|
};
|
|
726
|
-
return /* @__PURE__ */ (0,
|
|
727
|
-
/* @__PURE__ */ (0,
|
|
989
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "aria-label": style ? "Selection style" : "New shape style", children: [
|
|
990
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: style ? "Selection" : "New shapes" }),
|
|
728
991
|
paintRow("fill", "Fill"),
|
|
729
992
|
paintRow("stroke", "Stroke"),
|
|
730
|
-
/* @__PURE__ */ (0,
|
|
731
|
-
/* @__PURE__ */ (0,
|
|
732
|
-
/* @__PURE__ */ (0,
|
|
993
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
994
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16", children: "Width" }),
|
|
995
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
733
996
|
"input",
|
|
734
997
|
{
|
|
735
998
|
type: "number",
|
|
@@ -745,33 +1008,33 @@ function VectorStylePanel({ controller, className }) {
|
|
|
745
1008
|
}
|
|
746
1009
|
)
|
|
747
1010
|
] }),
|
|
748
|
-
/* @__PURE__ */ (0,
|
|
749
|
-
/* @__PURE__ */ (0,
|
|
750
|
-
/* @__PURE__ */ (0,
|
|
1011
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "strokeAlign", children: [
|
|
1012
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16", children: "Align" }),
|
|
1013
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { "aria-label": "Stroke alignment", className: selectClass2, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(import_vector5.VECTOR_STROKE_ALIGN_LABELS).map((a) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: a, children: import_vector5.VECTOR_STROKE_ALIGN_LABELS[a] }, a)) }),
|
|
751
1014
|
mixed("strokeAlign")
|
|
752
1015
|
] }),
|
|
753
|
-
/* @__PURE__ */ (0,
|
|
754
|
-
/* @__PURE__ */ (0,
|
|
755
|
-
/* @__PURE__ */ (0,
|
|
1016
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
|
|
1017
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16", children: "Profile" }),
|
|
1018
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
756
1019
|
"select",
|
|
757
1020
|
{
|
|
758
1021
|
"aria-label": "Width profile",
|
|
759
|
-
className:
|
|
1022
|
+
className: selectClass2,
|
|
760
1023
|
value: source.widthProfile,
|
|
761
1024
|
onChange: (e) => {
|
|
762
1025
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
763
1026
|
},
|
|
764
1027
|
children: [
|
|
765
|
-
|
|
766
|
-
source.widthProfile === "custom" && /* @__PURE__ */ (0,
|
|
1028
|
+
import_vector5.VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: p.id, children: p.label }, p.id)),
|
|
1029
|
+
source.widthProfile === "custom" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "custom", disabled: true, children: "Custom" })
|
|
767
1030
|
]
|
|
768
1031
|
}
|
|
769
1032
|
),
|
|
770
|
-
/* @__PURE__ */ (0,
|
|
1033
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
771
1034
|
"button",
|
|
772
1035
|
{
|
|
773
1036
|
type: "button",
|
|
774
|
-
className:
|
|
1037
|
+
className: buttonClass2,
|
|
775
1038
|
title: "Reset to uniform width",
|
|
776
1039
|
"aria-label": "Reset to uniform width",
|
|
777
1040
|
disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
|
|
@@ -781,27 +1044,27 @@ function VectorStylePanel({ controller, className }) {
|
|
|
781
1044
|
),
|
|
782
1045
|
mixed("widthProfile")
|
|
783
1046
|
] }),
|
|
784
|
-
source.hasOpenPath && /* @__PURE__ */ (0,
|
|
1047
|
+
source.hasOpenPath && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
785
1048
|
arrowRow("start", "Start"),
|
|
786
1049
|
arrowRow("end", "End"),
|
|
787
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0,
|
|
788
|
-
/* @__PURE__ */ (0,
|
|
789
|
-
/* @__PURE__ */ (0,
|
|
790
|
-
/* @__PURE__ */ (0,
|
|
791
|
-
/* @__PURE__ */ (0,
|
|
1050
|
+
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "arrowAlign", children: [
|
|
1051
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16", children: "Heads" }),
|
|
1052
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("select", { "aria-label": "Arrowhead alignment", className: selectClass2, value: source.arrowAlign, onChange: (e) => apply({ arrowAlign: e.target.value }), children: [
|
|
1053
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "extend", children: "Tip past end" }),
|
|
1054
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "tip", children: "Tip at end" })
|
|
792
1055
|
] })
|
|
793
1056
|
] })
|
|
794
1057
|
] }),
|
|
795
|
-
source.corners > 0 && /* @__PURE__ */ (0,
|
|
796
|
-
/* @__PURE__ */ (0,
|
|
797
|
-
/* @__PURE__ */ (0,
|
|
1058
|
+
source.corners > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": "corners", children: [
|
|
1059
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Corners" }),
|
|
1060
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
798
1061
|
"input",
|
|
799
1062
|
{
|
|
800
1063
|
type: "number",
|
|
801
1064
|
min: 0,
|
|
802
1065
|
step: 1,
|
|
803
1066
|
"aria-label": "Corner radius",
|
|
804
|
-
className:
|
|
1067
|
+
className: numberClass2,
|
|
805
1068
|
value: Math.round(source.cornerRadius * 100) / 100,
|
|
806
1069
|
onChange: (e) => {
|
|
807
1070
|
const n = parseFloat(e.target.value);
|
|
@@ -809,12 +1072,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
809
1072
|
}
|
|
810
1073
|
}
|
|
811
1074
|
),
|
|
812
|
-
/* @__PURE__ */ (0,
|
|
1075
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { "aria-label": "Corner kind", className: selectClass2, value: source.cornerKind, onChange: (e) => setCorners({ kind: e.target.value }), children: import_vector5.VECTOR_CORNER_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: k, children: import_vector5.VECTOR_CORNER_KIND_LABELS[k] }, k)) }),
|
|
813
1076
|
mixed("cornerRadius")
|
|
814
1077
|
] }),
|
|
815
|
-
style && /* @__PURE__ */ (0,
|
|
816
|
-
/* @__PURE__ */ (0,
|
|
817
|
-
/* @__PURE__ */ (0,
|
|
1078
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
1079
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16", children: "Opacity" }),
|
|
1080
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
818
1081
|
"input",
|
|
819
1082
|
{
|
|
820
1083
|
type: "range",
|
|
@@ -827,18 +1090,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
827
1090
|
onChange: (e) => apply({ opacity: parseFloat(e.target.value) })
|
|
828
1091
|
}
|
|
829
1092
|
)
|
|
830
|
-
] })
|
|
1093
|
+
] }),
|
|
1094
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(VectorEffectsPanel, { controller })
|
|
831
1095
|
] });
|
|
832
1096
|
}
|
|
833
1097
|
|
|
834
1098
|
// src/vector/VectorEditor.tsx
|
|
835
|
-
var
|
|
1099
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
836
1100
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }) {
|
|
837
|
-
return /* @__PURE__ */ (0,
|
|
838
|
-
/* @__PURE__ */ (0,
|
|
839
|
-
/* @__PURE__ */ (0,
|
|
840
|
-
/* @__PURE__ */ (0,
|
|
841
|
-
showStylePanel && /* @__PURE__ */ (0,
|
|
1101
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `flex flex-col gap-2 ${className ?? ""}`, "data-vector-editor": "", children: [
|
|
1102
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VectorToolbar, { controller, tools }),
|
|
1103
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex min-h-0 flex-col gap-2 md:flex-row", children: [
|
|
1104
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.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_runtime5.jsx)(VectorCanvas, { controller, ...canvasProps }) }),
|
|
1105
|
+
showStylePanel && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(VectorStylePanel, { controller, className: "w-full shrink-0 rounded-md border border-border p-3 md:w-56" })
|
|
842
1106
|
] })
|
|
843
1107
|
] });
|
|
844
1108
|
}
|
|
@@ -846,6 +1110,7 @@ function VectorEditor({ controller, tools, showStylePanel = true, height = 520,
|
|
|
846
1110
|
0 && (module.exports = {
|
|
847
1111
|
VectorCanvas,
|
|
848
1112
|
VectorEditor,
|
|
1113
|
+
VectorEffectsPanel,
|
|
849
1114
|
VectorGradientDefs,
|
|
850
1115
|
VectorSceneNodes,
|
|
851
1116
|
VectorStylePanel,
|