@pixerate/editor-react 0.66.0 → 0.68.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/README.md +1 -0
- package/dist/paint-editor/index.cjs +893 -0
- package/dist/paint-editor/index.cjs.map +1 -0
- package/dist/paint-editor/index.d.cts +130 -0
- package/dist/paint-editor/index.d.ts +130 -0
- package/dist/paint-editor/index.js +876 -0
- package/dist/paint-editor/index.js.map +1 -0
- package/dist/vector/index.cjs +482 -210
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +19 -2
- package/dist/vector/index.d.ts +19 -2
- package/dist/vector/index.js +468 -193
- package/dist/vector/index.js.map +1 -1
- package/package.json +11 -3
package/dist/vector/index.cjs
CHANGED
|
@@ -30,10 +30,12 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/vector/index.ts
|
|
31
31
|
var vector_exports = {};
|
|
32
32
|
__export(vector_exports, {
|
|
33
|
+
VectorAppearancePanel: () => VectorAppearancePanel,
|
|
33
34
|
VectorCanvas: () => VectorCanvas,
|
|
34
35
|
VectorEditor: () => VectorEditor,
|
|
35
36
|
VectorEffectsPanel: () => VectorEffectsPanel,
|
|
36
37
|
VectorEnvelopePanel: () => VectorEnvelopePanel,
|
|
38
|
+
VectorFilterDefs: () => VectorFilterDefs,
|
|
37
39
|
VectorGradientAnnotator: () => VectorGradientAnnotator,
|
|
38
40
|
VectorGradientDefs: () => VectorGradientDefs,
|
|
39
41
|
VectorGradientEditor: () => VectorGradientEditor,
|
|
@@ -91,7 +93,7 @@ function useVectorCommands(registry, controller, options = {}) {
|
|
|
91
93
|
}
|
|
92
94
|
|
|
93
95
|
// src/vector/VectorCanvas.tsx
|
|
94
|
-
var import_react3 = require("react");
|
|
96
|
+
var import_react3 = __toESM(require("react"), 1);
|
|
95
97
|
var import_vector3 = require("@pixerate/editor/vector");
|
|
96
98
|
|
|
97
99
|
// src/vector/VectorWidthPointEditor.tsx
|
|
@@ -224,37 +226,95 @@ function VectorGradientAnnotator({ annotator: g, accentColor = import_vector3.VE
|
|
|
224
226
|
] }, s.index))
|
|
225
227
|
] });
|
|
226
228
|
}
|
|
229
|
+
function VectorFilterDefs({ filters }) {
|
|
230
|
+
if (!filters.length) return null;
|
|
231
|
+
const primitive = (p, key) => import_react3.default.createElement(p.tag, { key, ...p.attrs }, p.children?.map(primitive));
|
|
232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: filters.map((f) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("filter", { id: f.id, filterUnits: "userSpaceOnUse", x: f.x, y: f.y, width: f.width, height: f.height, colorInterpolationFilters: "sRGB", children: f.primitives.map(primitive) }, f.id)) });
|
|
233
|
+
}
|
|
234
|
+
var blendStyle = (blendMode) => blendMode ? { mixBlendMode: blendMode } : void 0;
|
|
227
235
|
function VectorSceneNodes({ nodes }) {
|
|
228
236
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: nodes.map(
|
|
229
|
-
(node) => node.kind === "group" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
230
|
-
"
|
|
237
|
+
(node) => node.kind === "group" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
238
|
+
"g",
|
|
231
239
|
{
|
|
232
240
|
"data-vector-id": node.id,
|
|
233
241
|
transform: node.transform,
|
|
242
|
+
opacity: node.opacity < 1 ? node.opacity : void 0,
|
|
243
|
+
filter: node.filter,
|
|
244
|
+
style: blendStyle(node.blendMode),
|
|
245
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(VectorSceneNodes, { nodes: node.children })
|
|
246
|
+
},
|
|
247
|
+
node.id
|
|
248
|
+
) : node.layers ? (
|
|
249
|
+
// Fill and stroke stacks: each layer in order, bottom to top.
|
|
250
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
251
|
+
"g",
|
|
252
|
+
{
|
|
253
|
+
"data-vector-id": node.id,
|
|
254
|
+
transform: node.transform,
|
|
255
|
+
opacity: node.opacity < 1 ? node.opacity : void 0,
|
|
256
|
+
filter: node.filter,
|
|
257
|
+
style: blendStyle(node.blendMode),
|
|
258
|
+
children: node.layers.map((layer) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(VectorPaintPath, { paint: layer, d: node.d, fillRule: node.fillRule, layer: `${layer.kind}-${layer.index}` }, `${layer.kind}-${layer.index}`))
|
|
259
|
+
},
|
|
260
|
+
node.id
|
|
261
|
+
)
|
|
262
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
263
|
+
VectorPaintPath,
|
|
264
|
+
{
|
|
265
|
+
paint: node,
|
|
234
266
|
d: node.d,
|
|
235
|
-
fill: node.fill,
|
|
236
267
|
fillRule: node.fillRule,
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
strokeDasharray: node.strokeDasharray,
|
|
242
|
-
opacity: node.opacity < 1 ? node.opacity : void 0
|
|
268
|
+
id: node.id,
|
|
269
|
+
transform: node.transform,
|
|
270
|
+
filter: node.filter,
|
|
271
|
+
blendMode: node.blendMode
|
|
243
272
|
},
|
|
244
273
|
node.id
|
|
245
274
|
)
|
|
246
275
|
) });
|
|
247
276
|
}
|
|
248
|
-
function
|
|
249
|
-
|
|
277
|
+
function VectorPaintPath({
|
|
278
|
+
paint,
|
|
279
|
+
d,
|
|
280
|
+
fillRule,
|
|
281
|
+
id,
|
|
282
|
+
transform,
|
|
283
|
+
filter,
|
|
284
|
+
blendMode,
|
|
285
|
+
layer
|
|
286
|
+
}) {
|
|
287
|
+
const opacity = paint.opacity < 1 ? paint.opacity : void 0;
|
|
288
|
+
const style = blendStyle(blendMode ?? (layer ? paint.blendMode : void 0));
|
|
289
|
+
const sp = paint.strokeParts;
|
|
290
|
+
if (!sp)
|
|
291
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
292
|
+
"path",
|
|
293
|
+
{
|
|
294
|
+
"data-vector-id": id,
|
|
295
|
+
"data-vector-layer": layer,
|
|
296
|
+
transform,
|
|
297
|
+
d,
|
|
298
|
+
fill: paint.fill,
|
|
299
|
+
fillRule,
|
|
300
|
+
stroke: paint.stroke,
|
|
301
|
+
strokeWidth: paint.stroke === "none" ? void 0 : paint.strokeWidth,
|
|
302
|
+
strokeLinecap: paint.strokeLinecap,
|
|
303
|
+
strokeLinejoin: paint.strokeLinejoin,
|
|
304
|
+
strokeDasharray: paint.strokeDasharray,
|
|
305
|
+
opacity,
|
|
306
|
+
filter,
|
|
307
|
+
style
|
|
308
|
+
}
|
|
309
|
+
);
|
|
250
310
|
const clip = sp.clip;
|
|
251
311
|
const b = clip?.bounds;
|
|
252
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-id":
|
|
253
|
-
clip && b && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: clip.kind === "clip" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("clipPath", { id: clip.id, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d
|
|
312
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("g", { "data-vector-id": id, "data-vector-layer": layer, "data-vector-stroke-align": sp.align, transform, opacity, filter, style, children: [
|
|
313
|
+
clip && b && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("defs", { children: clip.kind === "clip" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("clipPath", { id: clip.id, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d, clipRule: fillRule }) }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("mask", { id: clip.id, maskUnits: "userSpaceOnUse", x: b.x, y: b.y, width: b.width, height: b.height, children: [
|
|
254
314
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: b.x, y: b.y, width: b.width, height: b.height, fill: "#fff" }),
|
|
255
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d
|
|
315
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d, fill: "#000", fillRule })
|
|
256
316
|
] }) }),
|
|
257
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-part": "fill", d
|
|
317
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-part": "fill", d, fill: paint.fill, fillRule, stroke: "none" }),
|
|
258
318
|
sp.outline !== void 0 ? (
|
|
259
319
|
// A variable-width stroke: its outline, filled.
|
|
260
320
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
@@ -262,7 +322,7 @@ function VectorPartedPath({ node }) {
|
|
|
262
322
|
{
|
|
263
323
|
"data-vector-part": "stroke-outline",
|
|
264
324
|
d: sp.outline,
|
|
265
|
-
fill:
|
|
325
|
+
fill: paint.stroke,
|
|
266
326
|
clipPath: clip?.kind === "clip" ? `url(#${clip.id})` : void 0,
|
|
267
327
|
mask: clip?.kind === "mask" ? `url(#${clip.id})` : void 0
|
|
268
328
|
}
|
|
@@ -273,16 +333,16 @@ function VectorPartedPath({ node }) {
|
|
|
273
333
|
"data-vector-part": "stroke",
|
|
274
334
|
d: sp.d,
|
|
275
335
|
fill: "none",
|
|
276
|
-
stroke:
|
|
336
|
+
stroke: paint.stroke,
|
|
277
337
|
strokeWidth: sp.width,
|
|
278
|
-
strokeLinecap:
|
|
279
|
-
strokeLinejoin:
|
|
280
|
-
strokeDasharray:
|
|
338
|
+
strokeLinecap: paint.strokeLinecap,
|
|
339
|
+
strokeLinejoin: paint.strokeLinejoin,
|
|
340
|
+
strokeDasharray: paint.strokeDasharray,
|
|
281
341
|
clipPath: clip?.kind === "clip" ? `url(#${clip.id})` : void 0,
|
|
282
342
|
mask: clip?.kind === "mask" ? `url(#${clip.id})` : void 0
|
|
283
343
|
}
|
|
284
344
|
),
|
|
285
|
-
sp.heads.map((head, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-part": "head", d: head, fill:
|
|
345
|
+
sp.heads.map((head, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { "data-vector-part": "head", d: head, fill: paint.stroke }, i))
|
|
286
346
|
] });
|
|
287
347
|
}
|
|
288
348
|
function VectorCanvas({
|
|
@@ -388,6 +448,7 @@ function VectorCanvas({
|
|
|
388
448
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: 8, y: 8, width: 8, height: 8, fill: "#e5e7eb" })
|
|
389
449
|
] }) }),
|
|
390
450
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(VectorGradientDefs, { defs: scene.defs }),
|
|
451
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(VectorFilterDefs, { filters: scene.filters }),
|
|
391
452
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
392
453
|
"rect",
|
|
393
454
|
{
|
|
@@ -568,7 +629,7 @@ function VectorCanvas({
|
|
|
568
629
|
|
|
569
630
|
// src/vector/VectorToolbar.tsx
|
|
570
631
|
var import_react5 = __toESM(require("react"), 1);
|
|
571
|
-
var
|
|
632
|
+
var import_vector8 = require("@pixerate/editor/vector");
|
|
572
633
|
|
|
573
634
|
// src/vector/VectorEffectsPanel.tsx
|
|
574
635
|
var import_vector4 = require("@pixerate/editor/vector");
|
|
@@ -710,14 +771,222 @@ function VectorEffectsPanel({ controller, className }) {
|
|
|
710
771
|
] });
|
|
711
772
|
}
|
|
712
773
|
|
|
713
|
-
// src/vector/
|
|
714
|
-
var import_react4 = __toESM(require("react"), 1);
|
|
774
|
+
// src/vector/VectorAppearancePanel.tsx
|
|
715
775
|
var import_vector5 = require("@pixerate/editor/vector");
|
|
716
776
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
717
777
|
var buttonClass2 = "inline-flex h-7 min-w-7 items-center justify-center rounded-md border border-border bg-background px-1.5 text-xs font-medium text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40";
|
|
718
778
|
var numberClass2 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
719
779
|
var selectClass2 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
780
|
+
var headingClass = "text-[11px] font-medium uppercase tracking-wide text-muted-foreground";
|
|
720
781
|
var labelClass2 = "w-full truncate text-[11px] text-muted-foreground";
|
|
782
|
+
function VectorAppearancePanel({ controller, className }) {
|
|
783
|
+
const state = useVectorEditorState(controller);
|
|
784
|
+
const panel = (0, import_vector5.getVectorAppearancePanel)(state);
|
|
785
|
+
if (!panel) return null;
|
|
786
|
+
const end = () => controller.endMergedEdit();
|
|
787
|
+
const ids = panel.pathIds;
|
|
788
|
+
const update = (l, patch, merge = false) => controller.updatePaintLayer(l.kind, l.index, patch, { ids, merge });
|
|
789
|
+
const layerRow = (l, count) => {
|
|
790
|
+
const name = `${l.kind === "fill" ? "Fill" : "Stroke"} ${l.index + 1}`;
|
|
791
|
+
if (l.unknownKind)
|
|
792
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "text-[11px] text-muted-foreground", "data-vector-layer": `${l.kind}-${l.index}`, children: [
|
|
793
|
+
name,
|
|
794
|
+
": ",
|
|
795
|
+
l.unknownKind,
|
|
796
|
+
" (not drawn by this version)"
|
|
797
|
+
] }, `${l.kind}-${l.index}`);
|
|
798
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "space-y-1 rounded border border-border p-1", "data-vector-layer": `${l.kind}-${l.index}`, "data-vector-layer-editing": l.editing ? "" : void 0, children: [
|
|
799
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
800
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", "aria-label": `${name} visible`, title: "Show", checked: l.visible, onChange: (e) => update(l, { visible: e.target.checked }) }),
|
|
801
|
+
l.gradient ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
802
|
+
"button",
|
|
803
|
+
{
|
|
804
|
+
type: "button",
|
|
805
|
+
"aria-label": `${name} gradient`,
|
|
806
|
+
title: "Edit this gradient",
|
|
807
|
+
className: "h-7 w-10 rounded border border-border",
|
|
808
|
+
style: { background: l.swatch },
|
|
809
|
+
onClick: () => controller.setGradientTarget(l.kind, l.index)
|
|
810
|
+
}
|
|
811
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
812
|
+
"input",
|
|
813
|
+
{
|
|
814
|
+
type: "color",
|
|
815
|
+
"aria-label": `${name} colour`,
|
|
816
|
+
className: "h-7 w-10 cursor-pointer rounded border border-border bg-background",
|
|
817
|
+
value: l.color ?? "#000000",
|
|
818
|
+
onChange: (e) => update(l, { paint: e.target.value }, true),
|
|
819
|
+
onBlur: end
|
|
820
|
+
}
|
|
821
|
+
),
|
|
822
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
823
|
+
"input",
|
|
824
|
+
{
|
|
825
|
+
type: "number",
|
|
826
|
+
min: 0,
|
|
827
|
+
max: 100,
|
|
828
|
+
step: 5,
|
|
829
|
+
"aria-label": `${name} opacity`,
|
|
830
|
+
title: "Opacity %",
|
|
831
|
+
className: numberClass2,
|
|
832
|
+
value: Math.round(l.opacity * 100),
|
|
833
|
+
onChange: (e) => {
|
|
834
|
+
const n = parseFloat(e.target.value);
|
|
835
|
+
if (Number.isFinite(n)) update(l, { opacity: Math.min(100, Math.max(0, n)) / 100 }, true);
|
|
836
|
+
},
|
|
837
|
+
onBlur: end
|
|
838
|
+
}
|
|
839
|
+
),
|
|
840
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { "aria-label": `${name} blend mode`, className: selectClass2, value: l.blendMode, onChange: (e) => update(l, { blendMode: e.target.value }), children: import_vector5.VECTOR_BLEND_MODE_MENU.map((m) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: m.mode, children: m.label }, m.mode)) })
|
|
841
|
+
] }),
|
|
842
|
+
l.kind === "stroke" && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
843
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
844
|
+
"input",
|
|
845
|
+
{
|
|
846
|
+
type: "number",
|
|
847
|
+
min: 0,
|
|
848
|
+
step: 0.5,
|
|
849
|
+
"aria-label": `${name} width`,
|
|
850
|
+
title: "Width",
|
|
851
|
+
className: numberClass2,
|
|
852
|
+
value: l.strokeWidth ?? 1,
|
|
853
|
+
onChange: (e) => {
|
|
854
|
+
const n = parseFloat(e.target.value);
|
|
855
|
+
if (Number.isFinite(n) && n >= 0) update(l, { strokeWidth: n }, true);
|
|
856
|
+
},
|
|
857
|
+
onBlur: end
|
|
858
|
+
}
|
|
859
|
+
),
|
|
860
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { "aria-label": `${name} alignment`, className: selectClass2, value: l.strokeAlign ?? "center", onChange: (e) => update(l, { 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)) })
|
|
861
|
+
] }),
|
|
862
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
863
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "flex-1" }),
|
|
864
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, title: "Edit gradient", "aria-label": `Edit ${name} gradient`, "aria-pressed": l.editing, onClick: () => controller.setGradientTarget(l.kind, l.index), children: "\u270E" }),
|
|
865
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, title: "Move up", "aria-label": `Move ${name} up`, disabled: l.index === count - 1, onClick: () => controller.movePaintLayer(l.kind, l.index, l.index + 1, { ids }), children: "\u2191" }),
|
|
866
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, title: "Move down", "aria-label": `Move ${name} down`, disabled: l.index === 0, onClick: () => controller.movePaintLayer(l.kind, l.index, l.index - 1, { ids }), children: "\u2193" }),
|
|
867
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, title: "Remove", "aria-label": `Remove ${name}`, onClick: () => controller.removePaintLayer(l.kind, l.index, { ids }), children: "\xD7" })
|
|
868
|
+
] })
|
|
869
|
+
] }, `${l.kind}-${l.index}`);
|
|
870
|
+
};
|
|
871
|
+
const stack = (kind, layers, mixed) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "space-y-1", "data-vector-stack": kind, children: [
|
|
872
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
873
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `flex-1 ${headingClass}`, children: kind === "fill" ? "Fills" : "Strokes" }),
|
|
874
|
+
mixed && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }),
|
|
875
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
876
|
+
"button",
|
|
877
|
+
{
|
|
878
|
+
type: "button",
|
|
879
|
+
className: buttonClass2,
|
|
880
|
+
title: kind === "fill" ? "Add fill" : "Add stroke",
|
|
881
|
+
"aria-label": kind === "fill" ? "Add fill" : "Add stroke",
|
|
882
|
+
disabled: !ids.length,
|
|
883
|
+
onClick: () => controller.addPaintLayer(kind, {}, { ids }),
|
|
884
|
+
children: "+"
|
|
885
|
+
}
|
|
886
|
+
)
|
|
887
|
+
] }),
|
|
888
|
+
[...layers].reverse().map((l) => layerRow(l, layers.length))
|
|
889
|
+
] });
|
|
890
|
+
const filterNode = panel.filterNodeId;
|
|
891
|
+
const setFilter = (f, key, value, merge) => {
|
|
892
|
+
if (filterNode) controller.updateFilter(filterNode, f.id, { params: { [key]: value } }, { merge });
|
|
893
|
+
};
|
|
894
|
+
const filterParam = (f, spec) => {
|
|
895
|
+
const label = `${f.label} ${spec.label}`;
|
|
896
|
+
if (spec.kind === "color")
|
|
897
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-filter-param": spec.key, children: [
|
|
898
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-14 truncate text-[11px] text-muted-foreground", children: spec.label }),
|
|
899
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
900
|
+
"input",
|
|
901
|
+
{
|
|
902
|
+
type: "color",
|
|
903
|
+
"aria-label": label,
|
|
904
|
+
className: "h-7 w-10 cursor-pointer rounded border border-border bg-background",
|
|
905
|
+
value: /^#[0-9a-f]{6}$/i.test(String(f.params[spec.key])) ? String(f.params[spec.key]) : "#000000",
|
|
906
|
+
onChange: (e) => setFilter(f, spec.key, e.target.value, true),
|
|
907
|
+
onBlur: end
|
|
908
|
+
}
|
|
909
|
+
)
|
|
910
|
+
] }, spec.key);
|
|
911
|
+
if (spec.kind !== "number") return null;
|
|
912
|
+
const value = Number(f.params[spec.key] ?? 0);
|
|
913
|
+
const onChange = (e) => {
|
|
914
|
+
const n = parseFloat(e.target.value);
|
|
915
|
+
if (Number.isFinite(n)) setFilter(f, spec.key, n, true);
|
|
916
|
+
};
|
|
917
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-foreground", "data-vector-filter-param": spec.key, children: [
|
|
918
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: labelClass2, children: spec.label }),
|
|
919
|
+
spec.slider && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
920
|
+
"input",
|
|
921
|
+
{
|
|
922
|
+
type: "range",
|
|
923
|
+
min: spec.min,
|
|
924
|
+
max: spec.max,
|
|
925
|
+
step: spec.step,
|
|
926
|
+
"aria-label": `${label} slider`,
|
|
927
|
+
className: "h-4 min-w-0 flex-1 accent-primary",
|
|
928
|
+
value,
|
|
929
|
+
onChange,
|
|
930
|
+
onPointerUp: end,
|
|
931
|
+
onKeyUp: end,
|
|
932
|
+
onBlur: end
|
|
933
|
+
}
|
|
934
|
+
),
|
|
935
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "number", min: spec.min, max: spec.max, step: spec.step, "aria-label": label, className: numberClass2, value: Math.round(value * 1e3) / 1e3, onChange, onBlur: end })
|
|
936
|
+
] }, spec.key);
|
|
937
|
+
};
|
|
938
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-appearance": "", "aria-label": "Appearance", children: [
|
|
939
|
+
ids.length > 0 && stack("stroke", panel.strokes, panel.mixed.strokes),
|
|
940
|
+
ids.length > 0 && stack("fill", panel.fills, panel.mixed.fills),
|
|
941
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "blendMode", children: [
|
|
942
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "w-16", children: "Blend" }),
|
|
943
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("select", { "aria-label": "Blend mode", className: selectClass2, value: panel.blendMode, onChange: (e) => controller.setBlendMode(e.target.value, { ids: panel.nodeIds }), children: import_vector5.VECTOR_BLEND_MODE_MENU.map((m) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: m.mode, children: m.label }, m.mode)) }),
|
|
944
|
+
panel.mixed.blendMode && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
945
|
+
] }),
|
|
946
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "space-y-2", "data-vector-filters": "", children: [
|
|
947
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
948
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `w-16 ${headingClass}`, children: "Filters" }),
|
|
949
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
950
|
+
"select",
|
|
951
|
+
{
|
|
952
|
+
"aria-label": "Add filter",
|
|
953
|
+
className: selectClass2,
|
|
954
|
+
value: "",
|
|
955
|
+
onChange: (e) => {
|
|
956
|
+
if (e.target.value) controller.addFilter(e.target.value, { ids: panel.nodeIds });
|
|
957
|
+
},
|
|
958
|
+
children: [
|
|
959
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: "Add filter\u2026" }),
|
|
960
|
+
import_vector5.VECTOR_FILTER_MENU.map((m) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: m.type, children: m.label }, m.type))
|
|
961
|
+
]
|
|
962
|
+
}
|
|
963
|
+
)
|
|
964
|
+
] }),
|
|
965
|
+
!filterNode && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Select one object to edit its filters." }),
|
|
966
|
+
filterNode && panel.filters.map((f, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "space-y-1 rounded border border-border p-1.5", "data-vector-filter": f.id, "data-vector-filter-type": f.type, children: [
|
|
967
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
968
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "flex min-w-0 flex-1 items-center gap-1.5 text-xs font-medium text-foreground", children: [
|
|
969
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("input", { type: "checkbox", "aria-label": `${f.label} on`, checked: f.enabled, onChange: (e) => controller.updateFilter(filterNode, f.id, { enabled: e.target.checked }) }),
|
|
970
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "truncate", children: f.label })
|
|
971
|
+
] }),
|
|
972
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, title: "Move up", "aria-label": `Move ${f.label} up`, disabled: i === 0, onClick: () => controller.moveFilter(filterNode, f.id, i - 1), children: "\u2191" }),
|
|
973
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, title: "Move down", "aria-label": `Move ${f.label} down`, disabled: i === panel.filters.length - 1, onClick: () => controller.moveFilter(filterNode, f.id, i + 1), children: "\u2193" }),
|
|
974
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: buttonClass2, title: "Remove", "aria-label": `Remove ${f.label}`, onClick: () => controller.removeFilter(filterNode, f.id), children: "\xD7" })
|
|
975
|
+
] }),
|
|
976
|
+
f.specs.map((spec) => filterParam(f, spec))
|
|
977
|
+
] }, f.id))
|
|
978
|
+
] })
|
|
979
|
+
] });
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// src/vector/VectorEnvelopePanel.tsx
|
|
983
|
+
var import_react4 = __toESM(require("react"), 1);
|
|
984
|
+
var import_vector6 = require("@pixerate/editor/vector");
|
|
985
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
986
|
+
var buttonClass3 = "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";
|
|
987
|
+
var numberClass3 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
988
|
+
var selectClass3 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
989
|
+
var labelClass3 = "w-full truncate text-[11px] text-muted-foreground";
|
|
721
990
|
var SLIDERS = [
|
|
722
991
|
{ key: "bend", label: "Bend %" },
|
|
723
992
|
{ key: "horizontal", label: "Horizontal distortion %" },
|
|
@@ -725,7 +994,7 @@ var SLIDERS = [
|
|
|
725
994
|
];
|
|
726
995
|
function VectorEnvelopePanel({ controller, className }) {
|
|
727
996
|
const state = useVectorEditorState(controller);
|
|
728
|
-
const panel = (0,
|
|
997
|
+
const panel = (0, import_vector6.getVectorEnvelopePanel)(state);
|
|
729
998
|
const [size, setSize] = import_react4.default.useState({ rows: 2, columns: 2 });
|
|
730
999
|
if (!panel) return null;
|
|
731
1000
|
const env = panel.envelope;
|
|
@@ -740,16 +1009,16 @@ function VectorEnvelopePanel({ controller, className }) {
|
|
|
740
1009
|
if (env) set({ [key]: n });
|
|
741
1010
|
else setSize({ ...size, [key]: n });
|
|
742
1011
|
};
|
|
743
|
-
return /* @__PURE__ */ (0,
|
|
744
|
-
/* @__PURE__ */ (0,
|
|
745
|
-
/* @__PURE__ */ (0,
|
|
746
|
-
/* @__PURE__ */ (0,
|
|
747
|
-
/* @__PURE__ */ (0,
|
|
1012
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "data-vector-envelope": "", "aria-label": "Envelope", children: [
|
|
1013
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
1014
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-16 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: "Envelope" }),
|
|
1015
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", "data-vector-envelope-action": "warp", className: buttonClass3, title: "Make with Warp", "aria-label": "Make with Warp", disabled: !panel.canMake || !!env, onClick: () => set({ style: "arc", bend: 50 }), children: "Warp" }),
|
|
1016
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
748
1017
|
"button",
|
|
749
1018
|
{
|
|
750
1019
|
type: "button",
|
|
751
1020
|
"data-vector-envelope-action": "mesh",
|
|
752
|
-
className:
|
|
1021
|
+
className: buttonClass3,
|
|
753
1022
|
title: "Make with Mesh",
|
|
754
1023
|
"aria-label": "Make with Mesh",
|
|
755
1024
|
disabled: !panel.canMake || !!env,
|
|
@@ -757,12 +1026,12 @@ function VectorEnvelopePanel({ controller, className }) {
|
|
|
757
1026
|
children: "Mesh"
|
|
758
1027
|
}
|
|
759
1028
|
),
|
|
760
|
-
/* @__PURE__ */ (0,
|
|
1029
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
761
1030
|
"button",
|
|
762
1031
|
{
|
|
763
1032
|
type: "button",
|
|
764
1033
|
"data-vector-envelope-action": "top",
|
|
765
|
-
className:
|
|
1034
|
+
className: buttonClass3,
|
|
766
1035
|
title: "Make with Top Object",
|
|
767
1036
|
"aria-label": "Make with Top Object",
|
|
768
1037
|
disabled: !panel.canMakeWithTopObject,
|
|
@@ -770,12 +1039,12 @@ function VectorEnvelopePanel({ controller, className }) {
|
|
|
770
1039
|
children: "Top"
|
|
771
1040
|
}
|
|
772
1041
|
),
|
|
773
|
-
/* @__PURE__ */ (0,
|
|
774
|
-
/* @__PURE__ */ (0,
|
|
1042
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", "data-vector-envelope-action": "release", className: buttonClass3, title: "Release Envelope", "aria-label": "Release Envelope", disabled: !panel.canRelease, onClick: () => controller.releaseEnvelope(), children: "Release" }),
|
|
1043
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", "data-vector-envelope-action": "expand", className: buttonClass3, title: "Expand Envelope", "aria-label": "Expand Envelope", disabled: !panel.canRelease, onClick: () => controller.expandAppearance(), children: "Expand" })
|
|
775
1044
|
] }),
|
|
776
|
-
env && /* @__PURE__ */ (0,
|
|
777
|
-
/* @__PURE__ */ (0,
|
|
778
|
-
/* @__PURE__ */ (0,
|
|
1045
|
+
env && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-foreground", "data-vector-envelope-param": "style", children: [
|
|
1046
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: labelClass3, children: "Warp" }),
|
|
1047
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("select", { "aria-label": "Envelope warp", className: selectClass3, value: env.params.style, onChange: (e) => set({ style: e.target.value }), children: import_vector6.VECTOR_ENVELOPE_STYLE_OPTIONS.map((o) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: o.value, children: o.label }, o.value)) })
|
|
779
1048
|
] }),
|
|
780
1049
|
env && env.params.style !== "mesh" && SLIDERS.map((s) => {
|
|
781
1050
|
const value = env.params[s.key];
|
|
@@ -783,9 +1052,9 @@ function VectorEnvelopePanel({ controller, className }) {
|
|
|
783
1052
|
const n = parseFloat(ev.target.value);
|
|
784
1053
|
if (Number.isFinite(n)) set({ [s.key]: n }, true);
|
|
785
1054
|
};
|
|
786
|
-
return /* @__PURE__ */ (0,
|
|
787
|
-
/* @__PURE__ */ (0,
|
|
788
|
-
/* @__PURE__ */ (0,
|
|
1055
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-foreground", "data-vector-envelope-param": s.key, children: [
|
|
1056
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: labelClass3, children: s.label }),
|
|
1057
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
789
1058
|
"input",
|
|
790
1059
|
{
|
|
791
1060
|
type: "range",
|
|
@@ -801,36 +1070,36 @@ function VectorEnvelopePanel({ controller, className }) {
|
|
|
801
1070
|
onBlur: end
|
|
802
1071
|
}
|
|
803
1072
|
),
|
|
804
|
-
/* @__PURE__ */ (0,
|
|
1073
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "number", min: -100, max: 100, step: 1, "aria-label": `Envelope ${s.label}`, className: numberClass3, value, onChange, onBlur: end })
|
|
805
1074
|
] }, s.key);
|
|
806
1075
|
}),
|
|
807
|
-
env && env.params.style !== "mesh" && /* @__PURE__ */ (0,
|
|
808
|
-
/* @__PURE__ */ (0,
|
|
809
|
-
/* @__PURE__ */ (0,
|
|
810
|
-
/* @__PURE__ */ (0,
|
|
811
|
-
/* @__PURE__ */ (0,
|
|
1076
|
+
env && env.params.style !== "mesh" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs text-foreground", "data-vector-envelope-param": "orientation", children: [
|
|
1077
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: labelClass3, children: "Orientation" }),
|
|
1078
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("select", { "aria-label": "Envelope orientation", className: selectClass3, value: env.params.orientation, onChange: (e) => set({ orientation: e.target.value }), children: [
|
|
1079
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "horizontal", children: "Horizontal" }),
|
|
1080
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "vertical", children: "Vertical" })
|
|
812
1081
|
] })
|
|
813
1082
|
] }),
|
|
814
|
-
/* @__PURE__ */ (0,
|
|
815
|
-
/* @__PURE__ */ (0,
|
|
816
|
-
/* @__PURE__ */ (0,
|
|
817
|
-
/* @__PURE__ */ (0,
|
|
1083
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-envelope-param": "mesh", children: [
|
|
1084
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "min-w-0 flex-1 truncate text-[11px] text-muted-foreground", children: "Mesh rows \xD7 columns" }),
|
|
1085
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "number", min: 1, max: 16, step: 1, "aria-label": "Envelope mesh rows", className: numberClass3, value: rows, onChange: (e) => setCount("rows", e.target.value) }),
|
|
1086
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("input", { type: "number", min: 1, max: 16, step: 1, "aria-label": "Envelope mesh columns", className: numberClass3, value: columns, onChange: (e) => setCount("columns", e.target.value) })
|
|
818
1087
|
] }),
|
|
819
|
-
panel.count > 1 && !panel.canMakeWithTopObject && /* @__PURE__ */ (0,
|
|
820
|
-
env && /* @__PURE__ */ (0,
|
|
1088
|
+
panel.count > 1 && !panel.canMakeWithTopObject && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Select one object to edit its envelope." }),
|
|
1089
|
+
env && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-[11px] text-muted-foreground", children: "Edit the mesh with the Envelope tool (U)." })
|
|
821
1090
|
] });
|
|
822
1091
|
}
|
|
823
1092
|
|
|
824
1093
|
// src/vector/VectorGradientEditor.tsx
|
|
825
|
-
var
|
|
826
|
-
var
|
|
827
|
-
var
|
|
828
|
-
var
|
|
829
|
-
var
|
|
1094
|
+
var import_vector7 = require("@pixerate/editor/vector");
|
|
1095
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
1096
|
+
var selectClass4 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
1097
|
+
var numberClass4 = "h-7 w-14 rounded border border-border bg-background px-1.5 text-xs";
|
|
1098
|
+
var buttonClass4 = "inline-flex h-7 min-w-7 items-center justify-center rounded border border-border bg-background px-1.5 text-xs text-foreground hover:bg-muted disabled:cursor-not-allowed disabled:opacity-40 aria-pressed:bg-primary aria-pressed:text-primary-foreground";
|
|
830
1099
|
var percent = (v) => Math.round(v * 1e3) / 10;
|
|
831
1100
|
function VectorGradientEditor({ controller, className }) {
|
|
832
1101
|
const state = useVectorEditorState(controller);
|
|
833
|
-
const ed = (0,
|
|
1102
|
+
const ed = (0, import_vector7.getVectorGradientEditor)(state);
|
|
834
1103
|
if (!ed) return null;
|
|
835
1104
|
const g = ed.gradient;
|
|
836
1105
|
const sel = ed.selected;
|
|
@@ -838,26 +1107,26 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
838
1107
|
const setType = (value) => {
|
|
839
1108
|
if (value === "solid") {
|
|
840
1109
|
const first = ed.stops[0];
|
|
841
|
-
controller.setStyle({ [ed.target]: (0,
|
|
1110
|
+
controller.setStyle({ [ed.target]: (0, import_vector7.vectorPaintToHex)(first?.color) ?? first?.color ?? "#000000" }, void 0, { label: "Solid Colour" });
|
|
842
1111
|
} else controller.setGradient({ type: value });
|
|
843
1112
|
};
|
|
844
|
-
return /* @__PURE__ */ (0,
|
|
845
|
-
/* @__PURE__ */ (0,
|
|
846
|
-
/* @__PURE__ */ (0,
|
|
847
|
-
["fill", "stroke"].map((t) => /* @__PURE__ */ (0,
|
|
848
|
-
ed.mixed && /* @__PURE__ */ (0,
|
|
1113
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: `space-y-1.5 ${className ?? ""}`, "data-vector-gradient-editor": ed.target, "aria-label": "Gradient", children: [
|
|
1114
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
1115
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Gradient" }),
|
|
1116
|
+
["fill", "stroke"].map((t) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: buttonClass4, "aria-pressed": ed.target === t, onClick: () => controller.setGradientTarget(t), children: t === "fill" ? "Fill" : "Stroke" }, t)),
|
|
1117
|
+
ed.mixed && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
849
1118
|
] }),
|
|
850
|
-
/* @__PURE__ */ (0,
|
|
851
|
-
/* @__PURE__ */ (0,
|
|
852
|
-
/* @__PURE__ */ (0,
|
|
853
|
-
/* @__PURE__ */ (0,
|
|
854
|
-
|
|
1119
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center gap-1.5", children: [
|
|
1120
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Type" }),
|
|
1121
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("select", { "aria-label": "Gradient type", className: selectClass4, value: ed.type ?? "solid", onChange: (e) => setType(e.target.value), children: [
|
|
1122
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: "solid", children: "Solid" }),
|
|
1123
|
+
import_vector7.VECTOR_GRADIENT_TYPES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: t, children: import_vector7.VECTOR_GRADIENT_TYPE_LABELS[t] }, t))
|
|
855
1124
|
] }),
|
|
856
|
-
/* @__PURE__ */ (0,
|
|
1125
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: buttonClass4, "aria-label": "Reverse gradient", title: "Reverse gradient", disabled: !g, onClick: () => controller.reverseGradient(), children: "\u21C4" })
|
|
857
1126
|
] }),
|
|
858
|
-
g && /* @__PURE__ */ (0,
|
|
859
|
-
/* @__PURE__ */ (0,
|
|
860
|
-
/* @__PURE__ */ (0,
|
|
1127
|
+
g && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
1128
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "relative h-8", "data-vector-gradient-ramp": "", children: [
|
|
1129
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
861
1130
|
"div",
|
|
862
1131
|
{
|
|
863
1132
|
role: "button",
|
|
@@ -871,7 +1140,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
871
1140
|
}
|
|
872
1141
|
}
|
|
873
1142
|
),
|
|
874
|
-
ed.stops.map((s) => /* @__PURE__ */ (0,
|
|
1143
|
+
ed.stops.map((s) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
875
1144
|
"button",
|
|
876
1145
|
{
|
|
877
1146
|
type: "button",
|
|
@@ -885,21 +1154,21 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
885
1154
|
s.index
|
|
886
1155
|
))
|
|
887
1156
|
] }),
|
|
888
|
-
sel && /* @__PURE__ */ (0,
|
|
889
|
-
/* @__PURE__ */ (0,
|
|
1157
|
+
sel && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex flex-wrap items-center gap-1.5", "data-vector-gradient-selected-stop": sel.index, children: [
|
|
1158
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
890
1159
|
"input",
|
|
891
1160
|
{
|
|
892
1161
|
type: "color",
|
|
893
1162
|
"aria-label": "Stop colour",
|
|
894
1163
|
className: "h-7 w-9 cursor-pointer rounded border border-border bg-background",
|
|
895
|
-
value: (0,
|
|
1164
|
+
value: (0, import_vector7.vectorPaintToHex)(sel.color) ?? "#000000",
|
|
896
1165
|
onChange: (e) => controller.setGradientStop(sel.index, { color: e.target.value }, { merge: `gradient-stop-color-${sel.index}` }),
|
|
897
1166
|
onBlur: end
|
|
898
1167
|
}
|
|
899
1168
|
),
|
|
900
|
-
/* @__PURE__ */ (0,
|
|
1169
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
901
1170
|
"Opacity",
|
|
902
|
-
/* @__PURE__ */ (0,
|
|
1171
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
903
1172
|
"input",
|
|
904
1173
|
{
|
|
905
1174
|
type: "number",
|
|
@@ -907,7 +1176,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
907
1176
|
max: 100,
|
|
908
1177
|
step: 5,
|
|
909
1178
|
"aria-label": "Stop opacity",
|
|
910
|
-
className:
|
|
1179
|
+
className: numberClass4,
|
|
911
1180
|
value: percent(sel.opacity ?? 1),
|
|
912
1181
|
onChange: (e) => {
|
|
913
1182
|
const n = parseFloat(e.target.value);
|
|
@@ -916,9 +1185,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
916
1185
|
}
|
|
917
1186
|
)
|
|
918
1187
|
] }),
|
|
919
|
-
/* @__PURE__ */ (0,
|
|
1188
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
920
1189
|
"At",
|
|
921
|
-
/* @__PURE__ */ (0,
|
|
1190
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
922
1191
|
"input",
|
|
923
1192
|
{
|
|
924
1193
|
type: "number",
|
|
@@ -926,7 +1195,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
926
1195
|
max: 100,
|
|
927
1196
|
step: 1,
|
|
928
1197
|
"aria-label": "Stop position",
|
|
929
|
-
className:
|
|
1198
|
+
className: numberClass4,
|
|
930
1199
|
value: percent(sel.offset),
|
|
931
1200
|
onChange: (e) => {
|
|
932
1201
|
const n = parseFloat(e.target.value);
|
|
@@ -935,9 +1204,9 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
935
1204
|
}
|
|
936
1205
|
)
|
|
937
1206
|
] }),
|
|
938
|
-
!sel.last && /* @__PURE__ */ (0,
|
|
1207
|
+
!sel.last && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1 text-[11px] text-muted-foreground", children: [
|
|
939
1208
|
"Midpoint",
|
|
940
|
-
/* @__PURE__ */ (0,
|
|
1209
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
941
1210
|
"input",
|
|
942
1211
|
{
|
|
943
1212
|
type: "number",
|
|
@@ -945,7 +1214,7 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
945
1214
|
max: 95,
|
|
946
1215
|
step: 1,
|
|
947
1216
|
"aria-label": "Stop midpoint",
|
|
948
|
-
className:
|
|
1217
|
+
className: numberClass4,
|
|
949
1218
|
value: percent(sel.midpoint ?? 0.5),
|
|
950
1219
|
onChange: (e) => {
|
|
951
1220
|
const n = parseFloat(e.target.value);
|
|
@@ -954,15 +1223,15 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
954
1223
|
}
|
|
955
1224
|
)
|
|
956
1225
|
] }),
|
|
957
|
-
/* @__PURE__ */ (0,
|
|
1226
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: buttonClass4, "aria-label": "Delete stop", title: "Delete stop", disabled: ed.stops.length <= 2, onClick: () => controller.removeGradientStop(sel.index), children: "\u2715" })
|
|
958
1227
|
] }),
|
|
959
|
-
/* @__PURE__ */ (0,
|
|
960
|
-
/* @__PURE__ */ (0,
|
|
961
|
-
/* @__PURE__ */ (0,
|
|
1228
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
1229
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16", children: "Colours" }),
|
|
1230
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("select", { "aria-label": "Gradient interpolation", className: selectClass4, value: ed.interpolation, onChange: (e) => controller.setGradient({ interpolation: e.target.value }), children: import_vector7.VECTOR_GRADIENT_INTERPOLATIONS.map((i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: i, children: import_vector7.VECTOR_GRADIENT_INTERPOLATION_LABELS[i] }, i)) })
|
|
962
1231
|
] }),
|
|
963
|
-
/* @__PURE__ */ (0,
|
|
964
|
-
/* @__PURE__ */ (0,
|
|
965
|
-
/* @__PURE__ */ (0,
|
|
1232
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
1233
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16", children: "Smooth" }),
|
|
1234
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
966
1235
|
"input",
|
|
967
1236
|
{
|
|
968
1237
|
type: "range",
|
|
@@ -978,26 +1247,26 @@ function VectorGradientEditor({ controller, className }) {
|
|
|
978
1247
|
}
|
|
979
1248
|
)
|
|
980
1249
|
] }),
|
|
981
|
-
/* @__PURE__ */ (0,
|
|
982
|
-
/* @__PURE__ */ (0,
|
|
983
|
-
/* @__PURE__ */ (0,
|
|
1250
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
1251
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16", children: "Spread" }),
|
|
1252
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("select", { "aria-label": "Gradient spread", className: selectClass4, value: ed.spread, onChange: (e) => controller.setGradient({ spread: e.target.value }), children: import_vector7.VECTOR_GRADIENT_SPREADS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: sp, children: import_vector7.VECTOR_GRADIENT_SPREAD_LABELS[sp] }, sp)) })
|
|
984
1253
|
] }),
|
|
985
|
-
ed.target === "stroke" && /* @__PURE__ */ (0,
|
|
986
|
-
/* @__PURE__ */ (0,
|
|
987
|
-
/* @__PURE__ */ (0,
|
|
1254
|
+
ed.target === "stroke" && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("label", { className: "flex items-center gap-1.5 text-xs text-foreground", children: [
|
|
1255
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "w-16", children: "On stroke" }),
|
|
1256
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("select", { "aria-label": "Gradient on stroke", className: selectClass4, value: ed.strokeMode, onChange: (e) => controller.setGradient({ strokeMode: e.target.value }), children: import_vector7.VECTOR_STROKE_GRADIENT_MODES.map((m) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("option", { value: m, children: import_vector7.VECTOR_STROKE_GRADIENT_MODE_LABELS[m] }, m)) })
|
|
988
1257
|
] })
|
|
989
1258
|
] })
|
|
990
1259
|
] });
|
|
991
1260
|
}
|
|
992
1261
|
|
|
993
1262
|
// src/vector/VectorToolbar.tsx
|
|
994
|
-
var
|
|
1263
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
995
1264
|
var VECTOR_SNAP_TITLE = "Snap to objects";
|
|
996
1265
|
var modKeyLabel = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad/.test(navigator.platform ?? "") ? "\u2318" : "Ctrl";
|
|
997
|
-
var
|
|
1266
|
+
var buttonClass5 = "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";
|
|
998
1267
|
function VectorToolbar({
|
|
999
1268
|
controller,
|
|
1000
|
-
tools =
|
|
1269
|
+
tools = import_vector8.VECTOR_TOOLS,
|
|
1001
1270
|
showHistory = true,
|
|
1002
1271
|
showArrange = true,
|
|
1003
1272
|
showSnap = true,
|
|
@@ -1013,32 +1282,32 @@ function VectorToolbar({
|
|
|
1013
1282
|
const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === "group");
|
|
1014
1283
|
const [live, setLive] = import_react5.default.useState(false);
|
|
1015
1284
|
const booleanDisabled = live ? count < 1 : count < 2;
|
|
1016
|
-
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0,
|
|
1017
|
-
return /* @__PURE__ */ (0,
|
|
1018
|
-
/* @__PURE__ */ (0,
|
|
1285
|
+
const act = (label, title, run, disabled = false) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", className: buttonClass5, title, "aria-label": title, disabled, onClick: () => void run(), children: label }, label);
|
|
1286
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { role: "toolbar", "aria-label": "Vector tools", className: `flex flex-wrap items-center gap-1 ${className ?? ""}`, children: [
|
|
1287
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex items-center gap-1", role: "group", "aria-label": "Tools", children: tools.map((tool) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1019
1288
|
"button",
|
|
1020
1289
|
{
|
|
1021
1290
|
type: "button",
|
|
1022
1291
|
"data-vector-tool": tool,
|
|
1023
|
-
className:
|
|
1292
|
+
className: buttonClass5,
|
|
1024
1293
|
"aria-pressed": state.tool === tool,
|
|
1025
|
-
title: `${(0,
|
|
1026
|
-
"aria-label": (0,
|
|
1294
|
+
title: `${(0, import_vector8.vectorToolLabel)(tool)} (${import_vector8.VECTOR_TOOL_SHORTCUTS[tool]})`,
|
|
1295
|
+
"aria-label": (0, import_vector8.vectorToolLabel)(tool),
|
|
1027
1296
|
onClick: () => controller.setTool(tool),
|
|
1028
|
-
children:
|
|
1297
|
+
children: import_vector8.VECTOR_TOOL_GLYPHS[tool]
|
|
1029
1298
|
},
|
|
1030
1299
|
tool
|
|
1031
1300
|
)) }),
|
|
1032
|
-
showHistory && /* @__PURE__ */ (0,
|
|
1301
|
+
showHistory && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "History", children: [
|
|
1033
1302
|
act("\u21B6", state.canUndo ? `Undo ${state.undoLabel}` : "Undo", () => controller.undo(), !state.canUndo),
|
|
1034
1303
|
act("\u21B7", state.canRedo ? `Redo ${state.redoLabel}` : "Redo", () => controller.redo(), !state.canRedo)
|
|
1035
1304
|
] }),
|
|
1036
|
-
showSnap && /* @__PURE__ */ (0,
|
|
1305
|
+
showSnap && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Snapping", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1037
1306
|
"button",
|
|
1038
1307
|
{
|
|
1039
1308
|
type: "button",
|
|
1040
1309
|
"data-vector-snap": "",
|
|
1041
|
-
className:
|
|
1310
|
+
className: buttonClass5,
|
|
1042
1311
|
"aria-pressed": state.snap.objects,
|
|
1043
1312
|
title: `${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`,
|
|
1044
1313
|
"aria-label": VECTOR_SNAP_TITLE,
|
|
@@ -1046,13 +1315,13 @@ function VectorToolbar({
|
|
|
1046
1315
|
children: "Snap"
|
|
1047
1316
|
}
|
|
1048
1317
|
) }),
|
|
1049
|
-
showPathEdit && /* @__PURE__ */ (0,
|
|
1050
|
-
|
|
1318
|
+
showPathEdit && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Path editing", children: [
|
|
1319
|
+
import_vector8.VECTOR_PATH_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1051
1320
|
"button",
|
|
1052
1321
|
{
|
|
1053
1322
|
type: "button",
|
|
1054
1323
|
"data-vector-path-action": a.id,
|
|
1055
|
-
className:
|
|
1324
|
+
className: buttonClass5,
|
|
1056
1325
|
title: a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title,
|
|
1057
1326
|
"aria-label": a.title,
|
|
1058
1327
|
disabled: !a.enabled(count, points),
|
|
@@ -1061,12 +1330,12 @@ function VectorToolbar({
|
|
|
1061
1330
|
},
|
|
1062
1331
|
a.id
|
|
1063
1332
|
)),
|
|
1064
|
-
|
|
1333
|
+
import_vector8.VECTOR_EDIT_TOGGLES.map((t) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1065
1334
|
"button",
|
|
1066
1335
|
{
|
|
1067
1336
|
type: "button",
|
|
1068
1337
|
"data-vector-edit": t.key,
|
|
1069
|
-
className:
|
|
1338
|
+
className: buttonClass5,
|
|
1070
1339
|
"aria-pressed": editing[t.key],
|
|
1071
1340
|
title: t.title,
|
|
1072
1341
|
"aria-label": t.title,
|
|
@@ -1075,9 +1344,9 @@ function VectorToolbar({
|
|
|
1075
1344
|
},
|
|
1076
1345
|
t.key
|
|
1077
1346
|
)),
|
|
1078
|
-
state.tool === "pencil" && /* @__PURE__ */ (0,
|
|
1347
|
+
state.tool === "pencil" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
1079
1348
|
"Smoothing",
|
|
1080
|
-
/* @__PURE__ */ (0,
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1081
1350
|
"input",
|
|
1082
1351
|
{
|
|
1083
1352
|
type: "range",
|
|
@@ -1091,9 +1360,9 @@ function VectorToolbar({
|
|
|
1091
1360
|
}
|
|
1092
1361
|
)
|
|
1093
1362
|
] }),
|
|
1094
|
-
state.tool === "eraser" && /* @__PURE__ */ (0,
|
|
1363
|
+
state.tool === "eraser" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-1 text-xs text-foreground", children: [
|
|
1095
1364
|
"Size",
|
|
1096
|
-
/* @__PURE__ */ (0,
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1097
1366
|
"input",
|
|
1098
1367
|
{
|
|
1099
1368
|
type: "number",
|
|
@@ -1109,26 +1378,26 @@ function VectorToolbar({
|
|
|
1109
1378
|
}
|
|
1110
1379
|
)
|
|
1111
1380
|
] }),
|
|
1112
|
-
state.tool === "paintBucket" && /* @__PURE__ */ (0,
|
|
1381
|
+
state.tool === "paintBucket" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1113
1382
|
"button",
|
|
1114
1383
|
{
|
|
1115
1384
|
type: "button",
|
|
1116
1385
|
"data-vector-fill-gap": "",
|
|
1117
|
-
className:
|
|
1386
|
+
className: buttonClass5,
|
|
1118
1387
|
"aria-pressed": editing.fillGap > 0,
|
|
1119
1388
|
title: "Close small gaps between path ends when filling",
|
|
1120
1389
|
"aria-label": "Close gaps",
|
|
1121
|
-
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 :
|
|
1390
|
+
onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : import_vector8.VECTOR_FILL_GAP }),
|
|
1122
1391
|
children: "Gaps"
|
|
1123
1392
|
}
|
|
1124
1393
|
)
|
|
1125
1394
|
] }),
|
|
1126
|
-
showDistort && /* @__PURE__ */ (0,
|
|
1395
|
+
showDistort && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Distort", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1127
1396
|
"button",
|
|
1128
1397
|
{
|
|
1129
1398
|
type: "button",
|
|
1130
1399
|
"data-vector-free-distort": "",
|
|
1131
|
-
className:
|
|
1400
|
+
className: buttonClass5,
|
|
1132
1401
|
"aria-pressed": state.freeDistort,
|
|
1133
1402
|
title: `Free Distort: drag a corner of the selection box to distort in perspective (Shift+Alt+${modKeyLabel()}: symmetric perspective; ${modKeyLabel()}-drag a side to skew)`,
|
|
1134
1403
|
"aria-label": "Free Distort",
|
|
@@ -1136,15 +1405,15 @@ function VectorToolbar({
|
|
|
1136
1405
|
children: "Distort"
|
|
1137
1406
|
}
|
|
1138
1407
|
) }),
|
|
1139
|
-
showBlend && /* @__PURE__ */ (0,
|
|
1140
|
-
showArrange && /* @__PURE__ */ (0,
|
|
1141
|
-
/* @__PURE__ */ (0,
|
|
1142
|
-
/* @__PURE__ */ (0,
|
|
1408
|
+
showBlend && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VectorBlendControls, { controller }),
|
|
1409
|
+
showArrange && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1410
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
|
|
1411
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1143
1412
|
"button",
|
|
1144
1413
|
{
|
|
1145
1414
|
type: "button",
|
|
1146
1415
|
"data-vector-live-boolean": "",
|
|
1147
|
-
className:
|
|
1416
|
+
className: buttonClass5,
|
|
1148
1417
|
"aria-pressed": live,
|
|
1149
1418
|
title: "Live booleans: keep the shapes editable",
|
|
1150
1419
|
"aria-label": "Live booleans",
|
|
@@ -1159,12 +1428,12 @@ function VectorToolbar({
|
|
|
1159
1428
|
act("G", "Group", () => controller.group(), count < 1),
|
|
1160
1429
|
act("U", "Ungroup", () => controller.ungroup(), !groupSelected)
|
|
1161
1430
|
] }),
|
|
1162
|
-
/* @__PURE__ */ (0,
|
|
1431
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: import_vector8.VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1163
1432
|
"button",
|
|
1164
1433
|
{
|
|
1165
1434
|
type: "button",
|
|
1166
1435
|
"data-vector-pathfinder": a.id,
|
|
1167
|
-
className:
|
|
1436
|
+
className: buttonClass5,
|
|
1168
1437
|
title: a.title,
|
|
1169
1438
|
"aria-label": a.title,
|
|
1170
1439
|
disabled: count < a.min,
|
|
@@ -1173,7 +1442,7 @@ function VectorToolbar({
|
|
|
1173
1442
|
},
|
|
1174
1443
|
a.id
|
|
1175
1444
|
)) }),
|
|
1176
|
-
/* @__PURE__ */ (0,
|
|
1445
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
|
|
1177
1446
|
act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
|
|
1178
1447
|
act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
|
|
1179
1448
|
act("\u21E4", "Align Left", () => controller.align("left"), count < 1),
|
|
@@ -1188,22 +1457,22 @@ function VectorToolbar({
|
|
|
1188
1457
|
}
|
|
1189
1458
|
function VectorBlendControls({ controller }) {
|
|
1190
1459
|
const state = useVectorEditorState(controller);
|
|
1191
|
-
const blend = (0,
|
|
1460
|
+
const blend = (0, import_vector8.getVectorBlendControls)(state);
|
|
1192
1461
|
const o = blend.options;
|
|
1193
1462
|
const selected = blend.ids.length > 0;
|
|
1194
|
-
return /* @__PURE__ */ (0,
|
|
1195
|
-
/* @__PURE__ */ (0,
|
|
1196
|
-
/* @__PURE__ */ (0,
|
|
1463
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Blend", "data-vector-blend-controls": "", children: [
|
|
1464
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", "data-vector-blend-action": "make", className: buttonClass5, title: "Make Blend", "aria-label": "Make Blend", disabled: !blend.canBlend, onClick: () => controller.blend(), children: "\u29D3" }),
|
|
1465
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1197
1466
|
"select",
|
|
1198
1467
|
{
|
|
1199
1468
|
"aria-label": "Blend spacing",
|
|
1200
1469
|
className: "h-7 rounded border border-border bg-background px-1 text-xs",
|
|
1201
1470
|
value: o.spacing,
|
|
1202
|
-
onChange: (e) => (0,
|
|
1203
|
-
children:
|
|
1471
|
+
onChange: (e) => (0, import_vector8.applyVectorBlendOptions)(controller, { spacing: e.target.value }),
|
|
1472
|
+
children: import_vector8.VECTOR_BLEND_SPACINGS.map((sp) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: sp, children: import_vector8.VECTOR_BLEND_SPACING_LABELS[sp] }, sp))
|
|
1204
1473
|
}
|
|
1205
1474
|
),
|
|
1206
|
-
o.spacing !== "smoothColor" && /* @__PURE__ */ (0,
|
|
1475
|
+
o.spacing !== "smoothColor" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1207
1476
|
"input",
|
|
1208
1477
|
{
|
|
1209
1478
|
type: "number",
|
|
@@ -1215,29 +1484,29 @@ function VectorBlendControls({ controller }) {
|
|
|
1215
1484
|
onChange: (e) => {
|
|
1216
1485
|
const n = parseFloat(e.target.value);
|
|
1217
1486
|
if (!Number.isFinite(n) || n <= 0) return;
|
|
1218
|
-
(0,
|
|
1487
|
+
(0, import_vector8.applyVectorBlendOptions)(controller, o.spacing === "steps" ? { steps: n } : { distance: n });
|
|
1219
1488
|
}
|
|
1220
1489
|
}
|
|
1221
1490
|
),
|
|
1222
|
-
/* @__PURE__ */ (0,
|
|
1491
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1223
1492
|
"button",
|
|
1224
1493
|
{
|
|
1225
1494
|
type: "button",
|
|
1226
1495
|
"data-vector-blend-action": "orient",
|
|
1227
|
-
className:
|
|
1496
|
+
className: buttonClass5,
|
|
1228
1497
|
"aria-pressed": o.orientToSpine,
|
|
1229
1498
|
title: "Orient steps to the spine",
|
|
1230
1499
|
"aria-label": "Orient to spine",
|
|
1231
|
-
onClick: () => (0,
|
|
1500
|
+
onClick: () => (0, import_vector8.applyVectorBlendOptions)(controller, { orientToSpine: !o.orientToSpine }),
|
|
1232
1501
|
children: "\u293F"
|
|
1233
1502
|
}
|
|
1234
1503
|
),
|
|
1235
|
-
/* @__PURE__ */ (0,
|
|
1504
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1236
1505
|
"button",
|
|
1237
1506
|
{
|
|
1238
1507
|
type: "button",
|
|
1239
1508
|
"data-vector-blend-action": "spine",
|
|
1240
|
-
className:
|
|
1509
|
+
className: buttonClass5,
|
|
1241
1510
|
title: "Replace Spine (select a blend and a path)",
|
|
1242
1511
|
"aria-label": "Replace Spine",
|
|
1243
1512
|
disabled: !blend.canReplaceSpine,
|
|
@@ -1245,15 +1514,15 @@ function VectorBlendControls({ controller }) {
|
|
|
1245
1514
|
children: "\u2307"
|
|
1246
1515
|
}
|
|
1247
1516
|
),
|
|
1248
|
-
/* @__PURE__ */ (0,
|
|
1249
|
-
/* @__PURE__ */ (0,
|
|
1517
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", "data-vector-blend-action": "expand", className: buttonClass5, title: "Expand Blend", "aria-label": "Expand Blend", disabled: !selected, onClick: () => controller.expandBlend(), children: "\u29C9" }),
|
|
1518
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { type: "button", "data-vector-blend-action": "release", className: buttonClass5, title: "Release Blend", "aria-label": "Release Blend", disabled: !selected, onClick: () => controller.releaseBlend(), children: "\u29C4" })
|
|
1250
1519
|
] });
|
|
1251
1520
|
}
|
|
1252
|
-
var
|
|
1253
|
-
var
|
|
1521
|
+
var selectClass5 = "h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs";
|
|
1522
|
+
var numberClass5 = "h-7 w-16 rounded border border-border bg-background px-1.5 text-xs";
|
|
1254
1523
|
function VectorStylePanel({ controller, className }) {
|
|
1255
1524
|
const state = useVectorEditorState(controller);
|
|
1256
|
-
const style = (0,
|
|
1525
|
+
const style = (0, import_vector8.getVectorSelectionStyle)(state);
|
|
1257
1526
|
const d = state.defaults;
|
|
1258
1527
|
const source = style ?? {
|
|
1259
1528
|
fill: d.fill ?? null,
|
|
@@ -1266,7 +1535,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1266
1535
|
arrowAlign: d.arrowAlign ?? "extend",
|
|
1267
1536
|
startArrowScale: d.startArrowScale ?? 1,
|
|
1268
1537
|
endArrowScale: d.endArrowScale ?? 1,
|
|
1269
|
-
widthProfile: (0,
|
|
1538
|
+
widthProfile: (0, import_vector8.widthProfilePresetId)(d.strokeWidthProfile),
|
|
1270
1539
|
cornerRadius: d.cornerRadius,
|
|
1271
1540
|
cornerKind: d.cornerKind ?? "round",
|
|
1272
1541
|
corners: 1,
|
|
@@ -1279,19 +1548,19 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1279
1548
|
};
|
|
1280
1549
|
const setProfile = (id) => {
|
|
1281
1550
|
if (style) controller.setWidthProfile(id);
|
|
1282
|
-
else controller.setDefaults({ strokeWidthProfile: (0,
|
|
1551
|
+
else controller.setDefaults({ strokeWidthProfile: (0, import_vector8.widthProfilePreset)(id)?.length ? (0, import_vector8.widthProfilePreset)(id) : null });
|
|
1283
1552
|
};
|
|
1284
|
-
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0,
|
|
1553
|
+
const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
|
|
1285
1554
|
const arrowRow = (end, label) => {
|
|
1286
1555
|
const key = end === "start" ? "startArrow" : "endArrow";
|
|
1287
1556
|
const scaleKey = end === "start" ? "startArrowScale" : "endArrowScale";
|
|
1288
|
-
return /* @__PURE__ */ (0,
|
|
1289
|
-
/* @__PURE__ */ (0,
|
|
1290
|
-
/* @__PURE__ */ (0,
|
|
1291
|
-
/* @__PURE__ */ (0,
|
|
1292
|
-
|
|
1557
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
1558
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-16 text-xs text-foreground", children: label }),
|
|
1559
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("select", { "aria-label": `${label} arrowhead`, className: selectClass5, value: source[key] ?? "", onChange: (e) => apply({ [key]: e.target.value || null }), children: [
|
|
1560
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "", children: "None" }),
|
|
1561
|
+
import_vector8.VECTOR_ARROWHEADS.map((h) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: h, children: import_vector8.VECTOR_ARROWHEAD_LABELS[h] }, h))
|
|
1293
1562
|
] }),
|
|
1294
|
-
/* @__PURE__ */ (0,
|
|
1563
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1295
1564
|
"input",
|
|
1296
1565
|
{
|
|
1297
1566
|
type: "number",
|
|
@@ -1299,7 +1568,7 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1299
1568
|
step: 0.25,
|
|
1300
1569
|
"aria-label": `${label} arrowhead scale`,
|
|
1301
1570
|
title: "Scale (\xD7 stroke width)",
|
|
1302
|
-
className:
|
|
1571
|
+
className: numberClass5,
|
|
1303
1572
|
value: source[scaleKey],
|
|
1304
1573
|
onChange: (e) => {
|
|
1305
1574
|
const n = parseFloat(e.target.value);
|
|
@@ -1315,14 +1584,14 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1315
1584
|
};
|
|
1316
1585
|
const paintRow = (key, label) => {
|
|
1317
1586
|
const paint = source[key];
|
|
1318
|
-
const hex = (0,
|
|
1587
|
+
const hex = (0, import_vector8.vectorPaintToHex)(paint);
|
|
1319
1588
|
const on = paint !== null && paint !== "none";
|
|
1320
|
-
return /* @__PURE__ */ (0,
|
|
1321
|
-
/* @__PURE__ */ (0,
|
|
1322
|
-
/* @__PURE__ */ (0,
|
|
1589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": key, children: [
|
|
1590
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex w-16 items-center gap-1.5 text-xs text-foreground", children: [
|
|
1591
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("input", { type: "checkbox", checked: on, "aria-label": `${label} on`, onChange: (e) => apply({ [key]: e.target.checked ? hex ?? "#000000" : null }) }),
|
|
1323
1592
|
label
|
|
1324
1593
|
] }),
|
|
1325
|
-
/* @__PURE__ */ (0,
|
|
1594
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1326
1595
|
"input",
|
|
1327
1596
|
{
|
|
1328
1597
|
type: "color",
|
|
@@ -1333,18 +1602,18 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1333
1602
|
onChange: (e) => apply({ [key]: e.target.value })
|
|
1334
1603
|
}
|
|
1335
1604
|
),
|
|
1336
|
-
on && !hex && /* @__PURE__ */ (0,
|
|
1337
|
-
style?.mixed[key] && /* @__PURE__ */ (0,
|
|
1605
|
+
on && !hex && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate text-[11px] text-muted-foreground", children: typeof paint === "string" ? paint : "Gradient" }),
|
|
1606
|
+
style?.mixed[key] && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" })
|
|
1338
1607
|
] });
|
|
1339
1608
|
};
|
|
1340
|
-
return /* @__PURE__ */ (0,
|
|
1341
|
-
/* @__PURE__ */ (0,
|
|
1609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `space-y-2 ${className ?? ""}`, "aria-label": style ? "Selection style" : "New shape style", children: [
|
|
1610
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: style ? "Selection" : "New shapes" }),
|
|
1342
1611
|
paintRow("fill", "Fill"),
|
|
1343
1612
|
paintRow("stroke", "Stroke"),
|
|
1344
|
-
style && /* @__PURE__ */ (0,
|
|
1345
|
-
/* @__PURE__ */ (0,
|
|
1346
|
-
/* @__PURE__ */ (0,
|
|
1347
|
-
/* @__PURE__ */ (0,
|
|
1613
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VectorGradientEditor, { controller }),
|
|
1614
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
1615
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-16", children: "Width" }),
|
|
1616
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1348
1617
|
"input",
|
|
1349
1618
|
{
|
|
1350
1619
|
type: "number",
|
|
@@ -1360,33 +1629,33 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1360
1629
|
}
|
|
1361
1630
|
)
|
|
1362
1631
|
] }),
|
|
1363
|
-
/* @__PURE__ */ (0,
|
|
1364
|
-
/* @__PURE__ */ (0,
|
|
1365
|
-
/* @__PURE__ */ (0,
|
|
1632
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "strokeAlign", children: [
|
|
1633
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-16", children: "Align" }),
|
|
1634
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("select", { "aria-label": "Stroke alignment", className: selectClass5, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(import_vector8.VECTOR_STROKE_ALIGN_LABELS).map((a) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: a, children: import_vector8.VECTOR_STROKE_ALIGN_LABELS[a] }, a)) }),
|
|
1366
1635
|
mixed("strokeAlign")
|
|
1367
1636
|
] }),
|
|
1368
|
-
/* @__PURE__ */ (0,
|
|
1369
|
-
/* @__PURE__ */ (0,
|
|
1370
|
-
/* @__PURE__ */ (0,
|
|
1637
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
|
|
1638
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-16", children: "Profile" }),
|
|
1639
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
1371
1640
|
"select",
|
|
1372
1641
|
{
|
|
1373
1642
|
"aria-label": "Width profile",
|
|
1374
|
-
className:
|
|
1643
|
+
className: selectClass5,
|
|
1375
1644
|
value: source.widthProfile,
|
|
1376
1645
|
onChange: (e) => {
|
|
1377
1646
|
if (e.target.value !== "custom") setProfile(e.target.value);
|
|
1378
1647
|
},
|
|
1379
1648
|
children: [
|
|
1380
|
-
|
|
1381
|
-
source.widthProfile === "custom" && /* @__PURE__ */ (0,
|
|
1649
|
+
import_vector8.VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: p.id, children: p.label }, p.id)),
|
|
1650
|
+
source.widthProfile === "custom" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "custom", disabled: true, children: "Custom" })
|
|
1382
1651
|
]
|
|
1383
1652
|
}
|
|
1384
1653
|
),
|
|
1385
|
-
/* @__PURE__ */ (0,
|
|
1654
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1386
1655
|
"button",
|
|
1387
1656
|
{
|
|
1388
1657
|
type: "button",
|
|
1389
|
-
className:
|
|
1658
|
+
className: buttonClass5,
|
|
1390
1659
|
title: "Reset to uniform width",
|
|
1391
1660
|
"aria-label": "Reset to uniform width",
|
|
1392
1661
|
disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
|
|
@@ -1396,27 +1665,27 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1396
1665
|
),
|
|
1397
1666
|
mixed("widthProfile")
|
|
1398
1667
|
] }),
|
|
1399
|
-
source.hasOpenPath && /* @__PURE__ */ (0,
|
|
1668
|
+
source.hasOpenPath && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
1400
1669
|
arrowRow("start", "Start"),
|
|
1401
1670
|
arrowRow("end", "End"),
|
|
1402
|
-
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0,
|
|
1403
|
-
/* @__PURE__ */ (0,
|
|
1404
|
-
/* @__PURE__ */ (0,
|
|
1405
|
-
/* @__PURE__ */ (0,
|
|
1406
|
-
/* @__PURE__ */ (0,
|
|
1671
|
+
(source.startArrow || source.endArrow) && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "arrowAlign", children: [
|
|
1672
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-16", children: "Heads" }),
|
|
1673
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("select", { "aria-label": "Arrowhead alignment", className: selectClass5, value: source.arrowAlign, onChange: (e) => apply({ arrowAlign: e.target.value }), children: [
|
|
1674
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "extend", children: "Tip past end" }),
|
|
1675
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: "tip", children: "Tip at end" })
|
|
1407
1676
|
] })
|
|
1408
1677
|
] })
|
|
1409
1678
|
] }),
|
|
1410
|
-
source.corners > 0 && /* @__PURE__ */ (0,
|
|
1411
|
-
/* @__PURE__ */ (0,
|
|
1412
|
-
/* @__PURE__ */ (0,
|
|
1679
|
+
source.corners > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", "data-vector-style": "corners", children: [
|
|
1680
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-16 text-xs text-foreground", children: "Corners" }),
|
|
1681
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1413
1682
|
"input",
|
|
1414
1683
|
{
|
|
1415
1684
|
type: "number",
|
|
1416
1685
|
min: 0,
|
|
1417
1686
|
step: 1,
|
|
1418
1687
|
"aria-label": "Corner radius",
|
|
1419
|
-
className:
|
|
1688
|
+
className: numberClass5,
|
|
1420
1689
|
value: Math.round(source.cornerRadius * 100) / 100,
|
|
1421
1690
|
onChange: (e) => {
|
|
1422
1691
|
const n = parseFloat(e.target.value);
|
|
@@ -1424,12 +1693,12 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1424
1693
|
}
|
|
1425
1694
|
}
|
|
1426
1695
|
),
|
|
1427
|
-
/* @__PURE__ */ (0,
|
|
1696
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("select", { "aria-label": "Corner kind", className: selectClass5, value: source.cornerKind, onChange: (e) => setCorners({ kind: e.target.value }), children: import_vector8.VECTOR_CORNER_KINDS.map((k) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("option", { value: k, children: import_vector8.VECTOR_CORNER_KIND_LABELS[k] }, k)) }),
|
|
1428
1697
|
mixed("cornerRadius")
|
|
1429
1698
|
] }),
|
|
1430
|
-
style && /* @__PURE__ */ (0,
|
|
1431
|
-
/* @__PURE__ */ (0,
|
|
1432
|
-
/* @__PURE__ */ (0,
|
|
1699
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("label", { className: "flex items-center gap-2 text-xs text-foreground", children: [
|
|
1700
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "w-16", children: "Opacity" }),
|
|
1701
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
1433
1702
|
"input",
|
|
1434
1703
|
{
|
|
1435
1704
|
type: "range",
|
|
@@ -1443,28 +1712,31 @@ function VectorStylePanel({ controller, className }) {
|
|
|
1443
1712
|
}
|
|
1444
1713
|
)
|
|
1445
1714
|
] }),
|
|
1446
|
-
style && /* @__PURE__ */ (0,
|
|
1447
|
-
style && /* @__PURE__ */ (0,
|
|
1715
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VectorAppearancePanel, { controller }),
|
|
1716
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VectorEffectsPanel, { controller }),
|
|
1717
|
+
style && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(VectorEnvelopePanel, { controller })
|
|
1448
1718
|
] });
|
|
1449
1719
|
}
|
|
1450
1720
|
|
|
1451
1721
|
// src/vector/VectorEditor.tsx
|
|
1452
|
-
var
|
|
1722
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
1453
1723
|
function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }) {
|
|
1454
|
-
return /* @__PURE__ */ (0,
|
|
1455
|
-
/* @__PURE__ */ (0,
|
|
1456
|
-
/* @__PURE__ */ (0,
|
|
1457
|
-
/* @__PURE__ */ (0,
|
|
1458
|
-
showStylePanel && /* @__PURE__ */ (0,
|
|
1724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: `flex flex-col gap-2 ${className ?? ""}`, "data-vector-editor": "", children: [
|
|
1725
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(VectorToolbar, { controller, tools }),
|
|
1726
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex min-h-0 flex-col gap-2 md:flex-row", children: [
|
|
1727
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.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_runtime8.jsx)(VectorCanvas, { controller, ...canvasProps }) }),
|
|
1728
|
+
showStylePanel && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(VectorStylePanel, { controller, className: "w-full shrink-0 rounded-md border border-border p-3 md:w-56" })
|
|
1459
1729
|
] })
|
|
1460
1730
|
] });
|
|
1461
1731
|
}
|
|
1462
1732
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1463
1733
|
0 && (module.exports = {
|
|
1734
|
+
VectorAppearancePanel,
|
|
1464
1735
|
VectorCanvas,
|
|
1465
1736
|
VectorEditor,
|
|
1466
1737
|
VectorEffectsPanel,
|
|
1467
1738
|
VectorEnvelopePanel,
|
|
1739
|
+
VectorFilterDefs,
|
|
1468
1740
|
VectorGradientAnnotator,
|
|
1469
1741
|
VectorGradientDefs,
|
|
1470
1742
|
VectorGradientEditor,
|