@pixerate/editor-react 0.26.0 → 0.28.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.
@@ -117,7 +117,19 @@ function VectorPartedPath({ node }) {
117
117
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: node.d, fill: "#000", fillRule: node.fillRule })
118
118
  ] }) }),
119
119
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { "data-vector-part": "fill", d: node.d, fill: node.fill, fillRule: node.fillRule, stroke: "none" }),
120
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
120
+ sp.outline !== void 0 ? (
121
+ // A variable-width stroke: its outline, filled.
122
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
123
+ "path",
124
+ {
125
+ "data-vector-part": "stroke-outline",
126
+ d: sp.outline,
127
+ fill: node.stroke,
128
+ clipPath: clip?.kind === "clip" ? `url(#${clip.id})` : void 0,
129
+ mask: clip?.kind === "mask" ? `url(#${clip.id})` : void 0
130
+ }
131
+ )
132
+ ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
121
133
  "path",
122
134
  {
123
135
  "data-vector-part": "stroke",
@@ -273,7 +285,32 @@ function VectorCanvas({
273
285
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: w.x, cy: w.y, r: import_vector2.VECTOR_OVERLAY_THEME.cornerWidgetRadius + (w.hovered ? 1 : 0), fill: import_vector2.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor }),
274
286
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: w.x, cy: w.y, r: 1.5, fill: accentColor })
275
287
  ] }, `corner:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`)),
288
+ overlay.widthSpot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { "data-vector-width-spot": "", children: [
289
+ /* @__PURE__ */ (0, import_jsx_runtime.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" }),
290
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: (0, import_vector2.vectorDiamondPath)(overlay.widthSpot.x, overlay.widthSpot.y), fill: "none", stroke: accentColor })
291
+ ] }),
292
+ overlay.widthPoints.map((w) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { "data-vector-width-point": w.ref.index, "data-selected": w.selected || void 0, children: [
293
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: w.left.x, y1: w.left.y, x2: w.right.x, y2: w.right.y, stroke: accentColor }),
294
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: (0, import_vector2.vectorDiamondPath)(w.x, w.y), fill: w.selected || w.active ? accentColor : import_vector2.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor, strokeWidth: w.hovered === "center" ? 2 : 1 }),
295
+ ["left", "right"].map((side) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { "data-vector-width-side": side, cx: w[side].x, cy: w[side].y, r: import_vector2.VECTOR_OVERLAY_THEME.handleRadius + (w.hovered === side ? 1 : 0), fill: import_vector2.VECTOR_OVERLAY_THEME.handleFill, stroke: accentColor }, side))
296
+ ] }, `width:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`)),
276
297
  state.tool === "pen" && overlay.anchors.some((a) => a.closes && a.hovered) && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: overlay.anchors.find((a) => a.closes).x, cy: overlay.anchors.find((a) => a.closes).y, r: as, stroke: accentColor }),
298
+ overlay.builder && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("g", { "data-vector-builder": overlay.builder.mode, children: [
299
+ overlay.builder.faces.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
300
+ "path",
301
+ {
302
+ "data-vector-builder-face": "",
303
+ d,
304
+ fill: overlay.builder.mode === "erase" ? import_vector2.VECTOR_OVERLAY_THEME.builderEraseFill : import_vector2.VECTOR_OVERLAY_THEME.builderFill,
305
+ fillRule: "nonzero",
306
+ stroke: overlay.builder.mode === "erase" ? import_vector2.VECTOR_OVERLAY_THEME.builderErase : accentColor,
307
+ strokeWidth: 1
308
+ },
309
+ `f${i}`
310
+ )),
311
+ overlay.builder.lines.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { "data-vector-builder-line": "", d, fill: "none", stroke: import_vector2.VECTOR_OVERLAY_THEME.builderErase, strokeWidth: 3, strokeLinecap: "round" }, `l${i}`)),
312
+ overlay.builder.trail && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { "data-vector-builder-trail": "", d: overlay.builder.trail, fill: "none", stroke: overlay.builder.mode === "erase" ? import_vector2.VECTOR_OVERLAY_THEME.builderErase : accentColor, strokeWidth: 1 })
313
+ ] }),
277
314
  overlay.toolStroke && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
278
315
  "path",
279
316
  {
@@ -443,7 +480,20 @@ function VectorToolbar({ controller, tools = import_vector3.VECTOR_TOOLS, showHi
443
480
  }
444
481
  }
445
482
  )
446
- ] })
483
+ ] }),
484
+ state.tool === "paintBucket" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
485
+ "button",
486
+ {
487
+ type: "button",
488
+ "data-vector-fill-gap": "",
489
+ className: buttonClass,
490
+ "aria-pressed": editing.fillGap > 0,
491
+ title: "Close small gaps between path ends when filling",
492
+ "aria-label": "Close gaps",
493
+ onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : import_vector3.VECTOR_FILL_GAP }),
494
+ children: "Gaps"
495
+ }
496
+ )
447
497
  ] }),
448
498
  showArrange && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
449
499
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
@@ -454,6 +504,20 @@ function VectorToolbar({ controller, tools = import_vector3.VECTOR_TOOLS, showHi
454
504
  act("G", "Group", () => controller.group(), count < 1),
455
505
  act("U", "Ungroup", () => controller.ungroup(), !groupSelected)
456
506
  ] }),
507
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: import_vector3.VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
508
+ "button",
509
+ {
510
+ type: "button",
511
+ "data-vector-pathfinder": a.id,
512
+ className: buttonClass,
513
+ title: a.title,
514
+ "aria-label": a.title,
515
+ disabled: count < a.min,
516
+ onClick: () => void controller.pathfinder(a.id),
517
+ children: a.label
518
+ },
519
+ a.id
520
+ )) }),
457
521
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
458
522
  act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
459
523
  act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
@@ -484,6 +548,7 @@ function VectorStylePanel({ controller, className }) {
484
548
  arrowAlign: d.arrowAlign ?? "extend",
485
549
  startArrowScale: d.startArrowScale ?? 1,
486
550
  endArrowScale: d.endArrowScale ?? 1,
551
+ widthProfile: (0, import_vector3.widthProfilePresetId)(d.strokeWidthProfile),
487
552
  cornerRadius: d.cornerRadius,
488
553
  cornerKind: d.cornerKind ?? "round",
489
554
  corners: 1,
@@ -494,6 +559,10 @@ function VectorStylePanel({ controller, className }) {
494
559
  else if (patch.radius !== void 0) controller.setCornerRadius(patch.radius);
495
560
  else if (patch.kind) controller.setCornerKind(patch.kind);
496
561
  };
562
+ const setProfile = (id) => {
563
+ if (style) controller.setWidthProfile(id);
564
+ else controller.setDefaults({ strokeWidthProfile: (0, import_vector3.widthProfilePreset)(id)?.length ? (0, import_vector3.widthProfilePreset)(id) : null });
565
+ };
497
566
  const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
498
567
  const arrowRow = (end, label) => {
499
568
  const key = end === "start" ? "startArrow" : "endArrow";
@@ -577,6 +646,37 @@ function VectorStylePanel({ controller, className }) {
577
646
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("select", { "aria-label": "Stroke alignment", className: selectClass, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(import_vector3.VECTOR_STROKE_ALIGN_LABELS).map((a) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: a, children: import_vector3.VECTOR_STROKE_ALIGN_LABELS[a] }, a)) }),
578
647
  mixed("strokeAlign")
579
648
  ] }),
649
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
650
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-16", children: "Profile" }),
651
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
652
+ "select",
653
+ {
654
+ "aria-label": "Width profile",
655
+ className: selectClass,
656
+ value: source.widthProfile,
657
+ onChange: (e) => {
658
+ if (e.target.value !== "custom") setProfile(e.target.value);
659
+ },
660
+ children: [
661
+ import_vector3.VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: p.id, children: p.label }, p.id)),
662
+ source.widthProfile === "custom" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: "custom", disabled: true, children: "Custom" })
663
+ ]
664
+ }
665
+ ),
666
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
667
+ "button",
668
+ {
669
+ type: "button",
670
+ className: buttonClass,
671
+ title: "Reset to uniform width",
672
+ "aria-label": "Reset to uniform width",
673
+ disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
674
+ onClick: () => setProfile("uniform"),
675
+ children: "\u2550"
676
+ }
677
+ ),
678
+ mixed("widthProfile")
679
+ ] }),
580
680
  source.hasOpenPath && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
581
681
  arrowRow("start", "Start"),
582
682
  arrowRow("end", "End"),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/vector/index.ts","../../src/vector/useVectorEditor.ts","../../src/vector/VectorCanvas.tsx","../../src/vector/VectorToolbar.tsx","../../src/vector/VectorEditor.tsx"],"sourcesContent":["export * from './useVectorEditor';\nexport * from './VectorCanvas';\nexport * from './VectorToolbar';\nexport * from './VectorEditor';\n","import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n VectorEditorController,\n createVectorCommands,\n type VectorCommandOptions,\n type VectorEditorOptions,\n type VectorEditorState,\n type VectorTool,\n} from '@pixerate/editor/vector';\n\n/** A `VectorEditorController` created once for the component's lifetime (destroyed on unmount). */\nexport function useVectorEditorController(options: VectorEditorOptions = {}): VectorEditorController {\n const ref = useRef<VectorEditorController | null>(null);\n if (!ref.current) ref.current = new VectorEditorController(options);\n const controller = ref.current;\n useEffect(() => () => controller.destroy(), [controller]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change). */\nexport function useVectorEditorState(controller: VectorEditorController): VectorEditorState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseVectorEditorResult {\n controller: VectorEditorController;\n state: VectorEditorState;\n setTool: (tool: VectorTool) => void;\n undo: () => void;\n redo: () => void;\n deleteSelection: () => void;\n toSvg: () => string;\n}\n\n/**\n * Subscribes to a vector editor controller and exposes its state with bound actions. Pass\n * options instead of a controller to create one for the component's lifetime.\n */\nexport function useVectorEditor(controllerOrOptions: VectorEditorController | VectorEditorOptions = {}): UseVectorEditorResult {\n const own = useRef<VectorEditorController | null>(null);\n let controller: VectorEditorController;\n if (controllerOrOptions instanceof VectorEditorController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new VectorEditorController(controllerOrOptions);\n controller = own.current;\n }\n const state = useVectorEditorState(controller);\n const actions = useMemo(\n () => ({\n setTool: (tool: VectorTool) => controller.setTool(tool),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n deleteSelection: () => void controller.deleteSelection(),\n toSvg: () => controller.toSvg(),\n }),\n [controller],\n );\n return { controller, state, ...actions };\n}\n\n/** Anything with `register(specs) → unregister` (a `CommandRegistry`). */\nexport interface VectorCommandTarget {\n register(specs: any): () => void;\n}\n\n/**\n * Registers the controller's palette / agent commands (`vector.addShape`, `vector.boolean`, …)\n * in `registry` while mounted, so `createCommandToolProvider` exposes them to agents.\n */\nexport function useVectorCommands(\n registry: VectorCommandTarget | null | undefined,\n controller: VectorEditorController,\n options: VectorCommandOptions = {},\n): void {\n const { prefix, group, scope } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createVectorCommands(controller, { prefix, group, scope }));\n }, [registry, controller, prefix, group, scope]);\n}\n","import React, { useEffect, useId, useRef } from 'react';\nimport {\n VECTOR_OVERLAY_THEME as THEME,\n getVectorOverlayRenderData,\n getVectorSceneRenderData,\n isVectorTextTarget,\n toVectorKeyInput,\n toVectorPointerInput,\n type VectorEditorController,\n type VectorRenderNode,\n type VectorRenderPath,\n type SvgGradientDef,\n} from '@pixerate/editor/vector';\nimport { useVectorEditorState } from './useVectorEditor';\n\nexport interface VectorCanvasProps {\n controller: VectorEditorController;\n /** Fit the artboard into the canvas when it first gets a size (default `true`). */\n fitOnMount?: boolean;\n /** Draw a checkerboard behind a transparent artboard (default `true`). */\n checkerboard?: boolean;\n /** Overlay accent colour (default sky blue). */\n accentColor?: string;\n /** Smart guide colour (default magenta). */\n guideColor?: string;\n className?: string;\n style?: React.CSSProperties;\n /** Accessible label (default \"Vector canvas\"). */\n 'aria-label'?: string;\n}\n\n/** Renders `<linearGradient>` / `<radialGradient>` descriptors. */\nexport function VectorGradientDefs({ defs }: { defs: readonly SvgGradientDef[] }) {\n if (!defs.length) return null;\n return (\n <defs>\n {defs.map((def) => {\n const stops = def.stops.map((s, i) => <stop key={i} offset={s.offset} stopColor={s.stopColor} stopOpacity={s.stopOpacity} />);\n return def.type === 'radial' ? (\n <radialGradient key={def.id} id={def.id} {...(def.attrs as any)}>\n {stops}\n </radialGradient>\n ) : (\n <linearGradient key={def.id} id={def.id} {...(def.attrs as any)}>\n {stops}\n </linearGradient>\n );\n })}\n </defs>\n );\n}\n\n/** Renders scene nodes (paths and groups) from `getVectorSceneRenderData`. */\nexport function VectorSceneNodes({ nodes }: { nodes: readonly VectorRenderNode[] }) {\n return (\n <>\n {nodes.map((node) =>\n node.kind === 'group' ? (\n <g key={node.id} data-vector-id={node.id} transform={node.transform} opacity={node.opacity < 1 ? node.opacity : undefined}>\n <VectorSceneNodes nodes={node.children} />\n </g>\n ) : node.strokeParts ? (\n <VectorPartedPath key={node.id} node={node} />\n ) : (\n <path\n key={node.id}\n data-vector-id={node.id}\n transform={node.transform}\n d={node.d}\n fill={node.fill}\n fillRule={node.fillRule}\n stroke={node.stroke}\n strokeWidth={node.stroke === 'none' ? undefined : node.strokeWidth}\n strokeLinecap={node.strokeLinecap as any}\n strokeLinejoin={node.strokeLinejoin as any}\n strokeDasharray={node.strokeDasharray}\n opacity={node.opacity < 1 ? node.opacity : undefined}\n />\n ),\n )}\n </>\n );\n}\n\n/** A path whose stroke is aligned inside / outside (double width, clipped or masked by the shape) or has arrowheads. */\nfunction VectorPartedPath({ node }: { node: VectorRenderPath }) {\n const sp = node.strokeParts!;\n const clip = sp.clip;\n const b = clip?.bounds;\n return (\n <g data-vector-id={node.id} data-vector-stroke-align={sp.align} transform={node.transform} opacity={node.opacity < 1 ? node.opacity : undefined}>\n {clip && b && (\n <defs>\n {clip.kind === 'clip' ? (\n <clipPath id={clip.id}>\n <path d={node.d} clipRule={node.fillRule} />\n </clipPath>\n ) : (\n <mask id={clip.id} maskUnits=\"userSpaceOnUse\" x={b.x} y={b.y} width={b.width} height={b.height}>\n <rect x={b.x} y={b.y} width={b.width} height={b.height} fill=\"#fff\" />\n <path d={node.d} fill=\"#000\" fillRule={node.fillRule} />\n </mask>\n )}\n </defs>\n )}\n <path data-vector-part=\"fill\" d={node.d} fill={node.fill} fillRule={node.fillRule} stroke=\"none\" />\n <path\n data-vector-part=\"stroke\"\n d={sp.d}\n fill=\"none\"\n stroke={node.stroke}\n strokeWidth={sp.width}\n strokeLinecap={node.strokeLinecap as any}\n strokeLinejoin={node.strokeLinejoin as any}\n strokeDasharray={node.strokeDasharray}\n clipPath={clip?.kind === 'clip' ? `url(#${clip.id})` : undefined}\n mask={clip?.kind === 'mask' ? `url(#${clip.id})` : undefined}\n />\n {sp.heads.map((head, i) => (\n <path key={i} data-vector-part=\"head\" d={head} fill={node.stroke} />\n ))}\n </g>\n );\n}\n\n/**\n * An SVG canvas for a `VectorEditorController`: draws the document and the editing overlay\n * and forwards pointer, wheel, keyboard and clipboard events. Focus it to use shortcuts.\n */\nexport function VectorCanvas({\n controller,\n fitOnMount = true,\n checkerboard = true,\n accentColor = THEME.accent,\n guideColor = THEME.guide,\n className,\n style,\n 'aria-label': ariaLabel = 'Vector canvas',\n}: VectorCanvasProps) {\n const state = useVectorEditorState(controller);\n const svgRef = useRef<SVGSVGElement | null>(null);\n const fitted = useRef(!fitOnMount);\n const uid = useId().replace(/:/g, '');\n const scene = getVectorSceneRenderData(state, { idPrefix: `ve${uid}-` });\n const overlay = getVectorOverlayRenderData(state);\n\n useEffect(() => {\n const el = svgRef.current;\n if (!el || fitted.current) return;\n const fit = () => {\n const rect = el.getBoundingClientRect();\n if (fitted.current || rect.width <= 0 || rect.height <= 0) return;\n fitted.current = true;\n controller.zoomToFit({ width: rect.width, height: rect.height });\n };\n fit();\n if (fitted.current || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(fit);\n observer.observe(el);\n return () => observer.disconnect();\n }, [controller]);\n\n // Wheel needs a non-passive listener to stop page scroll / browser zoom.\n useEffect(() => {\n const el = svgRef.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n controller.wheel(local(e), { x: e.deltaX, y: e.deltaY }, toVectorPointerInput(e));\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [controller]);\n\n const local = (e: { clientX: number; clientY: number }) => {\n const rect = svgRef.current?.getBoundingClientRect();\n return { x: e.clientX - (rect?.left ?? 0), y: e.clientY - (rect?.top ?? 0) };\n };\n\n const clipboard = (kind: 'copy' | 'cut' | 'paste') => (event: React.ClipboardEvent) => {\n const native = (event && 'nativeEvent' in event ? event.nativeEvent : event) as ClipboardEvent;\n const data = native?.clipboardData;\n if (kind === 'paste') {\n const text = data?.getData('text/plain') ?? '';\n const pasted = text ? controller.paste(text) : controller.paste();\n if (pasted.length) event.preventDefault?.();\n return;\n }\n const text = kind === 'cut' ? controller.cut() : controller.copy();\n if (text && data) {\n data.setData('text/plain', text);\n event.preventDefault?.();\n }\n };\n\n const hs = THEME.transformHandleSize;\n const as = THEME.anchorSize;\n const box = overlay.selectionBox;\n\n return (\n <svg\n ref={svgRef}\n role=\"application\"\n aria-label={ariaLabel}\n tabIndex={0}\n data-tool={state.tool}\n className={className}\n style={{ display: 'block', width: '100%', height: '100%', outline: 'none', touchAction: 'none', userSelect: 'none', cursor: state.cursor, ...style }}\n onPointerDown={(e) => {\n svgRef.current?.focus({ preventScroll: true });\n (e.currentTarget as Element).setPointerCapture?.(e.pointerId);\n controller.pointerDown(local(e), toVectorPointerInput(e));\n }}\n onPointerMove={(e) => controller.pointerMove(local(e), toVectorPointerInput(e))}\n onPointerUp={(e) => {\n (e.currentTarget as Element).releasePointerCapture?.(e.pointerId);\n controller.pointerUp(local(e), toVectorPointerInput(e));\n }}\n onPointerCancel={() => controller.cancelDrag()}\n onPointerLeave={() => controller.pointerLeave()}\n onDoubleClick={(e) => controller.doubleClick(local(e))}\n onKeyDown={(e) => {\n if (isVectorTextTarget(e.target)) return;\n if (controller.keyDown(toVectorKeyInput(e))) e.preventDefault();\n }}\n onKeyUp={(e) => controller.keyUp(toVectorKeyInput(e))}\n onCopy={clipboard('copy')}\n onCut={clipboard('cut')}\n onPaste={clipboard('paste')}\n >\n {checkerboard && (\n <defs>\n <pattern id={`ve${uid}-checker`} width={16} height={16} patternUnits=\"userSpaceOnUse\">\n <rect width={16} height={16} fill=\"#ffffff\" />\n <rect width={8} height={8} fill=\"#e5e7eb\" />\n <rect x={8} y={8} width={8} height={8} fill=\"#e5e7eb\" />\n </pattern>\n </defs>\n )}\n <VectorGradientDefs defs={scene.defs} />\n <rect\n data-vector-artboard=\"\"\n x={overlay.artboard.x}\n y={overlay.artboard.y}\n width={overlay.artboard.width}\n height={overlay.artboard.height}\n fill={scene.background ?? (checkerboard ? `url(#ve${uid}-checker)` : '#ffffff')}\n stroke=\"rgba(0,0,0,0.12)\"\n />\n <g data-vector-scene=\"\" transform={scene.transform}>\n <VectorSceneNodes nodes={scene.nodes} />\n </g>\n <g data-vector-overlay=\"\" pointerEvents=\"none\" fill=\"none\">\n {overlay.outlines.map((o) => (\n <path key={o.id} d={o.d} stroke={accentColor} strokeWidth={o.selected ? 1 : 1.5} opacity={o.selected ? 1 : 0.7} />\n ))}\n {overlay.penPreview && <path d={overlay.penPreview} stroke={accentColor} strokeDasharray=\"4 3\" />}\n {box && (\n <g data-vector-selection=\"\" transform={box.transform || undefined}>\n <rect x={box.x} y={box.y} width={box.width} height={box.height} stroke={accentColor} />\n <line x1={box.x + box.width / 2} y1={box.y} x2={box.x + box.width / 2} y2={box.y - 24} stroke={accentColor} />\n {box.handles.map((h) =>\n h.handle === 'rotate' ? (\n <circle key={h.handle} data-handle={h.handle} cx={h.x} cy={h.y} r={hs / 2 + 1} fill={THEME.handleFill} stroke={accentColor} />\n ) : (\n <rect key={h.handle} data-handle={h.handle} x={h.x - hs / 2} y={h.y - hs / 2} width={hs} height={hs} fill={THEME.handleFill} stroke={accentColor} />\n ),\n )}\n </g>\n )}\n {overlay.handles.map((h) => (\n <g key={`${h.ref.nodeId}:${h.ref.subpath}:${h.ref.index}:${h.ref.handle}`} data-vector-handle={h.ref.handle}>\n <line x1={h.anchorX} y1={h.anchorY} x2={h.x} y2={h.y} stroke={accentColor} />\n <circle cx={h.x} cy={h.y} r={THEME.handleRadius + (h.hovered ? 1 : 0)} fill={THEME.handleFill} stroke={accentColor} />\n </g>\n ))}\n {overlay.anchors.map((a) => {\n const size = as + (a.hovered ? 2 : 0);\n const fill = a.selected ? accentColor : THEME.handleFill;\n const key = `${a.ref.nodeId}:${a.ref.subpath}:${a.ref.index}`;\n return a.type === 'corner' ? (\n <rect key={key} data-vector-anchor={a.ref.index} x={a.x - size / 2} y={a.y - size / 2} width={size} height={size} fill={fill} stroke={accentColor} />\n ) : (\n <circle key={key} data-vector-anchor={a.ref.index} cx={a.x} cy={a.y} r={size / 2} fill={fill} stroke={accentColor} />\n );\n })}\n {overlay.cornerWidgets.map((w) => (\n <g key={`corner:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`} data-vector-corner-widget={w.ref.index} data-corner-kind={w.kind}>\n <circle cx={w.x} cy={w.y} r={THEME.cornerWidgetRadius + (w.hovered ? 1 : 0)} fill={THEME.handleFill} stroke={accentColor} />\n <circle cx={w.x} cy={w.y} r={1.5} fill={accentColor} />\n </g>\n ))}\n {state.tool === 'pen' && overlay.anchors.some((a) => a.closes && a.hovered) && (\n <circle cx={overlay.anchors.find((a) => a.closes)!.x} cy={overlay.anchors.find((a) => a.closes)!.y} r={as} stroke={accentColor} />\n )}\n {overlay.toolStroke && (\n <path\n data-vector-tool-stroke={overlay.toolStroke.tool}\n d={overlay.toolStroke.d}\n stroke={overlay.toolStroke.tool === 'eraser' ? THEME.eraserFill : accentColor}\n strokeWidth={overlay.toolStroke.tool === 'eraser' ? overlay.toolStroke.width : 1}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeDasharray={overlay.toolStroke.tool === 'knife' ? '5 3' : undefined}\n />\n )}\n {overlay.pencilString && (\n <line\n data-vector-pencil-string=\"\"\n x1={overlay.pencilString.x1}\n y1={overlay.pencilString.y1}\n x2={overlay.pencilString.x2}\n y2={overlay.pencilString.y2}\n stroke={accentColor}\n strokeDasharray=\"2 2\"\n />\n )}\n {overlay.cutPoint && <circle data-vector-cut-point=\"\" cx={overlay.cutPoint.x} cy={overlay.cutPoint.y} r={THEME.handleRadius + 1} fill={THEME.handleFill} stroke={accentColor} />}\n {overlay.marquee && (\n <rect\n data-vector-marquee=\"\"\n x={overlay.marquee.x}\n y={overlay.marquee.y}\n width={overlay.marquee.width}\n height={overlay.marquee.height}\n fill={THEME.marqueeFill}\n stroke={accentColor}\n strokeDasharray=\"3 2\"\n />\n )}\n {overlay.guides.lines.length > 0 && (\n <g data-vector-guides=\"\" stroke={guideColor}>\n {overlay.guides.lines.map((l, i) => (\n <line key={i} data-vector-guide={l.kind} x1={l.x1} y1={l.y1} x2={l.x2} y2={l.y2} strokeDasharray={l.kind === 'construction' ? '4 3' : undefined} />\n ))}\n </g>\n )}\n {overlay.guides.labels.map((l, i) => (\n <text\n key={i}\n data-vector-guide-label={l.kind}\n x={l.x + 6}\n y={l.y - 6}\n fontSize={10}\n fill={guideColor}\n stroke=\"#ffffff\"\n strokeWidth={3}\n paintOrder=\"stroke\"\n style={{ fontFamily: 'system-ui, sans-serif' }}\n >\n {l.text}\n </text>\n ))}\n {overlay.status && (\n <text data-vector-status=\"\" x={8} y=\"100%\" dy={-8} fontSize={11} fill={accentColor} style={{ fontFamily: 'system-ui, sans-serif' }}>\n {overlay.status}\n </text>\n )}\n </g>\n </svg>\n );\n}\n","import React from 'react';\nimport {\n VECTOR_TOOLS,\n VECTOR_TOOL_GLYPHS,\n VECTOR_TOOL_SHORTCUTS,\n VECTOR_EDIT_TOGGLES,\n VECTOR_PATH_ACTIONS,\n VECTOR_ARROWHEADS,\n VECTOR_ARROWHEAD_LABELS,\n VECTOR_CORNER_KINDS,\n VECTOR_CORNER_KIND_LABELS,\n VECTOR_STROKE_ALIGN_LABELS,\n getVectorSelectionStyle,\n vectorPaintToHex,\n vectorToolLabel,\n type VectorArrowhead,\n type VectorCornerKind,\n type VectorEditorController,\n type VectorStrokeAlign,\n type VectorTool,\n} from '@pixerate/editor/vector';\nimport { useVectorEditorState } from './useVectorEditor';\n\nconst VECTOR_SNAP_TITLE = 'Snap to objects';\nconst modKeyLabel = () => (typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform ?? '') ? '⌘' : 'Ctrl');\n\nconst buttonClass =\n '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';\n\nexport interface VectorToolbarProps {\n controller: VectorEditorController;\n /** Tools to show (default: all). */\n tools?: readonly VectorTool[];\n /** Undo / redo buttons (default `true`). */\n showHistory?: boolean;\n /** Boolean, group, arrange and align buttons (default `true`). */\n showArrange?: boolean;\n /** The snapping toggle (default `true`). */\n showSnap?: boolean;\n /**\n * Path editing: Join, Average, Cut at Points, Remove Redundant Points, Smooth, the Keep\n * Shape / Curvature / Shapes toggles, and the pencil smoothing and eraser size inputs while\n * those tools are active (default `true`).\n */\n showPathEdit?: boolean;\n className?: string;\n}\n\n/** Tool picker plus undo, snapping, boolean operations, grouping, stacking and alignment. */\nexport function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, showArrange = true, showSnap = true, showPathEdit = true, className }: VectorToolbarProps) {\n const state = useVectorEditorState(controller);\n const count = state.selection.length;\n const points = state.tool === 'direct' ? state.selectedAnchors.length : 0;\n const editing = state.editing;\n const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === 'group');\n const act = (label: string, title: string, run: () => unknown, disabled = false) => (\n <button key={label} type=\"button\" className={buttonClass} title={title} aria-label={title} disabled={disabled} onClick={() => void run()}>\n {label}\n </button>\n );\n return (\n <div role=\"toolbar\" aria-label=\"Vector tools\" className={`flex flex-wrap items-center gap-1 ${className ?? ''}`}>\n <div className=\"flex items-center gap-1\" role=\"group\" aria-label=\"Tools\">\n {tools.map((tool) => (\n <button\n key={tool}\n type=\"button\"\n data-vector-tool={tool}\n className={buttonClass}\n aria-pressed={state.tool === tool}\n title={`${vectorToolLabel(tool)} (${VECTOR_TOOL_SHORTCUTS[tool]})`}\n aria-label={vectorToolLabel(tool)}\n onClick={() => controller.setTool(tool)}\n >\n {VECTOR_TOOL_GLYPHS[tool]}\n </button>\n ))}\n </div>\n {showHistory && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"History\">\n {act('↶', state.canUndo ? `Undo ${state.undoLabel}` : 'Undo', () => controller.undo(), !state.canUndo)}\n {act('↷', state.canRedo ? `Redo ${state.redoLabel}` : 'Redo', () => controller.redo(), !state.canRedo)}\n </div>\n )}\n {showSnap && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Snapping\">\n <button\n type=\"button\"\n data-vector-snap=\"\"\n className={buttonClass}\n aria-pressed={state.snap.objects}\n title={`${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`}\n aria-label={VECTOR_SNAP_TITLE}\n onClick={() => controller.toggleSnapping()}\n >\n Snap\n </button>\n </div>\n )}\n {showPathEdit && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Path editing\">\n {VECTOR_PATH_ACTIONS.map((a) => (\n <button\n key={a.id}\n type=\"button\"\n data-vector-path-action={a.id}\n className={buttonClass}\n title={a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title}\n aria-label={a.title}\n disabled={!a.enabled(count, points)}\n onClick={() => void a.run(controller)}\n >\n {a.label}\n </button>\n ))}\n {VECTOR_EDIT_TOGGLES.map((t) => (\n <button\n key={t.key}\n type=\"button\"\n data-vector-edit={t.key}\n className={buttonClass}\n aria-pressed={editing[t.key]}\n title={t.title}\n aria-label={t.title}\n onClick={() => controller.setEditing({ [t.key]: !editing[t.key] })}\n >\n {t.label}\n </button>\n ))}\n {state.tool === 'pencil' && (\n <label className=\"flex items-center gap-1 text-xs text-foreground\">\n Smoothing\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.05}\n aria-label=\"Pencil smoothing\"\n className=\"h-4 w-20 accent-primary\"\n value={editing.pencilSmoothing}\n onChange={(e) => controller.setEditing({ pencilSmoothing: parseFloat(e.target.value) })}\n />\n </label>\n )}\n {state.tool === 'eraser' && (\n <label className=\"flex items-center gap-1 text-xs text-foreground\">\n Size\n <input\n type=\"number\"\n min={0.5}\n step={1}\n aria-label=\"Eraser size\"\n className=\"h-7 w-16 rounded border border-border bg-background px-1.5 text-xs\"\n value={editing.eraserSize}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n > 0) controller.setEditing({ eraserSize: n });\n }}\n />\n </label>\n )}\n </div>\n )}\n {showArrange && (\n <>\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Combine\">\n {act('∪', 'Union', () => controller.booleanOp('union'), count < 2)}\n {act('−', 'Subtract', () => controller.booleanOp('subtract'), count < 2)}\n {act('∩', 'Intersect', () => controller.booleanOp('intersect'), count < 2)}\n {act('⊻', 'Exclude', () => controller.booleanOp('exclude'), count < 2)}\n {act('G', 'Group', () => controller.group(), count < 1)}\n {act('U', 'Ungroup', () => controller.ungroup(), !groupSelected)}\n </div>\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Arrange\">\n {act('⇈', 'Bring to Front', () => controller.arrange('front'), count < 1)}\n {act('⇊', 'Send to Back', () => controller.arrange('back'), count < 1)}\n {act('⇤', 'Align Left', () => controller.align('left'), count < 1)}\n {act('↔', 'Align Center', () => controller.align('center'), count < 1)}\n {act('⇥', 'Align Right', () => controller.align('right'), count < 1)}\n {act('⤒', 'Align Top', () => controller.align('top'), count < 1)}\n {act('↕', 'Align Middle', () => controller.align('middle'), count < 1)}\n {act('⤓', 'Align Bottom', () => controller.align('bottom'), count < 1)}\n </div>\n </>\n )}\n </div>\n );\n}\n\nexport interface VectorStylePanelProps {\n controller: VectorEditorController;\n className?: string;\n}\n\nconst selectClass = 'h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs';\nconst numberClass = 'h-7 w-16 rounded border border-border bg-background px-1.5 text-xs';\n\n/**\n * Fill, stroke, stroke width and alignment, arrowheads, live corner radius and opacity of the\n * selection (corners of the selected points with the direct tool); with nothing selected it\n * edits the defaults for new shapes.\n */\nexport function VectorStylePanel({ controller, className }: VectorStylePanelProps) {\n const state = useVectorEditorState(controller);\n const style = getVectorSelectionStyle(state);\n const d = state.defaults;\n const source = style ?? {\n fill: d.fill ?? null,\n stroke: d.stroke ?? null,\n strokeWidth: d.strokeWidth ?? 1,\n opacity: 1,\n strokeAlign: d.strokeAlign ?? 'center',\n startArrow: d.startArrow ?? null,\n endArrow: d.endArrow ?? null,\n arrowAlign: d.arrowAlign ?? 'extend',\n startArrowScale: d.startArrowScale ?? 1,\n endArrowScale: d.endArrowScale ?? 1,\n cornerRadius: d.cornerRadius,\n cornerKind: d.cornerKind ?? 'round',\n corners: 1,\n hasOpenPath: true,\n };\n const setCorners = (patch: { radius?: number; kind?: VectorCornerKind }) => {\n if (!style) controller.setDefaults({ ...(patch.radius !== undefined ? { cornerRadius: patch.radius } : {}), ...(patch.kind ? { cornerKind: patch.kind } : {}) });\n else if (patch.radius !== undefined) controller.setCornerRadius(patch.radius);\n else if (patch.kind) controller.setCornerKind(patch.kind);\n };\n const mixed = (key: keyof NonNullable<typeof style>['mixed']) => (style?.mixed[key] ? <span className=\"text-[11px] text-muted-foreground\">Mixed</span> : null);\n const arrowRow = (end: 'start' | 'end', label: string) => {\n const key = end === 'start' ? 'startArrow' : 'endArrow';\n const scaleKey = end === 'start' ? 'startArrowScale' : 'endArrowScale';\n return (\n <div className=\"flex items-center gap-2\" data-vector-style={key}>\n <span className=\"w-16 text-xs text-foreground\">{label}</span>\n <select aria-label={`${label} arrowhead`} className={selectClass} value={source[key] ?? ''} onChange={(e) => apply({ [key]: (e.target.value || null) as VectorArrowhead | null })}>\n <option value=\"\">None</option>\n {VECTOR_ARROWHEADS.map((h) => (\n <option key={h} value={h}>\n {VECTOR_ARROWHEAD_LABELS[h]}\n </option>\n ))}\n </select>\n <input\n type=\"number\"\n min={0.1}\n step={0.25}\n aria-label={`${label} arrowhead scale`}\n title=\"Scale (× stroke width)\"\n className={numberClass}\n value={source[scaleKey]}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n > 0) apply({ [scaleKey]: n });\n }}\n />\n </div>\n );\n };\n const apply = (patch: Record<string, unknown>) => {\n if (style) controller.setStyle(patch);\n else controller.setDefaults(patch);\n };\n const paintRow = (key: 'fill' | 'stroke', label: string) => {\n const paint = source[key];\n const hex = vectorPaintToHex(paint);\n const on = paint !== null && paint !== 'none';\n return (\n <div className=\"flex items-center gap-2\" data-vector-style={key}>\n <label className=\"flex w-16 items-center gap-1.5 text-xs text-foreground\">\n <input type=\"checkbox\" checked={on} aria-label={`${label} on`} onChange={(e) => apply({ [key]: e.target.checked ? (hex ?? '#000000') : null })} />\n {label}\n </label>\n <input\n type=\"color\"\n aria-label={`${label} colour`}\n className=\"h-7 w-10 cursor-pointer rounded border border-border bg-background disabled:opacity-40\"\n disabled={!on}\n value={hex ?? '#000000'}\n onChange={(e) => apply({ [key]: e.target.value })}\n />\n {on && !hex && <span className=\"truncate text-[11px] text-muted-foreground\">{typeof paint === 'string' ? paint : 'Gradient'}</span>}\n {style?.mixed[key] && <span className=\"text-[11px] text-muted-foreground\">Mixed</span>}\n </div>\n );\n };\n return (\n <div className={`space-y-2 ${className ?? ''}`} aria-label={style ? 'Selection style' : 'New shape style'}>\n <p className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">{style ? 'Selection' : 'New shapes'}</p>\n {paintRow('fill', 'Fill')}\n {paintRow('stroke', 'Stroke')}\n <label className=\"flex items-center gap-2 text-xs text-foreground\">\n <span className=\"w-16\">Width</span>\n <input\n type=\"number\"\n min={0}\n step={0.5}\n aria-label=\"Stroke width\"\n className=\"h-7 w-20 rounded border border-border bg-background px-1.5 text-xs\"\n value={source.strokeWidth}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n >= 0) apply({ strokeWidth: n });\n }}\n />\n </label>\n <label className=\"flex items-center gap-2 text-xs text-foreground\" data-vector-style=\"strokeAlign\">\n <span className=\"w-16\">Align</span>\n <select aria-label=\"Stroke alignment\" className={selectClass} value={source.strokeAlign} onChange={(e) => apply({ strokeAlign: e.target.value as VectorStrokeAlign })}>\n {(Object.keys(VECTOR_STROKE_ALIGN_LABELS) as VectorStrokeAlign[]).map((a) => (\n <option key={a} value={a}>\n {VECTOR_STROKE_ALIGN_LABELS[a]}\n </option>\n ))}\n </select>\n {mixed('strokeAlign')}\n </label>\n {source.hasOpenPath && (\n <>\n {arrowRow('start', 'Start')}\n {arrowRow('end', 'End')}\n {(source.startArrow || source.endArrow) && (\n <label className=\"flex items-center gap-2 text-xs text-foreground\" data-vector-style=\"arrowAlign\">\n <span className=\"w-16\">Heads</span>\n <select aria-label=\"Arrowhead alignment\" className={selectClass} value={source.arrowAlign} onChange={(e) => apply({ arrowAlign: e.target.value })}>\n <option value=\"extend\">Tip past end</option>\n <option value=\"tip\">Tip at end</option>\n </select>\n </label>\n )}\n </>\n )}\n {source.corners > 0 && (\n <div className=\"flex items-center gap-2\" data-vector-style=\"corners\">\n <span className=\"w-16 text-xs text-foreground\">Corners</span>\n <input\n type=\"number\"\n min={0}\n step={1}\n aria-label=\"Corner radius\"\n className={numberClass}\n value={Math.round(source.cornerRadius * 100) / 100}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n >= 0) setCorners({ radius: n });\n }}\n />\n <select aria-label=\"Corner kind\" className={selectClass} value={source.cornerKind} onChange={(e) => setCorners({ kind: e.target.value as VectorCornerKind })}>\n {VECTOR_CORNER_KINDS.map((k) => (\n <option key={k} value={k}>\n {VECTOR_CORNER_KIND_LABELS[k]}\n </option>\n ))}\n </select>\n {mixed('cornerRadius')}\n </div>\n )}\n {style && (\n <label className=\"flex items-center gap-2 text-xs text-foreground\">\n <span className=\"w-16\">Opacity</span>\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.05}\n aria-label=\"Opacity\"\n className=\"h-4 flex-1 accent-primary\"\n value={source.opacity}\n onChange={(e) => apply({ opacity: parseFloat(e.target.value) })}\n />\n </label>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport type { VectorEditorController, VectorTool } from '@pixerate/editor/vector';\nimport { VectorCanvas, type VectorCanvasProps } from './VectorCanvas';\nimport { VectorStylePanel, VectorToolbar } from './VectorToolbar';\n\nexport interface VectorEditorProps {\n controller: VectorEditorController;\n /** Tools in the toolbar (default: all). */\n tools?: readonly VectorTool[];\n /** The style sidebar (default `true`). */\n showStylePanel?: boolean;\n /** Canvas height (default 520px). */\n height?: number | string;\n canvasProps?: Omit<VectorCanvasProps, 'controller'>;\n className?: string;\n}\n\n/** Toolbar, canvas and style panel for a `VectorEditorController`. */\nexport function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }: VectorEditorProps) {\n return (\n <div className={`flex flex-col gap-2 ${className ?? ''}`} data-vector-editor=\"\">\n <VectorToolbar controller={controller} tools={tools} />\n <div className=\"flex min-h-0 flex-col gap-2 md:flex-row\">\n <div className=\"relative min-h-[320px] flex-1 overflow-hidden rounded-md border border-border bg-muted/40\" style={{ height }}>\n <VectorCanvas controller={controller} {...canvasProps} />\n </div>\n {showStylePanel && <VectorStylePanel controller={controller} className=\"w-full shrink-0 rounded-md border border-border p-3 md:w-56\" />}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,mBAAiE;AACjE,oBAOO;AAGA,SAAS,0BAA0B,UAA+B,CAAC,GAA2B;AACnG,QAAM,UAAM,qBAAsC,IAAI;AACtD,MAAI,CAAC,IAAI,QAAS,KAAI,UAAU,IAAI,qCAAuB,OAAO;AAClE,QAAM,aAAa,IAAI;AACvB,8BAAU,MAAM,MAAM,WAAW,QAAQ,GAAG,CAAC,UAAU,CAAC;AACxD,SAAO;AACT;AAGO,SAAS,qBAAqB,YAAuD;AAC1F,aAAO,mCAAqB,WAAW,WAAW,WAAW,UAAU,WAAW,QAAQ;AAC5F;AAgBO,SAAS,gBAAgB,sBAAoE,CAAC,GAA0B;AAC7H,QAAM,UAAM,qBAAsC,IAAI;AACtD,MAAI;AACJ,MAAI,+BAA+B,qCAAwB,cAAa;AAAA,OACnE;AACH,QAAI,CAAC,IAAI,QAAS,KAAI,UAAU,IAAI,qCAAuB,mBAAmB;AAC9E,iBAAa,IAAI;AAAA,EACnB;AACA,QAAM,QAAQ,qBAAqB,UAAU;AAC7C,QAAM,cAAU;AAAA,IACd,OAAO;AAAA,MACL,SAAS,CAAC,SAAqB,WAAW,QAAQ,IAAI;AAAA,MACtD,MAAM,MAAM,KAAK,WAAW,KAAK;AAAA,MACjC,MAAM,MAAM,KAAK,WAAW,KAAK;AAAA,MACjC,iBAAiB,MAAM,KAAK,WAAW,gBAAgB;AAAA,MACvD,OAAO,MAAM,WAAW,MAAM;AAAA,IAChC;AAAA,IACA,CAAC,UAAU;AAAA,EACb;AACA,SAAO,EAAE,YAAY,OAAO,GAAG,QAAQ;AACzC;AAWO,SAAS,kBACd,UACA,YACA,UAAgC,CAAC,GAC3B;AACN,QAAM,EAAE,QAAQ,OAAO,MAAM,IAAI;AACjC,8BAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,WAAO,SAAS,aAAS,oCAAqB,YAAY,EAAE,QAAQ,OAAO,MAAM,CAAC,CAAC;AAAA,EACrF,GAAG,CAAC,UAAU,YAAY,QAAQ,OAAO,KAAK,CAAC;AACjD;;;AC/EA,IAAAA,gBAAgD;AAChD,IAAAC,iBAWO;AAyBuC;AALvC,SAAS,mBAAmB,EAAE,KAAK,GAAwC;AAChF,MAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,SACE,4CAAC,UACE,eAAK,IAAI,CAAC,QAAQ;AACjB,UAAM,QAAQ,IAAI,MAAM,IAAI,CAAC,GAAG,MAAM,4CAAC,UAAa,QAAQ,EAAE,QAAQ,WAAW,EAAE,WAAW,aAAa,EAAE,eAA5D,CAAyE,CAAE;AAC5H,WAAO,IAAI,SAAS,WAClB,4CAAC,oBAA4B,IAAI,IAAI,IAAK,GAAI,IAAI,OAC/C,mBADkB,IAAI,EAEzB,IAEA,4CAAC,oBAA4B,IAAI,IAAI,IAAK,GAAI,IAAI,OAC/C,mBADkB,IAAI,EAEzB;AAAA,EAEJ,CAAC,GACH;AAEJ;AAGO,SAAS,iBAAiB,EAAE,MAAM,GAA2C;AAClF,SACE,2EACG,gBAAM;AAAA,IAAI,CAAC,SACV,KAAK,SAAS,UACZ,4CAAC,OAAgB,kBAAgB,KAAK,IAAI,WAAW,KAAK,WAAW,SAAS,KAAK,UAAU,IAAI,KAAK,UAAU,QAC9G,sDAAC,oBAAiB,OAAO,KAAK,UAAU,KADlC,KAAK,EAEb,IACE,KAAK,cACP,4CAAC,oBAA+B,QAAT,KAAK,EAAgB,IAE5C;AAAA,MAAC;AAAA;AAAA,QAEC,kBAAgB,KAAK;AAAA,QACrB,WAAW,KAAK;AAAA,QAChB,GAAG,KAAK;AAAA,QACR,MAAM,KAAK;AAAA,QACX,UAAU,KAAK;AAAA,QACf,QAAQ,KAAK;AAAA,QACb,aAAa,KAAK,WAAW,SAAS,SAAY,KAAK;AAAA,QACvD,eAAe,KAAK;AAAA,QACpB,gBAAgB,KAAK;AAAA,QACrB,iBAAiB,KAAK;AAAA,QACtB,SAAS,KAAK,UAAU,IAAI,KAAK,UAAU;AAAA;AAAA,MAXtC,KAAK;AAAA,IAYZ;AAAA,EAEJ,GACF;AAEJ;AAGA,SAAS,iBAAiB,EAAE,KAAK,GAA+B;AAC9D,QAAM,KAAK,KAAK;AAChB,QAAM,OAAO,GAAG;AAChB,QAAM,IAAI,MAAM;AAChB,SACE,6CAAC,OAAE,kBAAgB,KAAK,IAAI,4BAA0B,GAAG,OAAO,WAAW,KAAK,WAAW,SAAS,KAAK,UAAU,IAAI,KAAK,UAAU,QACnI;AAAA,YAAQ,KACP,4CAAC,UACE,eAAK,SAAS,SACb,4CAAC,cAAS,IAAI,KAAK,IACjB,sDAAC,UAAK,GAAG,KAAK,GAAG,UAAU,KAAK,UAAU,GAC5C,IAEA,6CAAC,UAAK,IAAI,KAAK,IAAI,WAAU,kBAAiB,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,OAAO,EAAE,OAAO,QAAQ,EAAE,QACtF;AAAA,kDAAC,UAAK,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,OAAO,EAAE,OAAO,QAAQ,EAAE,QAAQ,MAAK,QAAO;AAAA,MACpE,4CAAC,UAAK,GAAG,KAAK,GAAG,MAAK,QAAO,UAAU,KAAK,UAAU;AAAA,OACxD,GAEJ;AAAA,IAEF,4CAAC,UAAK,oBAAiB,QAAO,GAAG,KAAK,GAAG,MAAM,KAAK,MAAM,UAAU,KAAK,UAAU,QAAO,QAAO;AAAA,IACjG;AAAA,MAAC;AAAA;AAAA,QACC,oBAAiB;AAAA,QACjB,GAAG,GAAG;AAAA,QACN,MAAK;AAAA,QACL,QAAQ,KAAK;AAAA,QACb,aAAa,GAAG;AAAA,QAChB,eAAe,KAAK;AAAA,QACpB,gBAAgB,KAAK;AAAA,QACrB,iBAAiB,KAAK;AAAA,QACtB,UAAU,MAAM,SAAS,SAAS,QAAQ,KAAK,EAAE,MAAM;AAAA,QACvD,MAAM,MAAM,SAAS,SAAS,QAAQ,KAAK,EAAE,MAAM;AAAA;AAAA,IACrD;AAAA,IACC,GAAG,MAAM,IAAI,CAAC,MAAM,MACnB,4CAAC,UAAa,oBAAiB,QAAO,GAAG,MAAM,MAAM,KAAK,UAA/C,CAAuD,CACnE;AAAA,KACH;AAEJ;AAMO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA,aAAa;AAAA,EACb,eAAe;AAAA,EACf,cAAc,eAAAC,qBAAM;AAAA,EACpB,aAAa,eAAAA,qBAAM;AAAA,EACnB;AAAA,EACA;AAAA,EACA,cAAc,YAAY;AAC5B,GAAsB;AACpB,QAAM,QAAQ,qBAAqB,UAAU;AAC7C,QAAM,aAAS,sBAA6B,IAAI;AAChD,QAAM,aAAS,sBAAO,CAAC,UAAU;AACjC,QAAM,UAAM,qBAAM,EAAE,QAAQ,MAAM,EAAE;AACpC,QAAM,YAAQ,yCAAyB,OAAO,EAAE,UAAU,KAAK,GAAG,IAAI,CAAC;AACvE,QAAM,cAAU,2CAA2B,KAAK;AAEhD,+BAAU,MAAM;AACd,UAAM,KAAK,OAAO;AAClB,QAAI,CAAC,MAAM,OAAO,QAAS;AAC3B,UAAM,MAAM,MAAM;AAChB,YAAM,OAAO,GAAG,sBAAsB;AACtC,UAAI,OAAO,WAAW,KAAK,SAAS,KAAK,KAAK,UAAU,EAAG;AAC3D,aAAO,UAAU;AACjB,iBAAW,UAAU,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,CAAC;AAAA,IACjE;AACA,QAAI;AACJ,QAAI,OAAO,WAAW,OAAO,mBAAmB,YAAa;AAC7D,UAAM,WAAW,IAAI,eAAe,GAAG;AACvC,aAAS,QAAQ,EAAE;AACnB,WAAO,MAAM,SAAS,WAAW;AAAA,EACnC,GAAG,CAAC,UAAU,CAAC;AAGf,+BAAU,MAAM;AACd,UAAM,KAAK,OAAO;AAClB,QAAI,CAAC,GAAI;AACT,UAAM,UAAU,CAAC,MAAkB;AACjC,QAAE,eAAe;AACjB,iBAAW,MAAM,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,GAAG,EAAE,OAAO,OAAG,qCAAqB,CAAC,CAAC;AAAA,IAClF;AACA,OAAG,iBAAiB,SAAS,SAAS,EAAE,SAAS,MAAM,CAAC;AACxD,WAAO,MAAM,GAAG,oBAAoB,SAAS,OAAO;AAAA,EACtD,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,QAAQ,CAAC,MAA4C;AACzD,UAAM,OAAO,OAAO,SAAS,sBAAsB;AACnD,WAAO,EAAE,GAAG,EAAE,WAAW,MAAM,QAAQ,IAAI,GAAG,EAAE,WAAW,MAAM,OAAO,GAAG;AAAA,EAC7E;AAEA,QAAM,YAAY,CAAC,SAAmC,CAAC,UAAgC;AACrF,UAAM,SAAU,SAAS,iBAAiB,QAAQ,MAAM,cAAc;AACtE,UAAM,OAAO,QAAQ;AACrB,QAAI,SAAS,SAAS;AACpB,YAAMC,QAAO,MAAM,QAAQ,YAAY,KAAK;AAC5C,YAAM,SAASA,QAAO,WAAW,MAAMA,KAAI,IAAI,WAAW,MAAM;AAChE,UAAI,OAAO,OAAQ,OAAM,iBAAiB;AAC1C;AAAA,IACF;AACA,UAAM,OAAO,SAAS,QAAQ,WAAW,IAAI,IAAI,WAAW,KAAK;AACjE,QAAI,QAAQ,MAAM;AAChB,WAAK,QAAQ,cAAc,IAAI;AAC/B,YAAM,iBAAiB;AAAA,IACzB;AAAA,EACF;AAEA,QAAM,KAAK,eAAAD,qBAAM;AACjB,QAAM,KAAK,eAAAA,qBAAM;AACjB,QAAM,MAAM,QAAQ;AAEpB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACL,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,UAAU;AAAA,MACV,aAAW,MAAM;AAAA,MACjB;AAAA,MACA,OAAO,EAAE,SAAS,SAAS,OAAO,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,aAAa,QAAQ,YAAY,QAAQ,QAAQ,MAAM,QAAQ,GAAG,MAAM;AAAA,MACnJ,eAAe,CAAC,MAAM;AACpB,eAAO,SAAS,MAAM,EAAE,eAAe,KAAK,CAAC;AAC7C,QAAC,EAAE,cAA0B,oBAAoB,EAAE,SAAS;AAC5D,mBAAW,YAAY,MAAM,CAAC,OAAG,qCAAqB,CAAC,CAAC;AAAA,MAC1D;AAAA,MACA,eAAe,CAAC,MAAM,WAAW,YAAY,MAAM,CAAC,OAAG,qCAAqB,CAAC,CAAC;AAAA,MAC9E,aAAa,CAAC,MAAM;AAClB,QAAC,EAAE,cAA0B,wBAAwB,EAAE,SAAS;AAChE,mBAAW,UAAU,MAAM,CAAC,OAAG,qCAAqB,CAAC,CAAC;AAAA,MACxD;AAAA,MACA,iBAAiB,MAAM,WAAW,WAAW;AAAA,MAC7C,gBAAgB,MAAM,WAAW,aAAa;AAAA,MAC9C,eAAe,CAAC,MAAM,WAAW,YAAY,MAAM,CAAC,CAAC;AAAA,MACrD,WAAW,CAAC,MAAM;AAChB,gBAAI,mCAAmB,EAAE,MAAM,EAAG;AAClC,YAAI,WAAW,YAAQ,iCAAiB,CAAC,CAAC,EAAG,GAAE,eAAe;AAAA,MAChE;AAAA,MACA,SAAS,CAAC,MAAM,WAAW,UAAM,iCAAiB,CAAC,CAAC;AAAA,MACpD,QAAQ,UAAU,MAAM;AAAA,MACxB,OAAO,UAAU,KAAK;AAAA,MACtB,SAAS,UAAU,OAAO;AAAA,MAEzB;AAAA,wBACC,4CAAC,UACC,uDAAC,aAAQ,IAAI,KAAK,GAAG,YAAY,OAAO,IAAI,QAAQ,IAAI,cAAa,kBACnE;AAAA,sDAAC,UAAK,OAAO,IAAI,QAAQ,IAAI,MAAK,WAAU;AAAA,UAC5C,4CAAC,UAAK,OAAO,GAAG,QAAQ,GAAG,MAAK,WAAU;AAAA,UAC1C,4CAAC,UAAK,GAAG,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAK,WAAU;AAAA,WACxD,GACF;AAAA,QAEF,4CAAC,sBAAmB,MAAM,MAAM,MAAM;AAAA,QACtC;AAAA,UAAC;AAAA;AAAA,YACC,wBAAqB;AAAA,YACrB,GAAG,QAAQ,SAAS;AAAA,YACpB,GAAG,QAAQ,SAAS;AAAA,YACpB,OAAO,QAAQ,SAAS;AAAA,YACxB,QAAQ,QAAQ,SAAS;AAAA,YACzB,MAAM,MAAM,eAAe,eAAe,UAAU,GAAG,cAAc;AAAA,YACrE,QAAO;AAAA;AAAA,QACT;AAAA,QACA,4CAAC,OAAE,qBAAkB,IAAG,WAAW,MAAM,WACvC,sDAAC,oBAAiB,OAAO,MAAM,OAAO,GACxC;AAAA,QACA,6CAAC,OAAE,uBAAoB,IAAG,eAAc,QAAO,MAAK,QACjD;AAAA,kBAAQ,SAAS,IAAI,CAAC,MACrB,4CAAC,UAAgB,GAAG,EAAE,GAAG,QAAQ,aAAa,aAAa,EAAE,WAAW,IAAI,KAAK,SAAS,EAAE,WAAW,IAAI,OAAhG,EAAE,EAAmG,CACjH;AAAA,UACA,QAAQ,cAAc,4CAAC,UAAK,GAAG,QAAQ,YAAY,QAAQ,aAAa,iBAAgB,OAAM;AAAA,UAC9F,OACC,6CAAC,OAAE,yBAAsB,IAAG,WAAW,IAAI,aAAa,QACtD;AAAA,wDAAC,UAAK,GAAG,IAAI,GAAG,GAAG,IAAI,GAAG,OAAO,IAAI,OAAO,QAAQ,IAAI,QAAQ,QAAQ,aAAa;AAAA,YACrF,4CAAC,UAAK,IAAI,IAAI,IAAI,IAAI,QAAQ,GAAG,IAAI,IAAI,GAAG,IAAI,IAAI,IAAI,IAAI,QAAQ,GAAG,IAAI,IAAI,IAAI,IAAI,QAAQ,aAAa;AAAA,YAC3G,IAAI,QAAQ;AAAA,cAAI,CAAC,MAChB,EAAE,WAAW,WACX,4CAAC,YAAsB,eAAa,EAAE,QAAQ,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,KAAK,IAAI,GAAG,MAAM,eAAAA,qBAAM,YAAY,QAAQ,eAAlG,EAAE,MAA6G,IAE5H,4CAAC,UAAoB,eAAa,EAAE,QAAQ,GAAG,EAAE,IAAI,KAAK,GAAG,GAAG,EAAE,IAAI,KAAK,GAAG,OAAO,IAAI,QAAQ,IAAI,MAAM,eAAAA,qBAAM,YAAY,QAAQ,eAA1H,EAAE,MAAqI;AAAA,YAEtJ;AAAA,aACF;AAAA,UAED,QAAQ,QAAQ,IAAI,CAAC,MACpB,6CAAC,OAA0E,sBAAoB,EAAE,IAAI,QACnG;AAAA,wDAAC,UAAK,IAAI,EAAE,SAAS,IAAI,EAAE,SAAS,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,aAAa;AAAA,YAC3E,4CAAC,YAAO,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,eAAAA,qBAAM,gBAAgB,EAAE,UAAU,IAAI,IAAI,MAAM,eAAAA,qBAAM,YAAY,QAAQ,aAAa;AAAA,eAF9G,GAAG,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,OAAO,IAAI,EAAE,IAAI,KAAK,IAAI,EAAE,IAAI,MAAM,EAGvE,CACD;AAAA,UACA,QAAQ,QAAQ,IAAI,CAAC,MAAM;AAC1B,kBAAM,OAAO,MAAM,EAAE,UAAU,IAAI;AACnC,kBAAM,OAAO,EAAE,WAAW,cAAc,eAAAA,qBAAM;AAC9C,kBAAM,MAAM,GAAG,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,OAAO,IAAI,EAAE,IAAI,KAAK;AAC3D,mBAAO,EAAE,SAAS,WAChB,4CAAC,UAAe,sBAAoB,EAAE,IAAI,OAAO,GAAG,EAAE,IAAI,OAAO,GAAG,GAAG,EAAE,IAAI,OAAO,GAAG,OAAO,MAAM,QAAQ,MAAM,MAAY,QAAQ,eAA3H,GAAwI,IAEnJ,4CAAC,YAAiB,sBAAoB,EAAE,IAAI,OAAO,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,OAAO,GAAG,MAAY,QAAQ,eAAzF,GAAsG;AAAA,UAEvH,CAAC;AAAA,UACA,QAAQ,cAAc,IAAI,CAAC,MAC1B,6CAAC,OAAiE,6BAA2B,EAAE,IAAI,OAAO,oBAAkB,EAAE,MAC5H;AAAA,wDAAC,YAAO,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,eAAAA,qBAAM,sBAAsB,EAAE,UAAU,IAAI,IAAI,MAAM,eAAAA,qBAAM,YAAY,QAAQ,aAAa;AAAA,YAC1H,4CAAC,YAAO,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,GAAG,KAAK,MAAM,aAAa;AAAA,eAF/C,UAAU,EAAE,IAAI,MAAM,IAAI,EAAE,IAAI,OAAO,IAAI,EAAE,IAAI,KAAK,EAG9D,CACD;AAAA,UACA,MAAM,SAAS,SAAS,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,KACxE,4CAAC,YAAO,IAAI,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,MAAM,EAAG,GAAG,IAAI,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,MAAM,EAAG,GAAG,GAAG,IAAI,QAAQ,aAAa;AAAA,UAEjI,QAAQ,cACP;AAAA,YAAC;AAAA;AAAA,cACC,2BAAyB,QAAQ,WAAW;AAAA,cAC5C,GAAG,QAAQ,WAAW;AAAA,cACtB,QAAQ,QAAQ,WAAW,SAAS,WAAW,eAAAA,qBAAM,aAAa;AAAA,cAClE,aAAa,QAAQ,WAAW,SAAS,WAAW,QAAQ,WAAW,QAAQ;AAAA,cAC/E,eAAc;AAAA,cACd,gBAAe;AAAA,cACf,iBAAiB,QAAQ,WAAW,SAAS,UAAU,QAAQ;AAAA;AAAA,UACjE;AAAA,UAED,QAAQ,gBACP;AAAA,YAAC;AAAA;AAAA,cACC,6BAA0B;AAAA,cAC1B,IAAI,QAAQ,aAAa;AAAA,cACzB,IAAI,QAAQ,aAAa;AAAA,cACzB,IAAI,QAAQ,aAAa;AAAA,cACzB,IAAI,QAAQ,aAAa;AAAA,cACzB,QAAQ;AAAA,cACR,iBAAgB;AAAA;AAAA,UAClB;AAAA,UAED,QAAQ,YAAY,4CAAC,YAAO,yBAAsB,IAAG,IAAI,QAAQ,SAAS,GAAG,IAAI,QAAQ,SAAS,GAAG,GAAG,eAAAA,qBAAM,eAAe,GAAG,MAAM,eAAAA,qBAAM,YAAY,QAAQ,aAAa;AAAA,UAC7K,QAAQ,WACP;AAAA,YAAC;AAAA;AAAA,cACC,uBAAoB;AAAA,cACpB,GAAG,QAAQ,QAAQ;AAAA,cACnB,GAAG,QAAQ,QAAQ;AAAA,cACnB,OAAO,QAAQ,QAAQ;AAAA,cACvB,QAAQ,QAAQ,QAAQ;AAAA,cACxB,MAAM,eAAAA,qBAAM;AAAA,cACZ,QAAQ;AAAA,cACR,iBAAgB;AAAA;AAAA,UAClB;AAAA,UAED,QAAQ,OAAO,MAAM,SAAS,KAC7B,4CAAC,OAAE,sBAAmB,IAAG,QAAQ,YAC9B,kBAAQ,OAAO,MAAM,IAAI,CAAC,GAAG,MAC5B,4CAAC,UAAa,qBAAmB,EAAE,MAAM,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,IAAI,iBAAiB,EAAE,SAAS,iBAAiB,QAAQ,UAA3H,CAAsI,CAClJ,GACH;AAAA,UAED,QAAQ,OAAO,OAAO,IAAI,CAAC,GAAG,MAC7B;AAAA,YAAC;AAAA;AAAA,cAEC,2BAAyB,EAAE;AAAA,cAC3B,GAAG,EAAE,IAAI;AAAA,cACT,GAAG,EAAE,IAAI;AAAA,cACT,UAAU;AAAA,cACV,MAAM;AAAA,cACN,QAAO;AAAA,cACP,aAAa;AAAA,cACb,YAAW;AAAA,cACX,OAAO,EAAE,YAAY,wBAAwB;AAAA,cAE5C,YAAE;AAAA;AAAA,YAXE;AAAA,UAYP,CACD;AAAA,UACA,QAAQ,UACP,4CAAC,UAAK,sBAAmB,IAAG,GAAG,GAAG,GAAE,QAAO,IAAI,IAAI,UAAU,IAAI,MAAM,aAAa,OAAO,EAAE,YAAY,wBAAwB,GAC9H,kBAAQ,QACX;AAAA,WAEJ;AAAA;AAAA;AAAA,EACF;AAEJ;;;ACxWA,IAAAE,iBAmBO;AAoCH,IAAAC,sBAAA;AAjCJ,IAAM,oBAAoB;AAC1B,IAAM,cAAc,MAAO,OAAO,cAAc,eAAe,kBAAkB,KAAK,UAAU,YAAY,EAAE,IAAI,WAAM;AAExH,IAAM,cACJ;AAsBK,SAAS,cAAc,EAAE,YAAY,QAAQ,6BAAc,cAAc,MAAM,cAAc,MAAM,WAAW,MAAM,eAAe,MAAM,UAAU,GAAuB;AAC/K,QAAM,QAAQ,qBAAqB,UAAU;AAC7C,QAAM,QAAQ,MAAM,UAAU;AAC9B,QAAM,SAAS,MAAM,SAAS,WAAW,MAAM,gBAAgB,SAAS;AACxE,QAAM,UAAU,MAAM;AACtB,QAAM,gBAAgB,MAAM,UAAU,KAAK,CAAC,OAAO,WAAW,QAAQ,EAAE,GAAG,SAAS,OAAO;AAC3F,QAAM,MAAM,CAAC,OAAe,OAAe,KAAoB,WAAW,UACxE,6CAAC,YAAmB,MAAK,UAAS,WAAW,aAAa,OAAc,cAAY,OAAO,UAAoB,SAAS,MAAM,KAAK,IAAI,GACpI,mBADU,KAEb;AAEF,SACE,8CAAC,SAAI,MAAK,WAAU,cAAW,gBAAe,WAAW,qCAAqC,aAAa,EAAE,IAC3G;AAAA,iDAAC,SAAI,WAAU,2BAA0B,MAAK,SAAQ,cAAW,SAC9D,gBAAM,IAAI,CAAC,SACV;AAAA,MAAC;AAAA;AAAA,QAEC,MAAK;AAAA,QACL,oBAAkB;AAAA,QAClB,WAAW;AAAA,QACX,gBAAc,MAAM,SAAS;AAAA,QAC7B,OAAO,OAAG,gCAAgB,IAAI,CAAC,KAAK,qCAAsB,IAAI,CAAC;AAAA,QAC/D,kBAAY,gCAAgB,IAAI;AAAA,QAChC,SAAS,MAAM,WAAW,QAAQ,IAAI;AAAA,QAErC,4CAAmB,IAAI;AAAA;AAAA,MATnB;AAAA,IAUP,CACD,GACH;AAAA,IACC,eACC,8CAAC,SAAI,WAAU,gCAA+B,MAAK,SAAQ,cAAW,WACnE;AAAA,UAAI,UAAK,MAAM,UAAU,QAAQ,MAAM,SAAS,KAAK,QAAQ,MAAM,WAAW,KAAK,GAAG,CAAC,MAAM,OAAO;AAAA,MACpG,IAAI,UAAK,MAAM,UAAU,QAAQ,MAAM,SAAS,KAAK,QAAQ,MAAM,WAAW,KAAK,GAAG,CAAC,MAAM,OAAO;AAAA,OACvG;AAAA,IAED,YACC,6CAAC,SAAI,WAAU,gCAA+B,MAAK,SAAQ,cAAW,YACpE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,oBAAiB;AAAA,QACjB,WAAW;AAAA,QACX,gBAAc,MAAM,KAAK;AAAA,QACzB,OAAO,GAAG,iBAAiB,UAAU,YAAY,CAAC;AAAA,QAClD,cAAY;AAAA,QACZ,SAAS,MAAM,WAAW,eAAe;AAAA,QAC1C;AAAA;AAAA,IAED,GACF;AAAA,IAED,gBACC,8CAAC,SAAI,WAAU,gCAA+B,MAAK,SAAQ,cAAW,gBACnE;AAAA,yCAAoB,IAAI,CAAC,MACxB;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,2BAAyB,EAAE;AAAA,UAC3B,WAAW;AAAA,UACX,OAAO,EAAE,WAAW,GAAG,EAAE,KAAK,KAAK,YAAY,CAAC,IAAI,EAAE,QAAQ,MAAM,EAAE;AAAA,UACtE,cAAY,EAAE;AAAA,UACd,UAAU,CAAC,EAAE,QAAQ,OAAO,MAAM;AAAA,UAClC,SAAS,MAAM,KAAK,EAAE,IAAI,UAAU;AAAA,UAEnC,YAAE;AAAA;AAAA,QATE,EAAE;AAAA,MAUT,CACD;AAAA,MACA,mCAAoB,IAAI,CAAC,MACxB;AAAA,QAAC;AAAA;AAAA,UAEC,MAAK;AAAA,UACL,oBAAkB,EAAE;AAAA,UACpB,WAAW;AAAA,UACX,gBAAc,QAAQ,EAAE,GAAG;AAAA,UAC3B,OAAO,EAAE;AAAA,UACT,cAAY,EAAE;AAAA,UACd,SAAS,MAAM,WAAW,WAAW,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC;AAAA,UAEhE,YAAE;AAAA;AAAA,QATE,EAAE;AAAA,MAUT,CACD;AAAA,MACA,MAAM,SAAS,YACd,8CAAC,WAAM,WAAU,mDAAkD;AAAA;AAAA,QAEjE;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,KAAK;AAAA,YACL,KAAK;AAAA,YACL,MAAM;AAAA,YACN,cAAW;AAAA,YACX,WAAU;AAAA,YACV,OAAO,QAAQ;AAAA,YACf,UAAU,CAAC,MAAM,WAAW,WAAW,EAAE,iBAAiB,WAAW,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA;AAAA,QACxF;AAAA,SACF;AAAA,MAED,MAAM,SAAS,YACd,8CAAC,WAAM,WAAU,mDAAkD;AAAA;AAAA,QAEjE;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,KAAK;AAAA,YACL,MAAM;AAAA,YACN,cAAW;AAAA,YACX,WAAU;AAAA,YACV,OAAO,QAAQ;AAAA,YACf,UAAU,CAAC,MAAM;AACf,oBAAM,IAAI,WAAW,EAAE,OAAO,KAAK;AACnC,kBAAI,OAAO,SAAS,CAAC,KAAK,IAAI,EAAG,YAAW,WAAW,EAAE,YAAY,EAAE,CAAC;AAAA,YAC1E;AAAA;AAAA,QACF;AAAA,SACF;AAAA,OAEJ;AAAA,IAED,eACC,8EACE;AAAA,oDAAC,SAAI,WAAU,gCAA+B,MAAK,SAAQ,cAAW,WACnE;AAAA,YAAI,UAAK,SAAS,MAAM,WAAW,UAAU,OAAO,GAAG,QAAQ,CAAC;AAAA,QAChE,IAAI,UAAK,YAAY,MAAM,WAAW,UAAU,UAAU,GAAG,QAAQ,CAAC;AAAA,QACtE,IAAI,UAAK,aAAa,MAAM,WAAW,UAAU,WAAW,GAAG,QAAQ,CAAC;AAAA,QACxE,IAAI,UAAK,WAAW,MAAM,WAAW,UAAU,SAAS,GAAG,QAAQ,CAAC;AAAA,QACpE,IAAI,KAAK,SAAS,MAAM,WAAW,MAAM,GAAG,QAAQ,CAAC;AAAA,QACrD,IAAI,KAAK,WAAW,MAAM,WAAW,QAAQ,GAAG,CAAC,aAAa;AAAA,SACjE;AAAA,MACA,8CAAC,SAAI,WAAU,gCAA+B,MAAK,SAAQ,cAAW,WACnE;AAAA,YAAI,UAAK,kBAAkB,MAAM,WAAW,QAAQ,OAAO,GAAG,QAAQ,CAAC;AAAA,QACvE,IAAI,UAAK,gBAAgB,MAAM,WAAW,QAAQ,MAAM,GAAG,QAAQ,CAAC;AAAA,QACpE,IAAI,UAAK,cAAc,MAAM,WAAW,MAAM,MAAM,GAAG,QAAQ,CAAC;AAAA,QAChE,IAAI,UAAK,gBAAgB,MAAM,WAAW,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAAA,QACpE,IAAI,UAAK,eAAe,MAAM,WAAW,MAAM,OAAO,GAAG,QAAQ,CAAC;AAAA,QAClE,IAAI,UAAK,aAAa,MAAM,WAAW,MAAM,KAAK,GAAG,QAAQ,CAAC;AAAA,QAC9D,IAAI,UAAK,gBAAgB,MAAM,WAAW,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAAA,QACpE,IAAI,UAAK,gBAAgB,MAAM,WAAW,MAAM,QAAQ,GAAG,QAAQ,CAAC;AAAA,SACvE;AAAA,OACF;AAAA,KAEJ;AAEJ;AAOA,IAAM,cAAc;AACpB,IAAM,cAAc;AAOb,SAAS,iBAAiB,EAAE,YAAY,UAAU,GAA0B;AACjF,QAAM,QAAQ,qBAAqB,UAAU;AAC7C,QAAM,YAAQ,wCAAwB,KAAK;AAC3C,QAAM,IAAI,MAAM;AAChB,QAAM,SAAS,SAAS;AAAA,IACtB,MAAM,EAAE,QAAQ;AAAA,IAChB,QAAQ,EAAE,UAAU;AAAA,IACpB,aAAa,EAAE,eAAe;AAAA,IAC9B,SAAS;AAAA,IACT,aAAa,EAAE,eAAe;AAAA,IAC9B,YAAY,EAAE,cAAc;AAAA,IAC5B,UAAU,EAAE,YAAY;AAAA,IACxB,YAAY,EAAE,cAAc;AAAA,IAC5B,iBAAiB,EAAE,mBAAmB;AAAA,IACtC,eAAe,EAAE,iBAAiB;AAAA,IAClC,cAAc,EAAE;AAAA,IAChB,YAAY,EAAE,cAAc;AAAA,IAC5B,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AACA,QAAM,aAAa,CAAC,UAAwD;AAC1E,QAAI,CAAC,MAAO,YAAW,YAAY,EAAE,GAAI,MAAM,WAAW,SAAY,EAAE,cAAc,MAAM,OAAO,IAAI,CAAC,GAAI,GAAI,MAAM,OAAO,EAAE,YAAY,MAAM,KAAK,IAAI,CAAC,EAAG,CAAC;AAAA,aACtJ,MAAM,WAAW,OAAW,YAAW,gBAAgB,MAAM,MAAM;AAAA,aACnE,MAAM,KAAM,YAAW,cAAc,MAAM,IAAI;AAAA,EAC1D;AACA,QAAM,QAAQ,CAAC,QAAmD,OAAO,MAAM,GAAG,IAAI,6CAAC,UAAK,WAAU,qCAAoC,mBAAK,IAAU;AACzJ,QAAM,WAAW,CAAC,KAAsB,UAAkB;AACxD,UAAM,MAAM,QAAQ,UAAU,eAAe;AAC7C,UAAM,WAAW,QAAQ,UAAU,oBAAoB;AACvD,WACE,8CAAC,SAAI,WAAU,2BAA0B,qBAAmB,KAC1D;AAAA,mDAAC,UAAK,WAAU,gCAAgC,iBAAM;AAAA,MACtD,8CAAC,YAAO,cAAY,GAAG,KAAK,cAAc,WAAW,aAAa,OAAO,OAAO,GAAG,KAAK,IAAI,UAAU,CAAC,MAAM,MAAM,EAAE,CAAC,GAAG,GAAI,EAAE,OAAO,SAAS,KAAgC,CAAC,GAC9K;AAAA,qDAAC,YAAO,OAAM,IAAG,kBAAI;AAAA,QACpB,iCAAkB,IAAI,CAAC,MACtB,6CAAC,YAAe,OAAO,GACpB,iDAAwB,CAAC,KADf,CAEb,CACD;AAAA,SACH;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,cAAY,GAAG,KAAK;AAAA,UACpB,OAAM;AAAA,UACN,WAAW;AAAA,UACX,OAAO,OAAO,QAAQ;AAAA,UACtB,UAAU,CAAC,MAAM;AACf,kBAAM,IAAI,WAAW,EAAE,OAAO,KAAK;AACnC,gBAAI,OAAO,SAAS,CAAC,KAAK,IAAI,EAAG,OAAM,EAAE,CAAC,QAAQ,GAAG,EAAE,CAAC;AAAA,UAC1D;AAAA;AAAA,MACF;AAAA,OACF;AAAA,EAEJ;AACA,QAAM,QAAQ,CAAC,UAAmC;AAChD,QAAI,MAAO,YAAW,SAAS,KAAK;AAAA,QAC/B,YAAW,YAAY,KAAK;AAAA,EACnC;AACA,QAAM,WAAW,CAAC,KAAwB,UAAkB;AAC1D,UAAM,QAAQ,OAAO,GAAG;AACxB,UAAM,UAAM,iCAAiB,KAAK;AAClC,UAAM,KAAK,UAAU,QAAQ,UAAU;AACvC,WACE,8CAAC,SAAI,WAAU,2BAA0B,qBAAmB,KAC1D;AAAA,oDAAC,WAAM,WAAU,0DACf;AAAA,qDAAC,WAAM,MAAK,YAAW,SAAS,IAAI,cAAY,GAAG,KAAK,OAAO,UAAU,CAAC,MAAM,MAAM,EAAE,CAAC,GAAG,GAAG,EAAE,OAAO,UAAW,OAAO,YAAa,KAAK,CAAC,GAAG;AAAA,QAC/I;AAAA,SACH;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,cAAY,GAAG,KAAK;AAAA,UACpB,WAAU;AAAA,UACV,UAAU,CAAC;AAAA,UACX,OAAO,OAAO;AAAA,UACd,UAAU,CAAC,MAAM,MAAM,EAAE,CAAC,GAAG,GAAG,EAAE,OAAO,MAAM,CAAC;AAAA;AAAA,MAClD;AAAA,MACC,MAAM,CAAC,OAAO,6CAAC,UAAK,WAAU,8CAA8C,iBAAO,UAAU,WAAW,QAAQ,YAAW;AAAA,MAC3H,OAAO,MAAM,GAAG,KAAK,6CAAC,UAAK,WAAU,qCAAoC,mBAAK;AAAA,OACjF;AAAA,EAEJ;AACA,SACE,8CAAC,SAAI,WAAW,aAAa,aAAa,EAAE,IAAI,cAAY,QAAQ,oBAAoB,mBACtF;AAAA,iDAAC,OAAE,WAAU,yEAAyE,kBAAQ,cAAc,cAAa;AAAA,IACxH,SAAS,QAAQ,MAAM;AAAA,IACvB,SAAS,UAAU,QAAQ;AAAA,IAC5B,8CAAC,WAAM,WAAU,mDACf;AAAA,mDAAC,UAAK,WAAU,QAAO,mBAAK;AAAA,MAC5B;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,cAAW;AAAA,UACX,WAAU;AAAA,UACV,OAAO,OAAO;AAAA,UACd,UAAU,CAAC,MAAM;AACf,kBAAM,IAAI,WAAW,EAAE,OAAO,KAAK;AACnC,gBAAI,OAAO,SAAS,CAAC,KAAK,KAAK,EAAG,OAAM,EAAE,aAAa,EAAE,CAAC;AAAA,UAC5D;AAAA;AAAA,MACF;AAAA,OACF;AAAA,IACA,8CAAC,WAAM,WAAU,mDAAkD,qBAAkB,eACnF;AAAA,mDAAC,UAAK,WAAU,QAAO,mBAAK;AAAA,MAC5B,6CAAC,YAAO,cAAW,oBAAmB,WAAW,aAAa,OAAO,OAAO,aAAa,UAAU,CAAC,MAAM,MAAM,EAAE,aAAa,EAAE,OAAO,MAA2B,CAAC,GAChK,iBAAO,KAAK,yCAA0B,EAA0B,IAAI,CAAC,MACrE,6CAAC,YAAe,OAAO,GACpB,oDAA2B,CAAC,KADlB,CAEb,CACD,GACH;AAAA,MACC,MAAM,aAAa;AAAA,OACtB;AAAA,IACC,OAAO,eACN,8EACG;AAAA,eAAS,SAAS,OAAO;AAAA,MACzB,SAAS,OAAO,KAAK;AAAA,OACpB,OAAO,cAAc,OAAO,aAC5B,8CAAC,WAAM,WAAU,mDAAkD,qBAAkB,cACnF;AAAA,qDAAC,UAAK,WAAU,QAAO,mBAAK;AAAA,QAC5B,8CAAC,YAAO,cAAW,uBAAsB,WAAW,aAAa,OAAO,OAAO,YAAY,UAAU,CAAC,MAAM,MAAM,EAAE,YAAY,EAAE,OAAO,MAAM,CAAC,GAC9I;AAAA,uDAAC,YAAO,OAAM,UAAS,0BAAY;AAAA,UACnC,6CAAC,YAAO,OAAM,OAAM,wBAAU;AAAA,WAChC;AAAA,SACF;AAAA,OAEJ;AAAA,IAED,OAAO,UAAU,KAChB,8CAAC,SAAI,WAAU,2BAA0B,qBAAkB,WACzD;AAAA,mDAAC,UAAK,WAAU,gCAA+B,qBAAO;AAAA,MACtD;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,cAAW;AAAA,UACX,WAAW;AAAA,UACX,OAAO,KAAK,MAAM,OAAO,eAAe,GAAG,IAAI;AAAA,UAC/C,UAAU,CAAC,MAAM;AACf,kBAAM,IAAI,WAAW,EAAE,OAAO,KAAK;AACnC,gBAAI,OAAO,SAAS,CAAC,KAAK,KAAK,EAAG,YAAW,EAAE,QAAQ,EAAE,CAAC;AAAA,UAC5D;AAAA;AAAA,MACF;AAAA,MACA,6CAAC,YAAO,cAAW,eAAc,WAAW,aAAa,OAAO,OAAO,YAAY,UAAU,CAAC,MAAM,WAAW,EAAE,MAAM,EAAE,OAAO,MAA0B,CAAC,GACxJ,6CAAoB,IAAI,CAAC,MACxB,6CAAC,YAAe,OAAO,GACpB,mDAA0B,CAAC,KADjB,CAEb,CACD,GACH;AAAA,MACC,MAAM,cAAc;AAAA,OACvB;AAAA,IAED,SACC,8CAAC,WAAM,WAAU,mDACf;AAAA,mDAAC,UAAK,WAAU,QAAO,qBAAO;AAAA,MAC9B;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,KAAK;AAAA,UACL,KAAK;AAAA,UACL,MAAM;AAAA,UACN,cAAW;AAAA,UACX,WAAU;AAAA,UACV,OAAO,OAAO;AAAA,UACd,UAAU,CAAC,MAAM,MAAM,EAAE,SAAS,WAAW,EAAE,OAAO,KAAK,EAAE,CAAC;AAAA;AAAA,MAChE;AAAA,OACF;AAAA,KAEJ;AAEJ;;;AChWM,IAAAC,sBAAA;AAHC,SAAS,aAAa,EAAE,YAAY,OAAO,iBAAiB,MAAM,SAAS,KAAK,aAAa,UAAU,GAAsB;AAClI,SACE,8CAAC,SAAI,WAAW,uBAAuB,aAAa,EAAE,IAAI,sBAAmB,IAC3E;AAAA,iDAAC,iBAAc,YAAwB,OAAc;AAAA,IACrD,8CAAC,SAAI,WAAU,2CACb;AAAA,mDAAC,SAAI,WAAU,6FAA4F,OAAO,EAAE,OAAO,GACzH,uDAAC,gBAAa,YAAyB,GAAG,aAAa,GACzD;AAAA,MACC,kBAAkB,6CAAC,oBAAiB,YAAwB,WAAU,+DAA8D;AAAA,OACvI;AAAA,KACF;AAEJ;","names":["import_react","import_vector","THEME","text","import_vector","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/vector/index.ts","../../src/vector/useVectorEditor.ts","../../src/vector/VectorCanvas.tsx","../../src/vector/VectorToolbar.tsx","../../src/vector/VectorEditor.tsx"],"sourcesContent":["export * from './useVectorEditor';\nexport * from './VectorCanvas';\nexport * from './VectorToolbar';\nexport * from './VectorEditor';\n","import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n VectorEditorController,\n createVectorCommands,\n type VectorCommandOptions,\n type VectorEditorOptions,\n type VectorEditorState,\n type VectorTool,\n} from '@pixerate/editor/vector';\n\n/** A `VectorEditorController` created once for the component's lifetime (destroyed on unmount). */\nexport function useVectorEditorController(options: VectorEditorOptions = {}): VectorEditorController {\n const ref = useRef<VectorEditorController | null>(null);\n if (!ref.current) ref.current = new VectorEditorController(options);\n const controller = ref.current;\n useEffect(() => () => controller.destroy(), [controller]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change). */\nexport function useVectorEditorState(controller: VectorEditorController): VectorEditorState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseVectorEditorResult {\n controller: VectorEditorController;\n state: VectorEditorState;\n setTool: (tool: VectorTool) => void;\n undo: () => void;\n redo: () => void;\n deleteSelection: () => void;\n toSvg: () => string;\n}\n\n/**\n * Subscribes to a vector editor controller and exposes its state with bound actions. Pass\n * options instead of a controller to create one for the component's lifetime.\n */\nexport function useVectorEditor(controllerOrOptions: VectorEditorController | VectorEditorOptions = {}): UseVectorEditorResult {\n const own = useRef<VectorEditorController | null>(null);\n let controller: VectorEditorController;\n if (controllerOrOptions instanceof VectorEditorController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new VectorEditorController(controllerOrOptions);\n controller = own.current;\n }\n const state = useVectorEditorState(controller);\n const actions = useMemo(\n () => ({\n setTool: (tool: VectorTool) => controller.setTool(tool),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n deleteSelection: () => void controller.deleteSelection(),\n toSvg: () => controller.toSvg(),\n }),\n [controller],\n );\n return { controller, state, ...actions };\n}\n\n/** Anything with `register(specs) → unregister` (a `CommandRegistry`). */\nexport interface VectorCommandTarget {\n register(specs: any): () => void;\n}\n\n/**\n * Registers the controller's palette / agent commands (`vector.addShape`, `vector.boolean`, …)\n * in `registry` while mounted, so `createCommandToolProvider` exposes them to agents.\n */\nexport function useVectorCommands(\n registry: VectorCommandTarget | null | undefined,\n controller: VectorEditorController,\n options: VectorCommandOptions = {},\n): void {\n const { prefix, group, scope } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createVectorCommands(controller, { prefix, group, scope }));\n }, [registry, controller, prefix, group, scope]);\n}\n","import React, { useEffect, useId, useRef } from 'react';\nimport {\n VECTOR_OVERLAY_THEME as THEME,\n getVectorOverlayRenderData,\n getVectorSceneRenderData,\n isVectorTextTarget,\n toVectorKeyInput,\n toVectorPointerInput,\n vectorDiamondPath,\n type VectorEditorController,\n type VectorRenderNode,\n type VectorRenderPath,\n type SvgGradientDef,\n} from '@pixerate/editor/vector';\nimport { useVectorEditorState } from './useVectorEditor';\n\nexport interface VectorCanvasProps {\n controller: VectorEditorController;\n /** Fit the artboard into the canvas when it first gets a size (default `true`). */\n fitOnMount?: boolean;\n /** Draw a checkerboard behind a transparent artboard (default `true`). */\n checkerboard?: boolean;\n /** Overlay accent colour (default sky blue). */\n accentColor?: string;\n /** Smart guide colour (default magenta). */\n guideColor?: string;\n className?: string;\n style?: React.CSSProperties;\n /** Accessible label (default \"Vector canvas\"). */\n 'aria-label'?: string;\n}\n\n/** Renders `<linearGradient>` / `<radialGradient>` descriptors. */\nexport function VectorGradientDefs({ defs }: { defs: readonly SvgGradientDef[] }) {\n if (!defs.length) return null;\n return (\n <defs>\n {defs.map((def) => {\n const stops = def.stops.map((s, i) => <stop key={i} offset={s.offset} stopColor={s.stopColor} stopOpacity={s.stopOpacity} />);\n return def.type === 'radial' ? (\n <radialGradient key={def.id} id={def.id} {...(def.attrs as any)}>\n {stops}\n </radialGradient>\n ) : (\n <linearGradient key={def.id} id={def.id} {...(def.attrs as any)}>\n {stops}\n </linearGradient>\n );\n })}\n </defs>\n );\n}\n\n/** Renders scene nodes (paths and groups) from `getVectorSceneRenderData`. */\nexport function VectorSceneNodes({ nodes }: { nodes: readonly VectorRenderNode[] }) {\n return (\n <>\n {nodes.map((node) =>\n node.kind === 'group' ? (\n <g key={node.id} data-vector-id={node.id} transform={node.transform} opacity={node.opacity < 1 ? node.opacity : undefined}>\n <VectorSceneNodes nodes={node.children} />\n </g>\n ) : node.strokeParts ? (\n <VectorPartedPath key={node.id} node={node} />\n ) : (\n <path\n key={node.id}\n data-vector-id={node.id}\n transform={node.transform}\n d={node.d}\n fill={node.fill}\n fillRule={node.fillRule}\n stroke={node.stroke}\n strokeWidth={node.stroke === 'none' ? undefined : node.strokeWidth}\n strokeLinecap={node.strokeLinecap as any}\n strokeLinejoin={node.strokeLinejoin as any}\n strokeDasharray={node.strokeDasharray}\n opacity={node.opacity < 1 ? node.opacity : undefined}\n />\n ),\n )}\n </>\n );\n}\n\n/** A path whose stroke is aligned inside / outside (double width, clipped or masked by the shape) or has arrowheads. */\nfunction VectorPartedPath({ node }: { node: VectorRenderPath }) {\n const sp = node.strokeParts!;\n const clip = sp.clip;\n const b = clip?.bounds;\n return (\n <g data-vector-id={node.id} data-vector-stroke-align={sp.align} transform={node.transform} opacity={node.opacity < 1 ? node.opacity : undefined}>\n {clip && b && (\n <defs>\n {clip.kind === 'clip' ? (\n <clipPath id={clip.id}>\n <path d={node.d} clipRule={node.fillRule} />\n </clipPath>\n ) : (\n <mask id={clip.id} maskUnits=\"userSpaceOnUse\" x={b.x} y={b.y} width={b.width} height={b.height}>\n <rect x={b.x} y={b.y} width={b.width} height={b.height} fill=\"#fff\" />\n <path d={node.d} fill=\"#000\" fillRule={node.fillRule} />\n </mask>\n )}\n </defs>\n )}\n <path data-vector-part=\"fill\" d={node.d} fill={node.fill} fillRule={node.fillRule} stroke=\"none\" />\n {sp.outline !== undefined ? (\n // A variable-width stroke: its outline, filled.\n <path\n data-vector-part=\"stroke-outline\"\n d={sp.outline}\n fill={node.stroke}\n clipPath={clip?.kind === 'clip' ? `url(#${clip.id})` : undefined}\n mask={clip?.kind === 'mask' ? `url(#${clip.id})` : undefined}\n />\n ) : (\n <path\n data-vector-part=\"stroke\"\n d={sp.d}\n fill=\"none\"\n stroke={node.stroke}\n strokeWidth={sp.width}\n strokeLinecap={node.strokeLinecap as any}\n strokeLinejoin={node.strokeLinejoin as any}\n strokeDasharray={node.strokeDasharray}\n clipPath={clip?.kind === 'clip' ? `url(#${clip.id})` : undefined}\n mask={clip?.kind === 'mask' ? `url(#${clip.id})` : undefined}\n />\n )}\n {sp.heads.map((head, i) => (\n <path key={i} data-vector-part=\"head\" d={head} fill={node.stroke} />\n ))}\n </g>\n );\n}\n\n/**\n * An SVG canvas for a `VectorEditorController`: draws the document and the editing overlay\n * and forwards pointer, wheel, keyboard and clipboard events. Focus it to use shortcuts.\n */\nexport function VectorCanvas({\n controller,\n fitOnMount = true,\n checkerboard = true,\n accentColor = THEME.accent,\n guideColor = THEME.guide,\n className,\n style,\n 'aria-label': ariaLabel = 'Vector canvas',\n}: VectorCanvasProps) {\n const state = useVectorEditorState(controller);\n const svgRef = useRef<SVGSVGElement | null>(null);\n const fitted = useRef(!fitOnMount);\n const uid = useId().replace(/:/g, '');\n const scene = getVectorSceneRenderData(state, { idPrefix: `ve${uid}-` });\n const overlay = getVectorOverlayRenderData(state);\n\n useEffect(() => {\n const el = svgRef.current;\n if (!el || fitted.current) return;\n const fit = () => {\n const rect = el.getBoundingClientRect();\n if (fitted.current || rect.width <= 0 || rect.height <= 0) return;\n fitted.current = true;\n controller.zoomToFit({ width: rect.width, height: rect.height });\n };\n fit();\n if (fitted.current || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(fit);\n observer.observe(el);\n return () => observer.disconnect();\n }, [controller]);\n\n // Wheel needs a non-passive listener to stop page scroll / browser zoom.\n useEffect(() => {\n const el = svgRef.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n controller.wheel(local(e), { x: e.deltaX, y: e.deltaY }, toVectorPointerInput(e));\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [controller]);\n\n const local = (e: { clientX: number; clientY: number }) => {\n const rect = svgRef.current?.getBoundingClientRect();\n return { x: e.clientX - (rect?.left ?? 0), y: e.clientY - (rect?.top ?? 0) };\n };\n\n const clipboard = (kind: 'copy' | 'cut' | 'paste') => (event: React.ClipboardEvent) => {\n const native = (event && 'nativeEvent' in event ? event.nativeEvent : event) as ClipboardEvent;\n const data = native?.clipboardData;\n if (kind === 'paste') {\n const text = data?.getData('text/plain') ?? '';\n const pasted = text ? controller.paste(text) : controller.paste();\n if (pasted.length) event.preventDefault?.();\n return;\n }\n const text = kind === 'cut' ? controller.cut() : controller.copy();\n if (text && data) {\n data.setData('text/plain', text);\n event.preventDefault?.();\n }\n };\n\n const hs = THEME.transformHandleSize;\n const as = THEME.anchorSize;\n const box = overlay.selectionBox;\n\n return (\n <svg\n ref={svgRef}\n role=\"application\"\n aria-label={ariaLabel}\n tabIndex={0}\n data-tool={state.tool}\n className={className}\n style={{ display: 'block', width: '100%', height: '100%', outline: 'none', touchAction: 'none', userSelect: 'none', cursor: state.cursor, ...style }}\n onPointerDown={(e) => {\n svgRef.current?.focus({ preventScroll: true });\n (e.currentTarget as Element).setPointerCapture?.(e.pointerId);\n controller.pointerDown(local(e), toVectorPointerInput(e));\n }}\n onPointerMove={(e) => controller.pointerMove(local(e), toVectorPointerInput(e))}\n onPointerUp={(e) => {\n (e.currentTarget as Element).releasePointerCapture?.(e.pointerId);\n controller.pointerUp(local(e), toVectorPointerInput(e));\n }}\n onPointerCancel={() => controller.cancelDrag()}\n onPointerLeave={() => controller.pointerLeave()}\n onDoubleClick={(e) => controller.doubleClick(local(e))}\n onKeyDown={(e) => {\n if (isVectorTextTarget(e.target)) return;\n if (controller.keyDown(toVectorKeyInput(e))) e.preventDefault();\n }}\n onKeyUp={(e) => controller.keyUp(toVectorKeyInput(e))}\n onCopy={clipboard('copy')}\n onCut={clipboard('cut')}\n onPaste={clipboard('paste')}\n >\n {checkerboard && (\n <defs>\n <pattern id={`ve${uid}-checker`} width={16} height={16} patternUnits=\"userSpaceOnUse\">\n <rect width={16} height={16} fill=\"#ffffff\" />\n <rect width={8} height={8} fill=\"#e5e7eb\" />\n <rect x={8} y={8} width={8} height={8} fill=\"#e5e7eb\" />\n </pattern>\n </defs>\n )}\n <VectorGradientDefs defs={scene.defs} />\n <rect\n data-vector-artboard=\"\"\n x={overlay.artboard.x}\n y={overlay.artboard.y}\n width={overlay.artboard.width}\n height={overlay.artboard.height}\n fill={scene.background ?? (checkerboard ? `url(#ve${uid}-checker)` : '#ffffff')}\n stroke=\"rgba(0,0,0,0.12)\"\n />\n <g data-vector-scene=\"\" transform={scene.transform}>\n <VectorSceneNodes nodes={scene.nodes} />\n </g>\n <g data-vector-overlay=\"\" pointerEvents=\"none\" fill=\"none\">\n {overlay.outlines.map((o) => (\n <path key={o.id} d={o.d} stroke={accentColor} strokeWidth={o.selected ? 1 : 1.5} opacity={o.selected ? 1 : 0.7} />\n ))}\n {overlay.penPreview && <path d={overlay.penPreview} stroke={accentColor} strokeDasharray=\"4 3\" />}\n {box && (\n <g data-vector-selection=\"\" transform={box.transform || undefined}>\n <rect x={box.x} y={box.y} width={box.width} height={box.height} stroke={accentColor} />\n <line x1={box.x + box.width / 2} y1={box.y} x2={box.x + box.width / 2} y2={box.y - 24} stroke={accentColor} />\n {box.handles.map((h) =>\n h.handle === 'rotate' ? (\n <circle key={h.handle} data-handle={h.handle} cx={h.x} cy={h.y} r={hs / 2 + 1} fill={THEME.handleFill} stroke={accentColor} />\n ) : (\n <rect key={h.handle} data-handle={h.handle} x={h.x - hs / 2} y={h.y - hs / 2} width={hs} height={hs} fill={THEME.handleFill} stroke={accentColor} />\n ),\n )}\n </g>\n )}\n {overlay.handles.map((h) => (\n <g key={`${h.ref.nodeId}:${h.ref.subpath}:${h.ref.index}:${h.ref.handle}`} data-vector-handle={h.ref.handle}>\n <line x1={h.anchorX} y1={h.anchorY} x2={h.x} y2={h.y} stroke={accentColor} />\n <circle cx={h.x} cy={h.y} r={THEME.handleRadius + (h.hovered ? 1 : 0)} fill={THEME.handleFill} stroke={accentColor} />\n </g>\n ))}\n {overlay.anchors.map((a) => {\n const size = as + (a.hovered ? 2 : 0);\n const fill = a.selected ? accentColor : THEME.handleFill;\n const key = `${a.ref.nodeId}:${a.ref.subpath}:${a.ref.index}`;\n return a.type === 'corner' ? (\n <rect key={key} data-vector-anchor={a.ref.index} x={a.x - size / 2} y={a.y - size / 2} width={size} height={size} fill={fill} stroke={accentColor} />\n ) : (\n <circle key={key} data-vector-anchor={a.ref.index} cx={a.x} cy={a.y} r={size / 2} fill={fill} stroke={accentColor} />\n );\n })}\n {overlay.cornerWidgets.map((w) => (\n <g key={`corner:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`} data-vector-corner-widget={w.ref.index} data-corner-kind={w.kind}>\n <circle cx={w.x} cy={w.y} r={THEME.cornerWidgetRadius + (w.hovered ? 1 : 0)} fill={THEME.handleFill} stroke={accentColor} />\n <circle cx={w.x} cy={w.y} r={1.5} fill={accentColor} />\n </g>\n ))}\n {overlay.widthSpot && (\n <g data-vector-width-spot=\"\">\n <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\" />\n <path d={vectorDiamondPath(overlay.widthSpot.x, overlay.widthSpot.y)} fill=\"none\" stroke={accentColor} />\n </g>\n )}\n {overlay.widthPoints.map((w) => (\n <g key={`width:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`} data-vector-width-point={w.ref.index} data-selected={w.selected || undefined}>\n <line x1={w.left.x} y1={w.left.y} x2={w.right.x} y2={w.right.y} stroke={accentColor} />\n <path d={vectorDiamondPath(w.x, w.y)} fill={w.selected || w.active ? accentColor : THEME.handleFill} stroke={accentColor} strokeWidth={w.hovered === 'center' ? 2 : 1} />\n {(['left', 'right'] as const).map((side) => (\n <circle key={side} data-vector-width-side={side} cx={w[side].x} cy={w[side].y} r={THEME.handleRadius + (w.hovered === side ? 1 : 0)} fill={THEME.handleFill} stroke={accentColor} />\n ))}\n </g>\n ))}\n {state.tool === 'pen' && overlay.anchors.some((a) => a.closes && a.hovered) && (\n <circle cx={overlay.anchors.find((a) => a.closes)!.x} cy={overlay.anchors.find((a) => a.closes)!.y} r={as} stroke={accentColor} />\n )}\n {overlay.builder && (\n <g data-vector-builder={overlay.builder.mode}>\n {overlay.builder.faces.map((d, i) => (\n <path\n key={`f${i}`}\n data-vector-builder-face=\"\"\n d={d}\n fill={overlay.builder!.mode === 'erase' ? THEME.builderEraseFill : THEME.builderFill}\n fillRule=\"nonzero\"\n stroke={overlay.builder!.mode === 'erase' ? THEME.builderErase : accentColor}\n strokeWidth={1}\n />\n ))}\n {overlay.builder.lines.map((d, i) => (\n <path key={`l${i}`} data-vector-builder-line=\"\" d={d} fill=\"none\" stroke={THEME.builderErase} strokeWidth={3} strokeLinecap=\"round\" />\n ))}\n {overlay.builder.trail && <path data-vector-builder-trail=\"\" d={overlay.builder.trail} fill=\"none\" stroke={overlay.builder.mode === 'erase' ? THEME.builderErase : accentColor} strokeWidth={1} />}\n </g>\n )}\n {overlay.toolStroke && (\n <path\n data-vector-tool-stroke={overlay.toolStroke.tool}\n d={overlay.toolStroke.d}\n stroke={overlay.toolStroke.tool === 'eraser' ? THEME.eraserFill : accentColor}\n strokeWidth={overlay.toolStroke.tool === 'eraser' ? overlay.toolStroke.width : 1}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeDasharray={overlay.toolStroke.tool === 'knife' ? '5 3' : undefined}\n />\n )}\n {overlay.pencilString && (\n <line\n data-vector-pencil-string=\"\"\n x1={overlay.pencilString.x1}\n y1={overlay.pencilString.y1}\n x2={overlay.pencilString.x2}\n y2={overlay.pencilString.y2}\n stroke={accentColor}\n strokeDasharray=\"2 2\"\n />\n )}\n {overlay.cutPoint && <circle data-vector-cut-point=\"\" cx={overlay.cutPoint.x} cy={overlay.cutPoint.y} r={THEME.handleRadius + 1} fill={THEME.handleFill} stroke={accentColor} />}\n {overlay.marquee && (\n <rect\n data-vector-marquee=\"\"\n x={overlay.marquee.x}\n y={overlay.marquee.y}\n width={overlay.marquee.width}\n height={overlay.marquee.height}\n fill={THEME.marqueeFill}\n stroke={accentColor}\n strokeDasharray=\"3 2\"\n />\n )}\n {overlay.guides.lines.length > 0 && (\n <g data-vector-guides=\"\" stroke={guideColor}>\n {overlay.guides.lines.map((l, i) => (\n <line key={i} data-vector-guide={l.kind} x1={l.x1} y1={l.y1} x2={l.x2} y2={l.y2} strokeDasharray={l.kind === 'construction' ? '4 3' : undefined} />\n ))}\n </g>\n )}\n {overlay.guides.labels.map((l, i) => (\n <text\n key={i}\n data-vector-guide-label={l.kind}\n x={l.x + 6}\n y={l.y - 6}\n fontSize={10}\n fill={guideColor}\n stroke=\"#ffffff\"\n strokeWidth={3}\n paintOrder=\"stroke\"\n style={{ fontFamily: 'system-ui, sans-serif' }}\n >\n {l.text}\n </text>\n ))}\n {overlay.status && (\n <text data-vector-status=\"\" x={8} y=\"100%\" dy={-8} fontSize={11} fill={accentColor} style={{ fontFamily: 'system-ui, sans-serif' }}>\n {overlay.status}\n </text>\n )}\n </g>\n </svg>\n );\n}\n","import React from 'react';\nimport {\n VECTOR_TOOLS,\n VECTOR_TOOL_GLYPHS,\n VECTOR_TOOL_SHORTCUTS,\n VECTOR_EDIT_TOGGLES,\n VECTOR_PATH_ACTIONS,\n VECTOR_PATHFINDER_ACTIONS,\n VECTOR_FILL_GAP,\n VECTOR_ARROWHEADS,\n VECTOR_ARROWHEAD_LABELS,\n VECTOR_CORNER_KINDS,\n VECTOR_CORNER_KIND_LABELS,\n VECTOR_STROKE_ALIGN_LABELS,\n VECTOR_WIDTH_PRESETS,\n getVectorSelectionStyle,\n widthProfilePreset,\n widthProfilePresetId,\n vectorPaintToHex,\n vectorToolLabel,\n type VectorArrowhead,\n type VectorCornerKind,\n type VectorEditorController,\n type VectorStrokeAlign,\n type VectorTool,\n type VectorWidthPreset,\n} from '@pixerate/editor/vector';\nimport { useVectorEditorState } from './useVectorEditor';\n\nconst VECTOR_SNAP_TITLE = 'Snap to objects';\nconst modKeyLabel = () => (typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform ?? '') ? '⌘' : 'Ctrl');\n\nconst buttonClass =\n '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';\n\nexport interface VectorToolbarProps {\n controller: VectorEditorController;\n /** Tools to show (default: all). */\n tools?: readonly VectorTool[];\n /** Undo / redo buttons (default `true`). */\n showHistory?: boolean;\n /** Boolean, Pathfinder, group, arrange and align buttons (default `true`). */\n showArrange?: boolean;\n /** The snapping toggle (default `true`). */\n showSnap?: boolean;\n /**\n * Path editing: Join, Average, Cut at Points, Remove Redundant Points, Smooth, the Keep\n * Shape / Curvature / Shapes toggles, and the pencil smoothing and eraser size inputs while\n * those tools are active (default `true`).\n */\n showPathEdit?: boolean;\n className?: string;\n}\n\n/** Tool picker plus undo, snapping, boolean operations, grouping, stacking and alignment. */\nexport function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, showArrange = true, showSnap = true, showPathEdit = true, className }: VectorToolbarProps) {\n const state = useVectorEditorState(controller);\n const count = state.selection.length;\n const points = state.tool === 'direct' ? state.selectedAnchors.length : 0;\n const editing = state.editing;\n const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === 'group');\n const act = (label: string, title: string, run: () => unknown, disabled = false) => (\n <button key={label} type=\"button\" className={buttonClass} title={title} aria-label={title} disabled={disabled} onClick={() => void run()}>\n {label}\n </button>\n );\n return (\n <div role=\"toolbar\" aria-label=\"Vector tools\" className={`flex flex-wrap items-center gap-1 ${className ?? ''}`}>\n <div className=\"flex items-center gap-1\" role=\"group\" aria-label=\"Tools\">\n {tools.map((tool) => (\n <button\n key={tool}\n type=\"button\"\n data-vector-tool={tool}\n className={buttonClass}\n aria-pressed={state.tool === tool}\n title={`${vectorToolLabel(tool)} (${VECTOR_TOOL_SHORTCUTS[tool]})`}\n aria-label={vectorToolLabel(tool)}\n onClick={() => controller.setTool(tool)}\n >\n {VECTOR_TOOL_GLYPHS[tool]}\n </button>\n ))}\n </div>\n {showHistory && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"History\">\n {act('↶', state.canUndo ? `Undo ${state.undoLabel}` : 'Undo', () => controller.undo(), !state.canUndo)}\n {act('↷', state.canRedo ? `Redo ${state.redoLabel}` : 'Redo', () => controller.redo(), !state.canRedo)}\n </div>\n )}\n {showSnap && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Snapping\">\n <button\n type=\"button\"\n data-vector-snap=\"\"\n className={buttonClass}\n aria-pressed={state.snap.objects}\n title={`${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`}\n aria-label={VECTOR_SNAP_TITLE}\n onClick={() => controller.toggleSnapping()}\n >\n Snap\n </button>\n </div>\n )}\n {showPathEdit && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Path editing\">\n {VECTOR_PATH_ACTIONS.map((a) => (\n <button\n key={a.id}\n type=\"button\"\n data-vector-path-action={a.id}\n className={buttonClass}\n title={a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title}\n aria-label={a.title}\n disabled={!a.enabled(count, points)}\n onClick={() => void a.run(controller)}\n >\n {a.label}\n </button>\n ))}\n {VECTOR_EDIT_TOGGLES.map((t) => (\n <button\n key={t.key}\n type=\"button\"\n data-vector-edit={t.key}\n className={buttonClass}\n aria-pressed={editing[t.key]}\n title={t.title}\n aria-label={t.title}\n onClick={() => controller.setEditing({ [t.key]: !editing[t.key] })}\n >\n {t.label}\n </button>\n ))}\n {state.tool === 'pencil' && (\n <label className=\"flex items-center gap-1 text-xs text-foreground\">\n Smoothing\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.05}\n aria-label=\"Pencil smoothing\"\n className=\"h-4 w-20 accent-primary\"\n value={editing.pencilSmoothing}\n onChange={(e) => controller.setEditing({ pencilSmoothing: parseFloat(e.target.value) })}\n />\n </label>\n )}\n {state.tool === 'eraser' && (\n <label className=\"flex items-center gap-1 text-xs text-foreground\">\n Size\n <input\n type=\"number\"\n min={0.5}\n step={1}\n aria-label=\"Eraser size\"\n className=\"h-7 w-16 rounded border border-border bg-background px-1.5 text-xs\"\n value={editing.eraserSize}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n > 0) controller.setEditing({ eraserSize: n });\n }}\n />\n </label>\n )}\n {state.tool === 'paintBucket' && (\n <button\n type=\"button\"\n data-vector-fill-gap=\"\"\n className={buttonClass}\n aria-pressed={editing.fillGap > 0}\n title=\"Close small gaps between path ends when filling\"\n aria-label=\"Close gaps\"\n onClick={() => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : VECTOR_FILL_GAP })}\n >\n Gaps\n </button>\n )}\n </div>\n )}\n {showArrange && (\n <>\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Combine\">\n {act('∪', 'Union', () => controller.booleanOp('union'), count < 2)}\n {act('−', 'Subtract', () => controller.booleanOp('subtract'), count < 2)}\n {act('∩', 'Intersect', () => controller.booleanOp('intersect'), count < 2)}\n {act('⊻', 'Exclude', () => controller.booleanOp('exclude'), count < 2)}\n {act('G', 'Group', () => controller.group(), count < 1)}\n {act('U', 'Ungroup', () => controller.ungroup(), !groupSelected)}\n </div>\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Pathfinder\">\n {VECTOR_PATHFINDER_ACTIONS.map((a) => (\n <button\n key={a.id}\n type=\"button\"\n data-vector-pathfinder={a.id}\n className={buttonClass}\n title={a.title}\n aria-label={a.title}\n disabled={count < a.min}\n onClick={() => void controller.pathfinder(a.id)}\n >\n {a.label}\n </button>\n ))}\n </div>\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Arrange\">\n {act('⇈', 'Bring to Front', () => controller.arrange('front'), count < 1)}\n {act('⇊', 'Send to Back', () => controller.arrange('back'), count < 1)}\n {act('⇤', 'Align Left', () => controller.align('left'), count < 1)}\n {act('↔', 'Align Center', () => controller.align('center'), count < 1)}\n {act('⇥', 'Align Right', () => controller.align('right'), count < 1)}\n {act('⤒', 'Align Top', () => controller.align('top'), count < 1)}\n {act('↕', 'Align Middle', () => controller.align('middle'), count < 1)}\n {act('⤓', 'Align Bottom', () => controller.align('bottom'), count < 1)}\n </div>\n </>\n )}\n </div>\n );\n}\n\nexport interface VectorStylePanelProps {\n controller: VectorEditorController;\n className?: string;\n}\n\nconst selectClass = 'h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs';\nconst numberClass = 'h-7 w-16 rounded border border-border bg-background px-1.5 text-xs';\n\n/**\n * Fill, stroke, stroke width, alignment and width profile, arrowheads, live corner radius and opacity of the\n * selection (corners of the selected points with the direct tool); with nothing selected it\n * edits the defaults for new shapes.\n */\nexport function VectorStylePanel({ controller, className }: VectorStylePanelProps) {\n const state = useVectorEditorState(controller);\n const style = getVectorSelectionStyle(state);\n const d = state.defaults;\n const source = style ?? {\n fill: d.fill ?? null,\n stroke: d.stroke ?? null,\n strokeWidth: d.strokeWidth ?? 1,\n opacity: 1,\n strokeAlign: d.strokeAlign ?? 'center',\n startArrow: d.startArrow ?? null,\n endArrow: d.endArrow ?? null,\n arrowAlign: d.arrowAlign ?? 'extend',\n startArrowScale: d.startArrowScale ?? 1,\n endArrowScale: d.endArrowScale ?? 1,\n widthProfile: widthProfilePresetId(d.strokeWidthProfile),\n cornerRadius: d.cornerRadius,\n cornerKind: d.cornerKind ?? 'round',\n corners: 1,\n hasOpenPath: true,\n };\n const setCorners = (patch: { radius?: number; kind?: VectorCornerKind }) => {\n if (!style) controller.setDefaults({ ...(patch.radius !== undefined ? { cornerRadius: patch.radius } : {}), ...(patch.kind ? { cornerKind: patch.kind } : {}) });\n else if (patch.radius !== undefined) controller.setCornerRadius(patch.radius);\n else if (patch.kind) controller.setCornerKind(patch.kind);\n };\n const setProfile = (id: VectorWidthPreset) => {\n if (style) controller.setWidthProfile(id);\n else controller.setDefaults({ strokeWidthProfile: widthProfilePreset(id)?.length ? widthProfilePreset(id) : null });\n };\n const mixed = (key: keyof NonNullable<typeof style>['mixed']) => (style?.mixed[key] ? <span className=\"text-[11px] text-muted-foreground\">Mixed</span> : null);\n const arrowRow = (end: 'start' | 'end', label: string) => {\n const key = end === 'start' ? 'startArrow' : 'endArrow';\n const scaleKey = end === 'start' ? 'startArrowScale' : 'endArrowScale';\n return (\n <div className=\"flex items-center gap-2\" data-vector-style={key}>\n <span className=\"w-16 text-xs text-foreground\">{label}</span>\n <select aria-label={`${label} arrowhead`} className={selectClass} value={source[key] ?? ''} onChange={(e) => apply({ [key]: (e.target.value || null) as VectorArrowhead | null })}>\n <option value=\"\">None</option>\n {VECTOR_ARROWHEADS.map((h) => (\n <option key={h} value={h}>\n {VECTOR_ARROWHEAD_LABELS[h]}\n </option>\n ))}\n </select>\n <input\n type=\"number\"\n min={0.1}\n step={0.25}\n aria-label={`${label} arrowhead scale`}\n title=\"Scale (× stroke width)\"\n className={numberClass}\n value={source[scaleKey]}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n > 0) apply({ [scaleKey]: n });\n }}\n />\n </div>\n );\n };\n const apply = (patch: Record<string, unknown>) => {\n if (style) controller.setStyle(patch);\n else controller.setDefaults(patch);\n };\n const paintRow = (key: 'fill' | 'stroke', label: string) => {\n const paint = source[key];\n const hex = vectorPaintToHex(paint);\n const on = paint !== null && paint !== 'none';\n return (\n <div className=\"flex items-center gap-2\" data-vector-style={key}>\n <label className=\"flex w-16 items-center gap-1.5 text-xs text-foreground\">\n <input type=\"checkbox\" checked={on} aria-label={`${label} on`} onChange={(e) => apply({ [key]: e.target.checked ? (hex ?? '#000000') : null })} />\n {label}\n </label>\n <input\n type=\"color\"\n aria-label={`${label} colour`}\n className=\"h-7 w-10 cursor-pointer rounded border border-border bg-background disabled:opacity-40\"\n disabled={!on}\n value={hex ?? '#000000'}\n onChange={(e) => apply({ [key]: e.target.value })}\n />\n {on && !hex && <span className=\"truncate text-[11px] text-muted-foreground\">{typeof paint === 'string' ? paint : 'Gradient'}</span>}\n {style?.mixed[key] && <span className=\"text-[11px] text-muted-foreground\">Mixed</span>}\n </div>\n );\n };\n return (\n <div className={`space-y-2 ${className ?? ''}`} aria-label={style ? 'Selection style' : 'New shape style'}>\n <p className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">{style ? 'Selection' : 'New shapes'}</p>\n {paintRow('fill', 'Fill')}\n {paintRow('stroke', 'Stroke')}\n <label className=\"flex items-center gap-2 text-xs text-foreground\">\n <span className=\"w-16\">Width</span>\n <input\n type=\"number\"\n min={0}\n step={0.5}\n aria-label=\"Stroke width\"\n className=\"h-7 w-20 rounded border border-border bg-background px-1.5 text-xs\"\n value={source.strokeWidth}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n >= 0) apply({ strokeWidth: n });\n }}\n />\n </label>\n <label className=\"flex items-center gap-2 text-xs text-foreground\" data-vector-style=\"strokeAlign\">\n <span className=\"w-16\">Align</span>\n <select aria-label=\"Stroke alignment\" className={selectClass} value={source.strokeAlign} onChange={(e) => apply({ strokeAlign: e.target.value as VectorStrokeAlign })}>\n {(Object.keys(VECTOR_STROKE_ALIGN_LABELS) as VectorStrokeAlign[]).map((a) => (\n <option key={a} value={a}>\n {VECTOR_STROKE_ALIGN_LABELS[a]}\n </option>\n ))}\n </select>\n {mixed('strokeAlign')}\n </label>\n <div className=\"flex items-center gap-2 text-xs text-foreground\" data-vector-style=\"widthProfile\">\n <span className=\"w-16\">Profile</span>\n <select\n aria-label=\"Width profile\"\n className={selectClass}\n value={source.widthProfile}\n onChange={(e) => {\n if (e.target.value !== 'custom') setProfile(e.target.value as VectorWidthPreset);\n }}\n >\n {VECTOR_WIDTH_PRESETS.map((p) => (\n <option key={p.id} value={p.id}>\n {p.label}\n </option>\n ))}\n {source.widthProfile === 'custom' && (\n <option value=\"custom\" disabled>\n Custom\n </option>\n )}\n </select>\n <button\n type=\"button\"\n className={buttonClass}\n title=\"Reset to uniform width\"\n aria-label=\"Reset to uniform width\"\n disabled={source.widthProfile === 'uniform' && !style?.mixed.widthProfile}\n onClick={() => setProfile('uniform')}\n >\n ═\n </button>\n {mixed('widthProfile')}\n </div>\n {source.hasOpenPath && (\n <>\n {arrowRow('start', 'Start')}\n {arrowRow('end', 'End')}\n {(source.startArrow || source.endArrow) && (\n <label className=\"flex items-center gap-2 text-xs text-foreground\" data-vector-style=\"arrowAlign\">\n <span className=\"w-16\">Heads</span>\n <select aria-label=\"Arrowhead alignment\" className={selectClass} value={source.arrowAlign} onChange={(e) => apply({ arrowAlign: e.target.value })}>\n <option value=\"extend\">Tip past end</option>\n <option value=\"tip\">Tip at end</option>\n </select>\n </label>\n )}\n </>\n )}\n {source.corners > 0 && (\n <div className=\"flex items-center gap-2\" data-vector-style=\"corners\">\n <span className=\"w-16 text-xs text-foreground\">Corners</span>\n <input\n type=\"number\"\n min={0}\n step={1}\n aria-label=\"Corner radius\"\n className={numberClass}\n value={Math.round(source.cornerRadius * 100) / 100}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n >= 0) setCorners({ radius: n });\n }}\n />\n <select aria-label=\"Corner kind\" className={selectClass} value={source.cornerKind} onChange={(e) => setCorners({ kind: e.target.value as VectorCornerKind })}>\n {VECTOR_CORNER_KINDS.map((k) => (\n <option key={k} value={k}>\n {VECTOR_CORNER_KIND_LABELS[k]}\n </option>\n ))}\n </select>\n {mixed('cornerRadius')}\n </div>\n )}\n {style && (\n <label className=\"flex items-center gap-2 text-xs text-foreground\">\n <span className=\"w-16\">Opacity</span>\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.05}\n aria-label=\"Opacity\"\n className=\"h-4 flex-1 accent-primary\"\n value={source.opacity}\n onChange={(e) => apply({ opacity: parseFloat(e.target.value) })}\n />\n </label>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport type { VectorEditorController, VectorTool } from '@pixerate/editor/vector';\nimport { VectorCanvas, type VectorCanvasProps } from './VectorCanvas';\nimport { VectorStylePanel, VectorToolbar } from './VectorToolbar';\n\nexport interface VectorEditorProps {\n controller: VectorEditorController;\n /** Tools in the toolbar (default: all). */\n tools?: readonly VectorTool[];\n /** The style sidebar (default `true`). */\n showStylePanel?: boolean;\n /** Canvas height (default 520px). */\n height?: number | string;\n canvasProps?: Omit<VectorCanvasProps, 'controller'>;\n className?: string;\n}\n\n/** Toolbar, canvas and style panel for a `VectorEditorController`. */\nexport function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }: VectorEditorProps) {\n return (\n <div className={`flex flex-col gap-2 ${className ?? ''}`} data-vector-editor=\"\">\n <VectorToolbar controller={controller} tools={tools} />\n <div className=\"flex min-h-0 flex-col gap-2 md:flex-row\">\n <div className=\"relative min-h-[320px] flex-1 overflow-hidden rounded-md border border-border bg-muted/40\" style={{ height }}>\n <VectorCanvas controller={controller} {...canvasProps} />\n </div>\n {showStylePanel && <VectorStylePanel controller={controller} className=\"w-full shrink-0 rounded-md border border-border p-3 md:w-56\" />}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["import_react","import_vector","THEME","text","import_vector","import_jsx_runtime","import_jsx_runtime"]}
@@ -64,7 +64,7 @@ interface VectorToolbarProps {
64
64
  tools?: readonly VectorTool[];
65
65
  /** Undo / redo buttons (default `true`). */
66
66
  showHistory?: boolean;
67
- /** Boolean, group, arrange and align buttons (default `true`). */
67
+ /** Boolean, Pathfinder, group, arrange and align buttons (default `true`). */
68
68
  showArrange?: boolean;
69
69
  /** The snapping toggle (default `true`). */
70
70
  showSnap?: boolean;
@@ -83,7 +83,7 @@ interface VectorStylePanelProps {
83
83
  className?: string;
84
84
  }
85
85
  /**
86
- * Fill, stroke, stroke width and alignment, arrowheads, live corner radius and opacity of the
86
+ * Fill, stroke, stroke width, alignment and width profile, arrowheads, live corner radius and opacity of the
87
87
  * selection (corners of the selected points with the direct tool); with nothing selected it
88
88
  * edits the defaults for new shapes.
89
89
  */
@@ -64,7 +64,7 @@ interface VectorToolbarProps {
64
64
  tools?: readonly VectorTool[];
65
65
  /** Undo / redo buttons (default `true`). */
66
66
  showHistory?: boolean;
67
- /** Boolean, group, arrange and align buttons (default `true`). */
67
+ /** Boolean, Pathfinder, group, arrange and align buttons (default `true`). */
68
68
  showArrange?: boolean;
69
69
  /** The snapping toggle (default `true`). */
70
70
  showSnap?: boolean;
@@ -83,7 +83,7 @@ interface VectorStylePanelProps {
83
83
  className?: string;
84
84
  }
85
85
  /**
86
- * Fill, stroke, stroke width and alignment, arrowheads, live corner radius and opacity of the
86
+ * Fill, stroke, stroke width, alignment and width profile, arrowheads, live corner radius and opacity of the
87
87
  * selection (corners of the selected points with the direct tool); with nothing selected it
88
88
  * edits the defaults for new shapes.
89
89
  */
@@ -51,7 +51,8 @@ import {
51
51
  getVectorSceneRenderData,
52
52
  isVectorTextTarget,
53
53
  toVectorKeyInput,
54
- toVectorPointerInput
54
+ toVectorPointerInput,
55
+ vectorDiamondPath
55
56
  } from "@pixerate/editor/vector";
56
57
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
57
58
  function VectorGradientDefs({ defs }) {
@@ -92,7 +93,19 @@ function VectorPartedPath({ node }) {
92
93
  /* @__PURE__ */ jsx("path", { d: node.d, fill: "#000", fillRule: node.fillRule })
93
94
  ] }) }),
94
95
  /* @__PURE__ */ jsx("path", { "data-vector-part": "fill", d: node.d, fill: node.fill, fillRule: node.fillRule, stroke: "none" }),
95
- /* @__PURE__ */ jsx(
96
+ sp.outline !== void 0 ? (
97
+ // A variable-width stroke: its outline, filled.
98
+ /* @__PURE__ */ jsx(
99
+ "path",
100
+ {
101
+ "data-vector-part": "stroke-outline",
102
+ d: sp.outline,
103
+ fill: node.stroke,
104
+ clipPath: clip?.kind === "clip" ? `url(#${clip.id})` : void 0,
105
+ mask: clip?.kind === "mask" ? `url(#${clip.id})` : void 0
106
+ }
107
+ )
108
+ ) : /* @__PURE__ */ jsx(
96
109
  "path",
97
110
  {
98
111
  "data-vector-part": "stroke",
@@ -248,7 +261,32 @@ function VectorCanvas({
248
261
  /* @__PURE__ */ jsx("circle", { cx: w.x, cy: w.y, r: THEME.cornerWidgetRadius + (w.hovered ? 1 : 0), fill: THEME.handleFill, stroke: accentColor }),
249
262
  /* @__PURE__ */ jsx("circle", { cx: w.x, cy: w.y, r: 1.5, fill: accentColor })
250
263
  ] }, `corner:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`)),
264
+ overlay.widthSpot && /* @__PURE__ */ jsxs("g", { "data-vector-width-spot": "", children: [
265
+ /* @__PURE__ */ 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" }),
266
+ /* @__PURE__ */ jsx("path", { d: vectorDiamondPath(overlay.widthSpot.x, overlay.widthSpot.y), fill: "none", stroke: accentColor })
267
+ ] }),
268
+ overlay.widthPoints.map((w) => /* @__PURE__ */ jsxs("g", { "data-vector-width-point": w.ref.index, "data-selected": w.selected || void 0, children: [
269
+ /* @__PURE__ */ jsx("line", { x1: w.left.x, y1: w.left.y, x2: w.right.x, y2: w.right.y, stroke: accentColor }),
270
+ /* @__PURE__ */ jsx("path", { d: vectorDiamondPath(w.x, w.y), fill: w.selected || w.active ? accentColor : THEME.handleFill, stroke: accentColor, strokeWidth: w.hovered === "center" ? 2 : 1 }),
271
+ ["left", "right"].map((side) => /* @__PURE__ */ jsx("circle", { "data-vector-width-side": side, cx: w[side].x, cy: w[side].y, r: THEME.handleRadius + (w.hovered === side ? 1 : 0), fill: THEME.handleFill, stroke: accentColor }, side))
272
+ ] }, `width:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`)),
251
273
  state.tool === "pen" && overlay.anchors.some((a) => a.closes && a.hovered) && /* @__PURE__ */ jsx("circle", { cx: overlay.anchors.find((a) => a.closes).x, cy: overlay.anchors.find((a) => a.closes).y, r: as, stroke: accentColor }),
274
+ overlay.builder && /* @__PURE__ */ jsxs("g", { "data-vector-builder": overlay.builder.mode, children: [
275
+ overlay.builder.faces.map((d, i) => /* @__PURE__ */ jsx(
276
+ "path",
277
+ {
278
+ "data-vector-builder-face": "",
279
+ d,
280
+ fill: overlay.builder.mode === "erase" ? THEME.builderEraseFill : THEME.builderFill,
281
+ fillRule: "nonzero",
282
+ stroke: overlay.builder.mode === "erase" ? THEME.builderErase : accentColor,
283
+ strokeWidth: 1
284
+ },
285
+ `f${i}`
286
+ )),
287
+ overlay.builder.lines.map((d, i) => /* @__PURE__ */ jsx("path", { "data-vector-builder-line": "", d, fill: "none", stroke: THEME.builderErase, strokeWidth: 3, strokeLinecap: "round" }, `l${i}`)),
288
+ overlay.builder.trail && /* @__PURE__ */ jsx("path", { "data-vector-builder-trail": "", d: overlay.builder.trail, fill: "none", stroke: overlay.builder.mode === "erase" ? THEME.builderErase : accentColor, strokeWidth: 1 })
289
+ ] }),
252
290
  overlay.toolStroke && /* @__PURE__ */ jsx(
253
291
  "path",
254
292
  {
@@ -318,12 +356,17 @@ import {
318
356
  VECTOR_TOOL_SHORTCUTS,
319
357
  VECTOR_EDIT_TOGGLES,
320
358
  VECTOR_PATH_ACTIONS,
359
+ VECTOR_PATHFINDER_ACTIONS,
360
+ VECTOR_FILL_GAP,
321
361
  VECTOR_ARROWHEADS,
322
362
  VECTOR_ARROWHEAD_LABELS,
323
363
  VECTOR_CORNER_KINDS,
324
364
  VECTOR_CORNER_KIND_LABELS,
325
365
  VECTOR_STROKE_ALIGN_LABELS,
366
+ VECTOR_WIDTH_PRESETS,
326
367
  getVectorSelectionStyle,
368
+ widthProfilePreset,
369
+ widthProfilePresetId,
327
370
  vectorPaintToHex,
328
371
  vectorToolLabel
329
372
  } from "@pixerate/editor/vector";
@@ -432,7 +475,20 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
432
475
  }
433
476
  }
434
477
  )
435
- ] })
478
+ ] }),
479
+ state.tool === "paintBucket" && /* @__PURE__ */ jsx2(
480
+ "button",
481
+ {
482
+ type: "button",
483
+ "data-vector-fill-gap": "",
484
+ className: buttonClass,
485
+ "aria-pressed": editing.fillGap > 0,
486
+ title: "Close small gaps between path ends when filling",
487
+ "aria-label": "Close gaps",
488
+ onClick: () => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : VECTOR_FILL_GAP }),
489
+ children: "Gaps"
490
+ }
491
+ )
436
492
  ] }),
437
493
  showArrange && /* @__PURE__ */ jsxs2(Fragment2, { children: [
438
494
  /* @__PURE__ */ jsxs2("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Combine", children: [
@@ -443,6 +499,20 @@ function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, s
443
499
  act("G", "Group", () => controller.group(), count < 1),
444
500
  act("U", "Ungroup", () => controller.ungroup(), !groupSelected)
445
501
  ] }),
502
+ /* @__PURE__ */ jsx2("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Pathfinder", children: VECTOR_PATHFINDER_ACTIONS.map((a) => /* @__PURE__ */ jsx2(
503
+ "button",
504
+ {
505
+ type: "button",
506
+ "data-vector-pathfinder": a.id,
507
+ className: buttonClass,
508
+ title: a.title,
509
+ "aria-label": a.title,
510
+ disabled: count < a.min,
511
+ onClick: () => void controller.pathfinder(a.id),
512
+ children: a.label
513
+ },
514
+ a.id
515
+ )) }),
446
516
  /* @__PURE__ */ jsxs2("div", { className: "ml-1 flex items-center gap-1", role: "group", "aria-label": "Arrange", children: [
447
517
  act("\u21C8", "Bring to Front", () => controller.arrange("front"), count < 1),
448
518
  act("\u21CA", "Send to Back", () => controller.arrange("back"), count < 1),
@@ -473,6 +543,7 @@ function VectorStylePanel({ controller, className }) {
473
543
  arrowAlign: d.arrowAlign ?? "extend",
474
544
  startArrowScale: d.startArrowScale ?? 1,
475
545
  endArrowScale: d.endArrowScale ?? 1,
546
+ widthProfile: widthProfilePresetId(d.strokeWidthProfile),
476
547
  cornerRadius: d.cornerRadius,
477
548
  cornerKind: d.cornerKind ?? "round",
478
549
  corners: 1,
@@ -483,6 +554,10 @@ function VectorStylePanel({ controller, className }) {
483
554
  else if (patch.radius !== void 0) controller.setCornerRadius(patch.radius);
484
555
  else if (patch.kind) controller.setCornerKind(patch.kind);
485
556
  };
557
+ const setProfile = (id) => {
558
+ if (style) controller.setWidthProfile(id);
559
+ else controller.setDefaults({ strokeWidthProfile: widthProfilePreset(id)?.length ? widthProfilePreset(id) : null });
560
+ };
486
561
  const mixed = (key) => style?.mixed[key] ? /* @__PURE__ */ jsx2("span", { className: "text-[11px] text-muted-foreground", children: "Mixed" }) : null;
487
562
  const arrowRow = (end, label) => {
488
563
  const key = end === "start" ? "startArrow" : "endArrow";
@@ -566,6 +641,37 @@ function VectorStylePanel({ controller, className }) {
566
641
  /* @__PURE__ */ jsx2("select", { "aria-label": "Stroke alignment", className: selectClass, value: source.strokeAlign, onChange: (e) => apply({ strokeAlign: e.target.value }), children: Object.keys(VECTOR_STROKE_ALIGN_LABELS).map((a) => /* @__PURE__ */ jsx2("option", { value: a, children: VECTOR_STROKE_ALIGN_LABELS[a] }, a)) }),
567
642
  mixed("strokeAlign")
568
643
  ] }),
644
+ /* @__PURE__ */ jsxs2("div", { className: "flex items-center gap-2 text-xs text-foreground", "data-vector-style": "widthProfile", children: [
645
+ /* @__PURE__ */ jsx2("span", { className: "w-16", children: "Profile" }),
646
+ /* @__PURE__ */ jsxs2(
647
+ "select",
648
+ {
649
+ "aria-label": "Width profile",
650
+ className: selectClass,
651
+ value: source.widthProfile,
652
+ onChange: (e) => {
653
+ if (e.target.value !== "custom") setProfile(e.target.value);
654
+ },
655
+ children: [
656
+ VECTOR_WIDTH_PRESETS.map((p) => /* @__PURE__ */ jsx2("option", { value: p.id, children: p.label }, p.id)),
657
+ source.widthProfile === "custom" && /* @__PURE__ */ jsx2("option", { value: "custom", disabled: true, children: "Custom" })
658
+ ]
659
+ }
660
+ ),
661
+ /* @__PURE__ */ jsx2(
662
+ "button",
663
+ {
664
+ type: "button",
665
+ className: buttonClass,
666
+ title: "Reset to uniform width",
667
+ "aria-label": "Reset to uniform width",
668
+ disabled: source.widthProfile === "uniform" && !style?.mixed.widthProfile,
669
+ onClick: () => setProfile("uniform"),
670
+ children: "\u2550"
671
+ }
672
+ ),
673
+ mixed("widthProfile")
674
+ ] }),
569
675
  source.hasOpenPath && /* @__PURE__ */ jsxs2(Fragment2, { children: [
570
676
  arrowRow("start", "Start"),
571
677
  arrowRow("end", "End"),
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/vector/useVectorEditor.ts","../../src/vector/VectorCanvas.tsx","../../src/vector/VectorToolbar.tsx","../../src/vector/VectorEditor.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n VectorEditorController,\n createVectorCommands,\n type VectorCommandOptions,\n type VectorEditorOptions,\n type VectorEditorState,\n type VectorTool,\n} from '@pixerate/editor/vector';\n\n/** A `VectorEditorController` created once for the component's lifetime (destroyed on unmount). */\nexport function useVectorEditorController(options: VectorEditorOptions = {}): VectorEditorController {\n const ref = useRef<VectorEditorController | null>(null);\n if (!ref.current) ref.current = new VectorEditorController(options);\n const controller = ref.current;\n useEffect(() => () => controller.destroy(), [controller]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change). */\nexport function useVectorEditorState(controller: VectorEditorController): VectorEditorState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseVectorEditorResult {\n controller: VectorEditorController;\n state: VectorEditorState;\n setTool: (tool: VectorTool) => void;\n undo: () => void;\n redo: () => void;\n deleteSelection: () => void;\n toSvg: () => string;\n}\n\n/**\n * Subscribes to a vector editor controller and exposes its state with bound actions. Pass\n * options instead of a controller to create one for the component's lifetime.\n */\nexport function useVectorEditor(controllerOrOptions: VectorEditorController | VectorEditorOptions = {}): UseVectorEditorResult {\n const own = useRef<VectorEditorController | null>(null);\n let controller: VectorEditorController;\n if (controllerOrOptions instanceof VectorEditorController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new VectorEditorController(controllerOrOptions);\n controller = own.current;\n }\n const state = useVectorEditorState(controller);\n const actions = useMemo(\n () => ({\n setTool: (tool: VectorTool) => controller.setTool(tool),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n deleteSelection: () => void controller.deleteSelection(),\n toSvg: () => controller.toSvg(),\n }),\n [controller],\n );\n return { controller, state, ...actions };\n}\n\n/** Anything with `register(specs) → unregister` (a `CommandRegistry`). */\nexport interface VectorCommandTarget {\n register(specs: any): () => void;\n}\n\n/**\n * Registers the controller's palette / agent commands (`vector.addShape`, `vector.boolean`, …)\n * in `registry` while mounted, so `createCommandToolProvider` exposes them to agents.\n */\nexport function useVectorCommands(\n registry: VectorCommandTarget | null | undefined,\n controller: VectorEditorController,\n options: VectorCommandOptions = {},\n): void {\n const { prefix, group, scope } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createVectorCommands(controller, { prefix, group, scope }));\n }, [registry, controller, prefix, group, scope]);\n}\n","import React, { useEffect, useId, useRef } from 'react';\nimport {\n VECTOR_OVERLAY_THEME as THEME,\n getVectorOverlayRenderData,\n getVectorSceneRenderData,\n isVectorTextTarget,\n toVectorKeyInput,\n toVectorPointerInput,\n type VectorEditorController,\n type VectorRenderNode,\n type VectorRenderPath,\n type SvgGradientDef,\n} from '@pixerate/editor/vector';\nimport { useVectorEditorState } from './useVectorEditor';\n\nexport interface VectorCanvasProps {\n controller: VectorEditorController;\n /** Fit the artboard into the canvas when it first gets a size (default `true`). */\n fitOnMount?: boolean;\n /** Draw a checkerboard behind a transparent artboard (default `true`). */\n checkerboard?: boolean;\n /** Overlay accent colour (default sky blue). */\n accentColor?: string;\n /** Smart guide colour (default magenta). */\n guideColor?: string;\n className?: string;\n style?: React.CSSProperties;\n /** Accessible label (default \"Vector canvas\"). */\n 'aria-label'?: string;\n}\n\n/** Renders `<linearGradient>` / `<radialGradient>` descriptors. */\nexport function VectorGradientDefs({ defs }: { defs: readonly SvgGradientDef[] }) {\n if (!defs.length) return null;\n return (\n <defs>\n {defs.map((def) => {\n const stops = def.stops.map((s, i) => <stop key={i} offset={s.offset} stopColor={s.stopColor} stopOpacity={s.stopOpacity} />);\n return def.type === 'radial' ? (\n <radialGradient key={def.id} id={def.id} {...(def.attrs as any)}>\n {stops}\n </radialGradient>\n ) : (\n <linearGradient key={def.id} id={def.id} {...(def.attrs as any)}>\n {stops}\n </linearGradient>\n );\n })}\n </defs>\n );\n}\n\n/** Renders scene nodes (paths and groups) from `getVectorSceneRenderData`. */\nexport function VectorSceneNodes({ nodes }: { nodes: readonly VectorRenderNode[] }) {\n return (\n <>\n {nodes.map((node) =>\n node.kind === 'group' ? (\n <g key={node.id} data-vector-id={node.id} transform={node.transform} opacity={node.opacity < 1 ? node.opacity : undefined}>\n <VectorSceneNodes nodes={node.children} />\n </g>\n ) : node.strokeParts ? (\n <VectorPartedPath key={node.id} node={node} />\n ) : (\n <path\n key={node.id}\n data-vector-id={node.id}\n transform={node.transform}\n d={node.d}\n fill={node.fill}\n fillRule={node.fillRule}\n stroke={node.stroke}\n strokeWidth={node.stroke === 'none' ? undefined : node.strokeWidth}\n strokeLinecap={node.strokeLinecap as any}\n strokeLinejoin={node.strokeLinejoin as any}\n strokeDasharray={node.strokeDasharray}\n opacity={node.opacity < 1 ? node.opacity : undefined}\n />\n ),\n )}\n </>\n );\n}\n\n/** A path whose stroke is aligned inside / outside (double width, clipped or masked by the shape) or has arrowheads. */\nfunction VectorPartedPath({ node }: { node: VectorRenderPath }) {\n const sp = node.strokeParts!;\n const clip = sp.clip;\n const b = clip?.bounds;\n return (\n <g data-vector-id={node.id} data-vector-stroke-align={sp.align} transform={node.transform} opacity={node.opacity < 1 ? node.opacity : undefined}>\n {clip && b && (\n <defs>\n {clip.kind === 'clip' ? (\n <clipPath id={clip.id}>\n <path d={node.d} clipRule={node.fillRule} />\n </clipPath>\n ) : (\n <mask id={clip.id} maskUnits=\"userSpaceOnUse\" x={b.x} y={b.y} width={b.width} height={b.height}>\n <rect x={b.x} y={b.y} width={b.width} height={b.height} fill=\"#fff\" />\n <path d={node.d} fill=\"#000\" fillRule={node.fillRule} />\n </mask>\n )}\n </defs>\n )}\n <path data-vector-part=\"fill\" d={node.d} fill={node.fill} fillRule={node.fillRule} stroke=\"none\" />\n <path\n data-vector-part=\"stroke\"\n d={sp.d}\n fill=\"none\"\n stroke={node.stroke}\n strokeWidth={sp.width}\n strokeLinecap={node.strokeLinecap as any}\n strokeLinejoin={node.strokeLinejoin as any}\n strokeDasharray={node.strokeDasharray}\n clipPath={clip?.kind === 'clip' ? `url(#${clip.id})` : undefined}\n mask={clip?.kind === 'mask' ? `url(#${clip.id})` : undefined}\n />\n {sp.heads.map((head, i) => (\n <path key={i} data-vector-part=\"head\" d={head} fill={node.stroke} />\n ))}\n </g>\n );\n}\n\n/**\n * An SVG canvas for a `VectorEditorController`: draws the document and the editing overlay\n * and forwards pointer, wheel, keyboard and clipboard events. Focus it to use shortcuts.\n */\nexport function VectorCanvas({\n controller,\n fitOnMount = true,\n checkerboard = true,\n accentColor = THEME.accent,\n guideColor = THEME.guide,\n className,\n style,\n 'aria-label': ariaLabel = 'Vector canvas',\n}: VectorCanvasProps) {\n const state = useVectorEditorState(controller);\n const svgRef = useRef<SVGSVGElement | null>(null);\n const fitted = useRef(!fitOnMount);\n const uid = useId().replace(/:/g, '');\n const scene = getVectorSceneRenderData(state, { idPrefix: `ve${uid}-` });\n const overlay = getVectorOverlayRenderData(state);\n\n useEffect(() => {\n const el = svgRef.current;\n if (!el || fitted.current) return;\n const fit = () => {\n const rect = el.getBoundingClientRect();\n if (fitted.current || rect.width <= 0 || rect.height <= 0) return;\n fitted.current = true;\n controller.zoomToFit({ width: rect.width, height: rect.height });\n };\n fit();\n if (fitted.current || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(fit);\n observer.observe(el);\n return () => observer.disconnect();\n }, [controller]);\n\n // Wheel needs a non-passive listener to stop page scroll / browser zoom.\n useEffect(() => {\n const el = svgRef.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n controller.wheel(local(e), { x: e.deltaX, y: e.deltaY }, toVectorPointerInput(e));\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [controller]);\n\n const local = (e: { clientX: number; clientY: number }) => {\n const rect = svgRef.current?.getBoundingClientRect();\n return { x: e.clientX - (rect?.left ?? 0), y: e.clientY - (rect?.top ?? 0) };\n };\n\n const clipboard = (kind: 'copy' | 'cut' | 'paste') => (event: React.ClipboardEvent) => {\n const native = (event && 'nativeEvent' in event ? event.nativeEvent : event) as ClipboardEvent;\n const data = native?.clipboardData;\n if (kind === 'paste') {\n const text = data?.getData('text/plain') ?? '';\n const pasted = text ? controller.paste(text) : controller.paste();\n if (pasted.length) event.preventDefault?.();\n return;\n }\n const text = kind === 'cut' ? controller.cut() : controller.copy();\n if (text && data) {\n data.setData('text/plain', text);\n event.preventDefault?.();\n }\n };\n\n const hs = THEME.transformHandleSize;\n const as = THEME.anchorSize;\n const box = overlay.selectionBox;\n\n return (\n <svg\n ref={svgRef}\n role=\"application\"\n aria-label={ariaLabel}\n tabIndex={0}\n data-tool={state.tool}\n className={className}\n style={{ display: 'block', width: '100%', height: '100%', outline: 'none', touchAction: 'none', userSelect: 'none', cursor: state.cursor, ...style }}\n onPointerDown={(e) => {\n svgRef.current?.focus({ preventScroll: true });\n (e.currentTarget as Element).setPointerCapture?.(e.pointerId);\n controller.pointerDown(local(e), toVectorPointerInput(e));\n }}\n onPointerMove={(e) => controller.pointerMove(local(e), toVectorPointerInput(e))}\n onPointerUp={(e) => {\n (e.currentTarget as Element).releasePointerCapture?.(e.pointerId);\n controller.pointerUp(local(e), toVectorPointerInput(e));\n }}\n onPointerCancel={() => controller.cancelDrag()}\n onPointerLeave={() => controller.pointerLeave()}\n onDoubleClick={(e) => controller.doubleClick(local(e))}\n onKeyDown={(e) => {\n if (isVectorTextTarget(e.target)) return;\n if (controller.keyDown(toVectorKeyInput(e))) e.preventDefault();\n }}\n onKeyUp={(e) => controller.keyUp(toVectorKeyInput(e))}\n onCopy={clipboard('copy')}\n onCut={clipboard('cut')}\n onPaste={clipboard('paste')}\n >\n {checkerboard && (\n <defs>\n <pattern id={`ve${uid}-checker`} width={16} height={16} patternUnits=\"userSpaceOnUse\">\n <rect width={16} height={16} fill=\"#ffffff\" />\n <rect width={8} height={8} fill=\"#e5e7eb\" />\n <rect x={8} y={8} width={8} height={8} fill=\"#e5e7eb\" />\n </pattern>\n </defs>\n )}\n <VectorGradientDefs defs={scene.defs} />\n <rect\n data-vector-artboard=\"\"\n x={overlay.artboard.x}\n y={overlay.artboard.y}\n width={overlay.artboard.width}\n height={overlay.artboard.height}\n fill={scene.background ?? (checkerboard ? `url(#ve${uid}-checker)` : '#ffffff')}\n stroke=\"rgba(0,0,0,0.12)\"\n />\n <g data-vector-scene=\"\" transform={scene.transform}>\n <VectorSceneNodes nodes={scene.nodes} />\n </g>\n <g data-vector-overlay=\"\" pointerEvents=\"none\" fill=\"none\">\n {overlay.outlines.map((o) => (\n <path key={o.id} d={o.d} stroke={accentColor} strokeWidth={o.selected ? 1 : 1.5} opacity={o.selected ? 1 : 0.7} />\n ))}\n {overlay.penPreview && <path d={overlay.penPreview} stroke={accentColor} strokeDasharray=\"4 3\" />}\n {box && (\n <g data-vector-selection=\"\" transform={box.transform || undefined}>\n <rect x={box.x} y={box.y} width={box.width} height={box.height} stroke={accentColor} />\n <line x1={box.x + box.width / 2} y1={box.y} x2={box.x + box.width / 2} y2={box.y - 24} stroke={accentColor} />\n {box.handles.map((h) =>\n h.handle === 'rotate' ? (\n <circle key={h.handle} data-handle={h.handle} cx={h.x} cy={h.y} r={hs / 2 + 1} fill={THEME.handleFill} stroke={accentColor} />\n ) : (\n <rect key={h.handle} data-handle={h.handle} x={h.x - hs / 2} y={h.y - hs / 2} width={hs} height={hs} fill={THEME.handleFill} stroke={accentColor} />\n ),\n )}\n </g>\n )}\n {overlay.handles.map((h) => (\n <g key={`${h.ref.nodeId}:${h.ref.subpath}:${h.ref.index}:${h.ref.handle}`} data-vector-handle={h.ref.handle}>\n <line x1={h.anchorX} y1={h.anchorY} x2={h.x} y2={h.y} stroke={accentColor} />\n <circle cx={h.x} cy={h.y} r={THEME.handleRadius + (h.hovered ? 1 : 0)} fill={THEME.handleFill} stroke={accentColor} />\n </g>\n ))}\n {overlay.anchors.map((a) => {\n const size = as + (a.hovered ? 2 : 0);\n const fill = a.selected ? accentColor : THEME.handleFill;\n const key = `${a.ref.nodeId}:${a.ref.subpath}:${a.ref.index}`;\n return a.type === 'corner' ? (\n <rect key={key} data-vector-anchor={a.ref.index} x={a.x - size / 2} y={a.y - size / 2} width={size} height={size} fill={fill} stroke={accentColor} />\n ) : (\n <circle key={key} data-vector-anchor={a.ref.index} cx={a.x} cy={a.y} r={size / 2} fill={fill} stroke={accentColor} />\n );\n })}\n {overlay.cornerWidgets.map((w) => (\n <g key={`corner:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`} data-vector-corner-widget={w.ref.index} data-corner-kind={w.kind}>\n <circle cx={w.x} cy={w.y} r={THEME.cornerWidgetRadius + (w.hovered ? 1 : 0)} fill={THEME.handleFill} stroke={accentColor} />\n <circle cx={w.x} cy={w.y} r={1.5} fill={accentColor} />\n </g>\n ))}\n {state.tool === 'pen' && overlay.anchors.some((a) => a.closes && a.hovered) && (\n <circle cx={overlay.anchors.find((a) => a.closes)!.x} cy={overlay.anchors.find((a) => a.closes)!.y} r={as} stroke={accentColor} />\n )}\n {overlay.toolStroke && (\n <path\n data-vector-tool-stroke={overlay.toolStroke.tool}\n d={overlay.toolStroke.d}\n stroke={overlay.toolStroke.tool === 'eraser' ? THEME.eraserFill : accentColor}\n strokeWidth={overlay.toolStroke.tool === 'eraser' ? overlay.toolStroke.width : 1}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeDasharray={overlay.toolStroke.tool === 'knife' ? '5 3' : undefined}\n />\n )}\n {overlay.pencilString && (\n <line\n data-vector-pencil-string=\"\"\n x1={overlay.pencilString.x1}\n y1={overlay.pencilString.y1}\n x2={overlay.pencilString.x2}\n y2={overlay.pencilString.y2}\n stroke={accentColor}\n strokeDasharray=\"2 2\"\n />\n )}\n {overlay.cutPoint && <circle data-vector-cut-point=\"\" cx={overlay.cutPoint.x} cy={overlay.cutPoint.y} r={THEME.handleRadius + 1} fill={THEME.handleFill} stroke={accentColor} />}\n {overlay.marquee && (\n <rect\n data-vector-marquee=\"\"\n x={overlay.marquee.x}\n y={overlay.marquee.y}\n width={overlay.marquee.width}\n height={overlay.marquee.height}\n fill={THEME.marqueeFill}\n stroke={accentColor}\n strokeDasharray=\"3 2\"\n />\n )}\n {overlay.guides.lines.length > 0 && (\n <g data-vector-guides=\"\" stroke={guideColor}>\n {overlay.guides.lines.map((l, i) => (\n <line key={i} data-vector-guide={l.kind} x1={l.x1} y1={l.y1} x2={l.x2} y2={l.y2} strokeDasharray={l.kind === 'construction' ? '4 3' : undefined} />\n ))}\n </g>\n )}\n {overlay.guides.labels.map((l, i) => (\n <text\n key={i}\n data-vector-guide-label={l.kind}\n x={l.x + 6}\n y={l.y - 6}\n fontSize={10}\n fill={guideColor}\n stroke=\"#ffffff\"\n strokeWidth={3}\n paintOrder=\"stroke\"\n style={{ fontFamily: 'system-ui, sans-serif' }}\n >\n {l.text}\n </text>\n ))}\n {overlay.status && (\n <text data-vector-status=\"\" x={8} y=\"100%\" dy={-8} fontSize={11} fill={accentColor} style={{ fontFamily: 'system-ui, sans-serif' }}>\n {overlay.status}\n </text>\n )}\n </g>\n </svg>\n );\n}\n","import React from 'react';\nimport {\n VECTOR_TOOLS,\n VECTOR_TOOL_GLYPHS,\n VECTOR_TOOL_SHORTCUTS,\n VECTOR_EDIT_TOGGLES,\n VECTOR_PATH_ACTIONS,\n VECTOR_ARROWHEADS,\n VECTOR_ARROWHEAD_LABELS,\n VECTOR_CORNER_KINDS,\n VECTOR_CORNER_KIND_LABELS,\n VECTOR_STROKE_ALIGN_LABELS,\n getVectorSelectionStyle,\n vectorPaintToHex,\n vectorToolLabel,\n type VectorArrowhead,\n type VectorCornerKind,\n type VectorEditorController,\n type VectorStrokeAlign,\n type VectorTool,\n} from '@pixerate/editor/vector';\nimport { useVectorEditorState } from './useVectorEditor';\n\nconst VECTOR_SNAP_TITLE = 'Snap to objects';\nconst modKeyLabel = () => (typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform ?? '') ? '⌘' : 'Ctrl');\n\nconst buttonClass =\n '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';\n\nexport interface VectorToolbarProps {\n controller: VectorEditorController;\n /** Tools to show (default: all). */\n tools?: readonly VectorTool[];\n /** Undo / redo buttons (default `true`). */\n showHistory?: boolean;\n /** Boolean, group, arrange and align buttons (default `true`). */\n showArrange?: boolean;\n /** The snapping toggle (default `true`). */\n showSnap?: boolean;\n /**\n * Path editing: Join, Average, Cut at Points, Remove Redundant Points, Smooth, the Keep\n * Shape / Curvature / Shapes toggles, and the pencil smoothing and eraser size inputs while\n * those tools are active (default `true`).\n */\n showPathEdit?: boolean;\n className?: string;\n}\n\n/** Tool picker plus undo, snapping, boolean operations, grouping, stacking and alignment. */\nexport function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, showArrange = true, showSnap = true, showPathEdit = true, className }: VectorToolbarProps) {\n const state = useVectorEditorState(controller);\n const count = state.selection.length;\n const points = state.tool === 'direct' ? state.selectedAnchors.length : 0;\n const editing = state.editing;\n const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === 'group');\n const act = (label: string, title: string, run: () => unknown, disabled = false) => (\n <button key={label} type=\"button\" className={buttonClass} title={title} aria-label={title} disabled={disabled} onClick={() => void run()}>\n {label}\n </button>\n );\n return (\n <div role=\"toolbar\" aria-label=\"Vector tools\" className={`flex flex-wrap items-center gap-1 ${className ?? ''}`}>\n <div className=\"flex items-center gap-1\" role=\"group\" aria-label=\"Tools\">\n {tools.map((tool) => (\n <button\n key={tool}\n type=\"button\"\n data-vector-tool={tool}\n className={buttonClass}\n aria-pressed={state.tool === tool}\n title={`${vectorToolLabel(tool)} (${VECTOR_TOOL_SHORTCUTS[tool]})`}\n aria-label={vectorToolLabel(tool)}\n onClick={() => controller.setTool(tool)}\n >\n {VECTOR_TOOL_GLYPHS[tool]}\n </button>\n ))}\n </div>\n {showHistory && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"History\">\n {act('↶', state.canUndo ? `Undo ${state.undoLabel}` : 'Undo', () => controller.undo(), !state.canUndo)}\n {act('↷', state.canRedo ? `Redo ${state.redoLabel}` : 'Redo', () => controller.redo(), !state.canRedo)}\n </div>\n )}\n {showSnap && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Snapping\">\n <button\n type=\"button\"\n data-vector-snap=\"\"\n className={buttonClass}\n aria-pressed={state.snap.objects}\n title={`${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`}\n aria-label={VECTOR_SNAP_TITLE}\n onClick={() => controller.toggleSnapping()}\n >\n Snap\n </button>\n </div>\n )}\n {showPathEdit && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Path editing\">\n {VECTOR_PATH_ACTIONS.map((a) => (\n <button\n key={a.id}\n type=\"button\"\n data-vector-path-action={a.id}\n className={buttonClass}\n title={a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title}\n aria-label={a.title}\n disabled={!a.enabled(count, points)}\n onClick={() => void a.run(controller)}\n >\n {a.label}\n </button>\n ))}\n {VECTOR_EDIT_TOGGLES.map((t) => (\n <button\n key={t.key}\n type=\"button\"\n data-vector-edit={t.key}\n className={buttonClass}\n aria-pressed={editing[t.key]}\n title={t.title}\n aria-label={t.title}\n onClick={() => controller.setEditing({ [t.key]: !editing[t.key] })}\n >\n {t.label}\n </button>\n ))}\n {state.tool === 'pencil' && (\n <label className=\"flex items-center gap-1 text-xs text-foreground\">\n Smoothing\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.05}\n aria-label=\"Pencil smoothing\"\n className=\"h-4 w-20 accent-primary\"\n value={editing.pencilSmoothing}\n onChange={(e) => controller.setEditing({ pencilSmoothing: parseFloat(e.target.value) })}\n />\n </label>\n )}\n {state.tool === 'eraser' && (\n <label className=\"flex items-center gap-1 text-xs text-foreground\">\n Size\n <input\n type=\"number\"\n min={0.5}\n step={1}\n aria-label=\"Eraser size\"\n className=\"h-7 w-16 rounded border border-border bg-background px-1.5 text-xs\"\n value={editing.eraserSize}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n > 0) controller.setEditing({ eraserSize: n });\n }}\n />\n </label>\n )}\n </div>\n )}\n {showArrange && (\n <>\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Combine\">\n {act('∪', 'Union', () => controller.booleanOp('union'), count < 2)}\n {act('−', 'Subtract', () => controller.booleanOp('subtract'), count < 2)}\n {act('∩', 'Intersect', () => controller.booleanOp('intersect'), count < 2)}\n {act('⊻', 'Exclude', () => controller.booleanOp('exclude'), count < 2)}\n {act('G', 'Group', () => controller.group(), count < 1)}\n {act('U', 'Ungroup', () => controller.ungroup(), !groupSelected)}\n </div>\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Arrange\">\n {act('⇈', 'Bring to Front', () => controller.arrange('front'), count < 1)}\n {act('⇊', 'Send to Back', () => controller.arrange('back'), count < 1)}\n {act('⇤', 'Align Left', () => controller.align('left'), count < 1)}\n {act('↔', 'Align Center', () => controller.align('center'), count < 1)}\n {act('⇥', 'Align Right', () => controller.align('right'), count < 1)}\n {act('⤒', 'Align Top', () => controller.align('top'), count < 1)}\n {act('↕', 'Align Middle', () => controller.align('middle'), count < 1)}\n {act('⤓', 'Align Bottom', () => controller.align('bottom'), count < 1)}\n </div>\n </>\n )}\n </div>\n );\n}\n\nexport interface VectorStylePanelProps {\n controller: VectorEditorController;\n className?: string;\n}\n\nconst selectClass = 'h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs';\nconst numberClass = 'h-7 w-16 rounded border border-border bg-background px-1.5 text-xs';\n\n/**\n * Fill, stroke, stroke width and alignment, arrowheads, live corner radius and opacity of the\n * selection (corners of the selected points with the direct tool); with nothing selected it\n * edits the defaults for new shapes.\n */\nexport function VectorStylePanel({ controller, className }: VectorStylePanelProps) {\n const state = useVectorEditorState(controller);\n const style = getVectorSelectionStyle(state);\n const d = state.defaults;\n const source = style ?? {\n fill: d.fill ?? null,\n stroke: d.stroke ?? null,\n strokeWidth: d.strokeWidth ?? 1,\n opacity: 1,\n strokeAlign: d.strokeAlign ?? 'center',\n startArrow: d.startArrow ?? null,\n endArrow: d.endArrow ?? null,\n arrowAlign: d.arrowAlign ?? 'extend',\n startArrowScale: d.startArrowScale ?? 1,\n endArrowScale: d.endArrowScale ?? 1,\n cornerRadius: d.cornerRadius,\n cornerKind: d.cornerKind ?? 'round',\n corners: 1,\n hasOpenPath: true,\n };\n const setCorners = (patch: { radius?: number; kind?: VectorCornerKind }) => {\n if (!style) controller.setDefaults({ ...(patch.radius !== undefined ? { cornerRadius: patch.radius } : {}), ...(patch.kind ? { cornerKind: patch.kind } : {}) });\n else if (patch.radius !== undefined) controller.setCornerRadius(patch.radius);\n else if (patch.kind) controller.setCornerKind(patch.kind);\n };\n const mixed = (key: keyof NonNullable<typeof style>['mixed']) => (style?.mixed[key] ? <span className=\"text-[11px] text-muted-foreground\">Mixed</span> : null);\n const arrowRow = (end: 'start' | 'end', label: string) => {\n const key = end === 'start' ? 'startArrow' : 'endArrow';\n const scaleKey = end === 'start' ? 'startArrowScale' : 'endArrowScale';\n return (\n <div className=\"flex items-center gap-2\" data-vector-style={key}>\n <span className=\"w-16 text-xs text-foreground\">{label}</span>\n <select aria-label={`${label} arrowhead`} className={selectClass} value={source[key] ?? ''} onChange={(e) => apply({ [key]: (e.target.value || null) as VectorArrowhead | null })}>\n <option value=\"\">None</option>\n {VECTOR_ARROWHEADS.map((h) => (\n <option key={h} value={h}>\n {VECTOR_ARROWHEAD_LABELS[h]}\n </option>\n ))}\n </select>\n <input\n type=\"number\"\n min={0.1}\n step={0.25}\n aria-label={`${label} arrowhead scale`}\n title=\"Scale (× stroke width)\"\n className={numberClass}\n value={source[scaleKey]}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n > 0) apply({ [scaleKey]: n });\n }}\n />\n </div>\n );\n };\n const apply = (patch: Record<string, unknown>) => {\n if (style) controller.setStyle(patch);\n else controller.setDefaults(patch);\n };\n const paintRow = (key: 'fill' | 'stroke', label: string) => {\n const paint = source[key];\n const hex = vectorPaintToHex(paint);\n const on = paint !== null && paint !== 'none';\n return (\n <div className=\"flex items-center gap-2\" data-vector-style={key}>\n <label className=\"flex w-16 items-center gap-1.5 text-xs text-foreground\">\n <input type=\"checkbox\" checked={on} aria-label={`${label} on`} onChange={(e) => apply({ [key]: e.target.checked ? (hex ?? '#000000') : null })} />\n {label}\n </label>\n <input\n type=\"color\"\n aria-label={`${label} colour`}\n className=\"h-7 w-10 cursor-pointer rounded border border-border bg-background disabled:opacity-40\"\n disabled={!on}\n value={hex ?? '#000000'}\n onChange={(e) => apply({ [key]: e.target.value })}\n />\n {on && !hex && <span className=\"truncate text-[11px] text-muted-foreground\">{typeof paint === 'string' ? paint : 'Gradient'}</span>}\n {style?.mixed[key] && <span className=\"text-[11px] text-muted-foreground\">Mixed</span>}\n </div>\n );\n };\n return (\n <div className={`space-y-2 ${className ?? ''}`} aria-label={style ? 'Selection style' : 'New shape style'}>\n <p className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">{style ? 'Selection' : 'New shapes'}</p>\n {paintRow('fill', 'Fill')}\n {paintRow('stroke', 'Stroke')}\n <label className=\"flex items-center gap-2 text-xs text-foreground\">\n <span className=\"w-16\">Width</span>\n <input\n type=\"number\"\n min={0}\n step={0.5}\n aria-label=\"Stroke width\"\n className=\"h-7 w-20 rounded border border-border bg-background px-1.5 text-xs\"\n value={source.strokeWidth}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n >= 0) apply({ strokeWidth: n });\n }}\n />\n </label>\n <label className=\"flex items-center gap-2 text-xs text-foreground\" data-vector-style=\"strokeAlign\">\n <span className=\"w-16\">Align</span>\n <select aria-label=\"Stroke alignment\" className={selectClass} value={source.strokeAlign} onChange={(e) => apply({ strokeAlign: e.target.value as VectorStrokeAlign })}>\n {(Object.keys(VECTOR_STROKE_ALIGN_LABELS) as VectorStrokeAlign[]).map((a) => (\n <option key={a} value={a}>\n {VECTOR_STROKE_ALIGN_LABELS[a]}\n </option>\n ))}\n </select>\n {mixed('strokeAlign')}\n </label>\n {source.hasOpenPath && (\n <>\n {arrowRow('start', 'Start')}\n {arrowRow('end', 'End')}\n {(source.startArrow || source.endArrow) && (\n <label className=\"flex items-center gap-2 text-xs text-foreground\" data-vector-style=\"arrowAlign\">\n <span className=\"w-16\">Heads</span>\n <select aria-label=\"Arrowhead alignment\" className={selectClass} value={source.arrowAlign} onChange={(e) => apply({ arrowAlign: e.target.value })}>\n <option value=\"extend\">Tip past end</option>\n <option value=\"tip\">Tip at end</option>\n </select>\n </label>\n )}\n </>\n )}\n {source.corners > 0 && (\n <div className=\"flex items-center gap-2\" data-vector-style=\"corners\">\n <span className=\"w-16 text-xs text-foreground\">Corners</span>\n <input\n type=\"number\"\n min={0}\n step={1}\n aria-label=\"Corner radius\"\n className={numberClass}\n value={Math.round(source.cornerRadius * 100) / 100}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n >= 0) setCorners({ radius: n });\n }}\n />\n <select aria-label=\"Corner kind\" className={selectClass} value={source.cornerKind} onChange={(e) => setCorners({ kind: e.target.value as VectorCornerKind })}>\n {VECTOR_CORNER_KINDS.map((k) => (\n <option key={k} value={k}>\n {VECTOR_CORNER_KIND_LABELS[k]}\n </option>\n ))}\n </select>\n {mixed('cornerRadius')}\n </div>\n )}\n {style && (\n <label className=\"flex items-center gap-2 text-xs text-foreground\">\n <span className=\"w-16\">Opacity</span>\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.05}\n aria-label=\"Opacity\"\n className=\"h-4 flex-1 accent-primary\"\n value={source.opacity}\n onChange={(e) => apply({ opacity: parseFloat(e.target.value) })}\n />\n </label>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport type { VectorEditorController, VectorTool } from '@pixerate/editor/vector';\nimport { VectorCanvas, type VectorCanvasProps } from './VectorCanvas';\nimport { VectorStylePanel, VectorToolbar } from './VectorToolbar';\n\nexport interface VectorEditorProps {\n controller: VectorEditorController;\n /** Tools in the toolbar (default: all). */\n tools?: readonly VectorTool[];\n /** The style sidebar (default `true`). */\n showStylePanel?: boolean;\n /** Canvas height (default 520px). */\n height?: number | string;\n canvasProps?: Omit<VectorCanvasProps, 'controller'>;\n className?: string;\n}\n\n/** Toolbar, canvas and style panel for a `VectorEditorController`. */\nexport function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }: VectorEditorProps) {\n return (\n <div className={`flex flex-col gap-2 ${className ?? ''}`} data-vector-editor=\"\">\n <VectorToolbar controller={controller} tools={tools} />\n <div className=\"flex min-h-0 flex-col gap-2 md:flex-row\">\n <div className=\"relative min-h-[320px] flex-1 overflow-hidden rounded-md border border-border bg-muted/40\" style={{ height }}>\n <VectorCanvas controller={controller} {...canvasProps} />\n </div>\n {showStylePanel && <VectorStylePanel controller={controller} className=\"w-full shrink-0 rounded-md border border-border p-3 md:w-56\" />}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["useEffect","useRef","useRef","useEffect","text","Fragment","jsx","jsxs","jsx","jsxs"]}
1
+ {"version":3,"sources":["../../src/vector/useVectorEditor.ts","../../src/vector/VectorCanvas.tsx","../../src/vector/VectorToolbar.tsx","../../src/vector/VectorEditor.tsx"],"sourcesContent":["import { useEffect, useMemo, useRef, useSyncExternalStore } from 'react';\nimport {\n VectorEditorController,\n createVectorCommands,\n type VectorCommandOptions,\n type VectorEditorOptions,\n type VectorEditorState,\n type VectorTool,\n} from '@pixerate/editor/vector';\n\n/** A `VectorEditorController` created once for the component's lifetime (destroyed on unmount). */\nexport function useVectorEditorController(options: VectorEditorOptions = {}): VectorEditorController {\n const ref = useRef<VectorEditorController | null>(null);\n if (!ref.current) ref.current = new VectorEditorController(options);\n const controller = ref.current;\n useEffect(() => () => controller.destroy(), [controller]);\n return controller;\n}\n\n/** The controller's state (re-renders on every change). */\nexport function useVectorEditorState(controller: VectorEditorController): VectorEditorState {\n return useSyncExternalStore(controller.subscribe, controller.getState, controller.getState);\n}\n\nexport interface UseVectorEditorResult {\n controller: VectorEditorController;\n state: VectorEditorState;\n setTool: (tool: VectorTool) => void;\n undo: () => void;\n redo: () => void;\n deleteSelection: () => void;\n toSvg: () => string;\n}\n\n/**\n * Subscribes to a vector editor controller and exposes its state with bound actions. Pass\n * options instead of a controller to create one for the component's lifetime.\n */\nexport function useVectorEditor(controllerOrOptions: VectorEditorController | VectorEditorOptions = {}): UseVectorEditorResult {\n const own = useRef<VectorEditorController | null>(null);\n let controller: VectorEditorController;\n if (controllerOrOptions instanceof VectorEditorController) controller = controllerOrOptions;\n else {\n if (!own.current) own.current = new VectorEditorController(controllerOrOptions);\n controller = own.current;\n }\n const state = useVectorEditorState(controller);\n const actions = useMemo(\n () => ({\n setTool: (tool: VectorTool) => controller.setTool(tool),\n undo: () => void controller.undo(),\n redo: () => void controller.redo(),\n deleteSelection: () => void controller.deleteSelection(),\n toSvg: () => controller.toSvg(),\n }),\n [controller],\n );\n return { controller, state, ...actions };\n}\n\n/** Anything with `register(specs) → unregister` (a `CommandRegistry`). */\nexport interface VectorCommandTarget {\n register(specs: any): () => void;\n}\n\n/**\n * Registers the controller's palette / agent commands (`vector.addShape`, `vector.boolean`, …)\n * in `registry` while mounted, so `createCommandToolProvider` exposes them to agents.\n */\nexport function useVectorCommands(\n registry: VectorCommandTarget | null | undefined,\n controller: VectorEditorController,\n options: VectorCommandOptions = {},\n): void {\n const { prefix, group, scope } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createVectorCommands(controller, { prefix, group, scope }));\n }, [registry, controller, prefix, group, scope]);\n}\n","import React, { useEffect, useId, useRef } from 'react';\nimport {\n VECTOR_OVERLAY_THEME as THEME,\n getVectorOverlayRenderData,\n getVectorSceneRenderData,\n isVectorTextTarget,\n toVectorKeyInput,\n toVectorPointerInput,\n vectorDiamondPath,\n type VectorEditorController,\n type VectorRenderNode,\n type VectorRenderPath,\n type SvgGradientDef,\n} from '@pixerate/editor/vector';\nimport { useVectorEditorState } from './useVectorEditor';\n\nexport interface VectorCanvasProps {\n controller: VectorEditorController;\n /** Fit the artboard into the canvas when it first gets a size (default `true`). */\n fitOnMount?: boolean;\n /** Draw a checkerboard behind a transparent artboard (default `true`). */\n checkerboard?: boolean;\n /** Overlay accent colour (default sky blue). */\n accentColor?: string;\n /** Smart guide colour (default magenta). */\n guideColor?: string;\n className?: string;\n style?: React.CSSProperties;\n /** Accessible label (default \"Vector canvas\"). */\n 'aria-label'?: string;\n}\n\n/** Renders `<linearGradient>` / `<radialGradient>` descriptors. */\nexport function VectorGradientDefs({ defs }: { defs: readonly SvgGradientDef[] }) {\n if (!defs.length) return null;\n return (\n <defs>\n {defs.map((def) => {\n const stops = def.stops.map((s, i) => <stop key={i} offset={s.offset} stopColor={s.stopColor} stopOpacity={s.stopOpacity} />);\n return def.type === 'radial' ? (\n <radialGradient key={def.id} id={def.id} {...(def.attrs as any)}>\n {stops}\n </radialGradient>\n ) : (\n <linearGradient key={def.id} id={def.id} {...(def.attrs as any)}>\n {stops}\n </linearGradient>\n );\n })}\n </defs>\n );\n}\n\n/** Renders scene nodes (paths and groups) from `getVectorSceneRenderData`. */\nexport function VectorSceneNodes({ nodes }: { nodes: readonly VectorRenderNode[] }) {\n return (\n <>\n {nodes.map((node) =>\n node.kind === 'group' ? (\n <g key={node.id} data-vector-id={node.id} transform={node.transform} opacity={node.opacity < 1 ? node.opacity : undefined}>\n <VectorSceneNodes nodes={node.children} />\n </g>\n ) : node.strokeParts ? (\n <VectorPartedPath key={node.id} node={node} />\n ) : (\n <path\n key={node.id}\n data-vector-id={node.id}\n transform={node.transform}\n d={node.d}\n fill={node.fill}\n fillRule={node.fillRule}\n stroke={node.stroke}\n strokeWidth={node.stroke === 'none' ? undefined : node.strokeWidth}\n strokeLinecap={node.strokeLinecap as any}\n strokeLinejoin={node.strokeLinejoin as any}\n strokeDasharray={node.strokeDasharray}\n opacity={node.opacity < 1 ? node.opacity : undefined}\n />\n ),\n )}\n </>\n );\n}\n\n/** A path whose stroke is aligned inside / outside (double width, clipped or masked by the shape) or has arrowheads. */\nfunction VectorPartedPath({ node }: { node: VectorRenderPath }) {\n const sp = node.strokeParts!;\n const clip = sp.clip;\n const b = clip?.bounds;\n return (\n <g data-vector-id={node.id} data-vector-stroke-align={sp.align} transform={node.transform} opacity={node.opacity < 1 ? node.opacity : undefined}>\n {clip && b && (\n <defs>\n {clip.kind === 'clip' ? (\n <clipPath id={clip.id}>\n <path d={node.d} clipRule={node.fillRule} />\n </clipPath>\n ) : (\n <mask id={clip.id} maskUnits=\"userSpaceOnUse\" x={b.x} y={b.y} width={b.width} height={b.height}>\n <rect x={b.x} y={b.y} width={b.width} height={b.height} fill=\"#fff\" />\n <path d={node.d} fill=\"#000\" fillRule={node.fillRule} />\n </mask>\n )}\n </defs>\n )}\n <path data-vector-part=\"fill\" d={node.d} fill={node.fill} fillRule={node.fillRule} stroke=\"none\" />\n {sp.outline !== undefined ? (\n // A variable-width stroke: its outline, filled.\n <path\n data-vector-part=\"stroke-outline\"\n d={sp.outline}\n fill={node.stroke}\n clipPath={clip?.kind === 'clip' ? `url(#${clip.id})` : undefined}\n mask={clip?.kind === 'mask' ? `url(#${clip.id})` : undefined}\n />\n ) : (\n <path\n data-vector-part=\"stroke\"\n d={sp.d}\n fill=\"none\"\n stroke={node.stroke}\n strokeWidth={sp.width}\n strokeLinecap={node.strokeLinecap as any}\n strokeLinejoin={node.strokeLinejoin as any}\n strokeDasharray={node.strokeDasharray}\n clipPath={clip?.kind === 'clip' ? `url(#${clip.id})` : undefined}\n mask={clip?.kind === 'mask' ? `url(#${clip.id})` : undefined}\n />\n )}\n {sp.heads.map((head, i) => (\n <path key={i} data-vector-part=\"head\" d={head} fill={node.stroke} />\n ))}\n </g>\n );\n}\n\n/**\n * An SVG canvas for a `VectorEditorController`: draws the document and the editing overlay\n * and forwards pointer, wheel, keyboard and clipboard events. Focus it to use shortcuts.\n */\nexport function VectorCanvas({\n controller,\n fitOnMount = true,\n checkerboard = true,\n accentColor = THEME.accent,\n guideColor = THEME.guide,\n className,\n style,\n 'aria-label': ariaLabel = 'Vector canvas',\n}: VectorCanvasProps) {\n const state = useVectorEditorState(controller);\n const svgRef = useRef<SVGSVGElement | null>(null);\n const fitted = useRef(!fitOnMount);\n const uid = useId().replace(/:/g, '');\n const scene = getVectorSceneRenderData(state, { idPrefix: `ve${uid}-` });\n const overlay = getVectorOverlayRenderData(state);\n\n useEffect(() => {\n const el = svgRef.current;\n if (!el || fitted.current) return;\n const fit = () => {\n const rect = el.getBoundingClientRect();\n if (fitted.current || rect.width <= 0 || rect.height <= 0) return;\n fitted.current = true;\n controller.zoomToFit({ width: rect.width, height: rect.height });\n };\n fit();\n if (fitted.current || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(fit);\n observer.observe(el);\n return () => observer.disconnect();\n }, [controller]);\n\n // Wheel needs a non-passive listener to stop page scroll / browser zoom.\n useEffect(() => {\n const el = svgRef.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n controller.wheel(local(e), { x: e.deltaX, y: e.deltaY }, toVectorPointerInput(e));\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [controller]);\n\n const local = (e: { clientX: number; clientY: number }) => {\n const rect = svgRef.current?.getBoundingClientRect();\n return { x: e.clientX - (rect?.left ?? 0), y: e.clientY - (rect?.top ?? 0) };\n };\n\n const clipboard = (kind: 'copy' | 'cut' | 'paste') => (event: React.ClipboardEvent) => {\n const native = (event && 'nativeEvent' in event ? event.nativeEvent : event) as ClipboardEvent;\n const data = native?.clipboardData;\n if (kind === 'paste') {\n const text = data?.getData('text/plain') ?? '';\n const pasted = text ? controller.paste(text) : controller.paste();\n if (pasted.length) event.preventDefault?.();\n return;\n }\n const text = kind === 'cut' ? controller.cut() : controller.copy();\n if (text && data) {\n data.setData('text/plain', text);\n event.preventDefault?.();\n }\n };\n\n const hs = THEME.transformHandleSize;\n const as = THEME.anchorSize;\n const box = overlay.selectionBox;\n\n return (\n <svg\n ref={svgRef}\n role=\"application\"\n aria-label={ariaLabel}\n tabIndex={0}\n data-tool={state.tool}\n className={className}\n style={{ display: 'block', width: '100%', height: '100%', outline: 'none', touchAction: 'none', userSelect: 'none', cursor: state.cursor, ...style }}\n onPointerDown={(e) => {\n svgRef.current?.focus({ preventScroll: true });\n (e.currentTarget as Element).setPointerCapture?.(e.pointerId);\n controller.pointerDown(local(e), toVectorPointerInput(e));\n }}\n onPointerMove={(e) => controller.pointerMove(local(e), toVectorPointerInput(e))}\n onPointerUp={(e) => {\n (e.currentTarget as Element).releasePointerCapture?.(e.pointerId);\n controller.pointerUp(local(e), toVectorPointerInput(e));\n }}\n onPointerCancel={() => controller.cancelDrag()}\n onPointerLeave={() => controller.pointerLeave()}\n onDoubleClick={(e) => controller.doubleClick(local(e))}\n onKeyDown={(e) => {\n if (isVectorTextTarget(e.target)) return;\n if (controller.keyDown(toVectorKeyInput(e))) e.preventDefault();\n }}\n onKeyUp={(e) => controller.keyUp(toVectorKeyInput(e))}\n onCopy={clipboard('copy')}\n onCut={clipboard('cut')}\n onPaste={clipboard('paste')}\n >\n {checkerboard && (\n <defs>\n <pattern id={`ve${uid}-checker`} width={16} height={16} patternUnits=\"userSpaceOnUse\">\n <rect width={16} height={16} fill=\"#ffffff\" />\n <rect width={8} height={8} fill=\"#e5e7eb\" />\n <rect x={8} y={8} width={8} height={8} fill=\"#e5e7eb\" />\n </pattern>\n </defs>\n )}\n <VectorGradientDefs defs={scene.defs} />\n <rect\n data-vector-artboard=\"\"\n x={overlay.artboard.x}\n y={overlay.artboard.y}\n width={overlay.artboard.width}\n height={overlay.artboard.height}\n fill={scene.background ?? (checkerboard ? `url(#ve${uid}-checker)` : '#ffffff')}\n stroke=\"rgba(0,0,0,0.12)\"\n />\n <g data-vector-scene=\"\" transform={scene.transform}>\n <VectorSceneNodes nodes={scene.nodes} />\n </g>\n <g data-vector-overlay=\"\" pointerEvents=\"none\" fill=\"none\">\n {overlay.outlines.map((o) => (\n <path key={o.id} d={o.d} stroke={accentColor} strokeWidth={o.selected ? 1 : 1.5} opacity={o.selected ? 1 : 0.7} />\n ))}\n {overlay.penPreview && <path d={overlay.penPreview} stroke={accentColor} strokeDasharray=\"4 3\" />}\n {box && (\n <g data-vector-selection=\"\" transform={box.transform || undefined}>\n <rect x={box.x} y={box.y} width={box.width} height={box.height} stroke={accentColor} />\n <line x1={box.x + box.width / 2} y1={box.y} x2={box.x + box.width / 2} y2={box.y - 24} stroke={accentColor} />\n {box.handles.map((h) =>\n h.handle === 'rotate' ? (\n <circle key={h.handle} data-handle={h.handle} cx={h.x} cy={h.y} r={hs / 2 + 1} fill={THEME.handleFill} stroke={accentColor} />\n ) : (\n <rect key={h.handle} data-handle={h.handle} x={h.x - hs / 2} y={h.y - hs / 2} width={hs} height={hs} fill={THEME.handleFill} stroke={accentColor} />\n ),\n )}\n </g>\n )}\n {overlay.handles.map((h) => (\n <g key={`${h.ref.nodeId}:${h.ref.subpath}:${h.ref.index}:${h.ref.handle}`} data-vector-handle={h.ref.handle}>\n <line x1={h.anchorX} y1={h.anchorY} x2={h.x} y2={h.y} stroke={accentColor} />\n <circle cx={h.x} cy={h.y} r={THEME.handleRadius + (h.hovered ? 1 : 0)} fill={THEME.handleFill} stroke={accentColor} />\n </g>\n ))}\n {overlay.anchors.map((a) => {\n const size = as + (a.hovered ? 2 : 0);\n const fill = a.selected ? accentColor : THEME.handleFill;\n const key = `${a.ref.nodeId}:${a.ref.subpath}:${a.ref.index}`;\n return a.type === 'corner' ? (\n <rect key={key} data-vector-anchor={a.ref.index} x={a.x - size / 2} y={a.y - size / 2} width={size} height={size} fill={fill} stroke={accentColor} />\n ) : (\n <circle key={key} data-vector-anchor={a.ref.index} cx={a.x} cy={a.y} r={size / 2} fill={fill} stroke={accentColor} />\n );\n })}\n {overlay.cornerWidgets.map((w) => (\n <g key={`corner:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`} data-vector-corner-widget={w.ref.index} data-corner-kind={w.kind}>\n <circle cx={w.x} cy={w.y} r={THEME.cornerWidgetRadius + (w.hovered ? 1 : 0)} fill={THEME.handleFill} stroke={accentColor} />\n <circle cx={w.x} cy={w.y} r={1.5} fill={accentColor} />\n </g>\n ))}\n {overlay.widthSpot && (\n <g data-vector-width-spot=\"\">\n <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\" />\n <path d={vectorDiamondPath(overlay.widthSpot.x, overlay.widthSpot.y)} fill=\"none\" stroke={accentColor} />\n </g>\n )}\n {overlay.widthPoints.map((w) => (\n <g key={`width:${w.ref.nodeId}:${w.ref.subpath}:${w.ref.index}`} data-vector-width-point={w.ref.index} data-selected={w.selected || undefined}>\n <line x1={w.left.x} y1={w.left.y} x2={w.right.x} y2={w.right.y} stroke={accentColor} />\n <path d={vectorDiamondPath(w.x, w.y)} fill={w.selected || w.active ? accentColor : THEME.handleFill} stroke={accentColor} strokeWidth={w.hovered === 'center' ? 2 : 1} />\n {(['left', 'right'] as const).map((side) => (\n <circle key={side} data-vector-width-side={side} cx={w[side].x} cy={w[side].y} r={THEME.handleRadius + (w.hovered === side ? 1 : 0)} fill={THEME.handleFill} stroke={accentColor} />\n ))}\n </g>\n ))}\n {state.tool === 'pen' && overlay.anchors.some((a) => a.closes && a.hovered) && (\n <circle cx={overlay.anchors.find((a) => a.closes)!.x} cy={overlay.anchors.find((a) => a.closes)!.y} r={as} stroke={accentColor} />\n )}\n {overlay.builder && (\n <g data-vector-builder={overlay.builder.mode}>\n {overlay.builder.faces.map((d, i) => (\n <path\n key={`f${i}`}\n data-vector-builder-face=\"\"\n d={d}\n fill={overlay.builder!.mode === 'erase' ? THEME.builderEraseFill : THEME.builderFill}\n fillRule=\"nonzero\"\n stroke={overlay.builder!.mode === 'erase' ? THEME.builderErase : accentColor}\n strokeWidth={1}\n />\n ))}\n {overlay.builder.lines.map((d, i) => (\n <path key={`l${i}`} data-vector-builder-line=\"\" d={d} fill=\"none\" stroke={THEME.builderErase} strokeWidth={3} strokeLinecap=\"round\" />\n ))}\n {overlay.builder.trail && <path data-vector-builder-trail=\"\" d={overlay.builder.trail} fill=\"none\" stroke={overlay.builder.mode === 'erase' ? THEME.builderErase : accentColor} strokeWidth={1} />}\n </g>\n )}\n {overlay.toolStroke && (\n <path\n data-vector-tool-stroke={overlay.toolStroke.tool}\n d={overlay.toolStroke.d}\n stroke={overlay.toolStroke.tool === 'eraser' ? THEME.eraserFill : accentColor}\n strokeWidth={overlay.toolStroke.tool === 'eraser' ? overlay.toolStroke.width : 1}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeDasharray={overlay.toolStroke.tool === 'knife' ? '5 3' : undefined}\n />\n )}\n {overlay.pencilString && (\n <line\n data-vector-pencil-string=\"\"\n x1={overlay.pencilString.x1}\n y1={overlay.pencilString.y1}\n x2={overlay.pencilString.x2}\n y2={overlay.pencilString.y2}\n stroke={accentColor}\n strokeDasharray=\"2 2\"\n />\n )}\n {overlay.cutPoint && <circle data-vector-cut-point=\"\" cx={overlay.cutPoint.x} cy={overlay.cutPoint.y} r={THEME.handleRadius + 1} fill={THEME.handleFill} stroke={accentColor} />}\n {overlay.marquee && (\n <rect\n data-vector-marquee=\"\"\n x={overlay.marquee.x}\n y={overlay.marquee.y}\n width={overlay.marquee.width}\n height={overlay.marquee.height}\n fill={THEME.marqueeFill}\n stroke={accentColor}\n strokeDasharray=\"3 2\"\n />\n )}\n {overlay.guides.lines.length > 0 && (\n <g data-vector-guides=\"\" stroke={guideColor}>\n {overlay.guides.lines.map((l, i) => (\n <line key={i} data-vector-guide={l.kind} x1={l.x1} y1={l.y1} x2={l.x2} y2={l.y2} strokeDasharray={l.kind === 'construction' ? '4 3' : undefined} />\n ))}\n </g>\n )}\n {overlay.guides.labels.map((l, i) => (\n <text\n key={i}\n data-vector-guide-label={l.kind}\n x={l.x + 6}\n y={l.y - 6}\n fontSize={10}\n fill={guideColor}\n stroke=\"#ffffff\"\n strokeWidth={3}\n paintOrder=\"stroke\"\n style={{ fontFamily: 'system-ui, sans-serif' }}\n >\n {l.text}\n </text>\n ))}\n {overlay.status && (\n <text data-vector-status=\"\" x={8} y=\"100%\" dy={-8} fontSize={11} fill={accentColor} style={{ fontFamily: 'system-ui, sans-serif' }}>\n {overlay.status}\n </text>\n )}\n </g>\n </svg>\n );\n}\n","import React from 'react';\nimport {\n VECTOR_TOOLS,\n VECTOR_TOOL_GLYPHS,\n VECTOR_TOOL_SHORTCUTS,\n VECTOR_EDIT_TOGGLES,\n VECTOR_PATH_ACTIONS,\n VECTOR_PATHFINDER_ACTIONS,\n VECTOR_FILL_GAP,\n VECTOR_ARROWHEADS,\n VECTOR_ARROWHEAD_LABELS,\n VECTOR_CORNER_KINDS,\n VECTOR_CORNER_KIND_LABELS,\n VECTOR_STROKE_ALIGN_LABELS,\n VECTOR_WIDTH_PRESETS,\n getVectorSelectionStyle,\n widthProfilePreset,\n widthProfilePresetId,\n vectorPaintToHex,\n vectorToolLabel,\n type VectorArrowhead,\n type VectorCornerKind,\n type VectorEditorController,\n type VectorStrokeAlign,\n type VectorTool,\n type VectorWidthPreset,\n} from '@pixerate/editor/vector';\nimport { useVectorEditorState } from './useVectorEditor';\n\nconst VECTOR_SNAP_TITLE = 'Snap to objects';\nconst modKeyLabel = () => (typeof navigator !== 'undefined' && /Mac|iPhone|iPad/.test(navigator.platform ?? '') ? '⌘' : 'Ctrl');\n\nconst buttonClass =\n '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';\n\nexport interface VectorToolbarProps {\n controller: VectorEditorController;\n /** Tools to show (default: all). */\n tools?: readonly VectorTool[];\n /** Undo / redo buttons (default `true`). */\n showHistory?: boolean;\n /** Boolean, Pathfinder, group, arrange and align buttons (default `true`). */\n showArrange?: boolean;\n /** The snapping toggle (default `true`). */\n showSnap?: boolean;\n /**\n * Path editing: Join, Average, Cut at Points, Remove Redundant Points, Smooth, the Keep\n * Shape / Curvature / Shapes toggles, and the pencil smoothing and eraser size inputs while\n * those tools are active (default `true`).\n */\n showPathEdit?: boolean;\n className?: string;\n}\n\n/** Tool picker plus undo, snapping, boolean operations, grouping, stacking and alignment. */\nexport function VectorToolbar({ controller, tools = VECTOR_TOOLS, showHistory = true, showArrange = true, showSnap = true, showPathEdit = true, className }: VectorToolbarProps) {\n const state = useVectorEditorState(controller);\n const count = state.selection.length;\n const points = state.tool === 'direct' ? state.selectedAnchors.length : 0;\n const editing = state.editing;\n const groupSelected = state.selection.some((id) => controller.getNode(id)?.type === 'group');\n const act = (label: string, title: string, run: () => unknown, disabled = false) => (\n <button key={label} type=\"button\" className={buttonClass} title={title} aria-label={title} disabled={disabled} onClick={() => void run()}>\n {label}\n </button>\n );\n return (\n <div role=\"toolbar\" aria-label=\"Vector tools\" className={`flex flex-wrap items-center gap-1 ${className ?? ''}`}>\n <div className=\"flex items-center gap-1\" role=\"group\" aria-label=\"Tools\">\n {tools.map((tool) => (\n <button\n key={tool}\n type=\"button\"\n data-vector-tool={tool}\n className={buttonClass}\n aria-pressed={state.tool === tool}\n title={`${vectorToolLabel(tool)} (${VECTOR_TOOL_SHORTCUTS[tool]})`}\n aria-label={vectorToolLabel(tool)}\n onClick={() => controller.setTool(tool)}\n >\n {VECTOR_TOOL_GLYPHS[tool]}\n </button>\n ))}\n </div>\n {showHistory && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"History\">\n {act('↶', state.canUndo ? `Undo ${state.undoLabel}` : 'Undo', () => controller.undo(), !state.canUndo)}\n {act('↷', state.canRedo ? `Redo ${state.redoLabel}` : 'Redo', () => controller.redo(), !state.canRedo)}\n </div>\n )}\n {showSnap && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Snapping\">\n <button\n type=\"button\"\n data-vector-snap=\"\"\n className={buttonClass}\n aria-pressed={state.snap.objects}\n title={`${VECTOR_SNAP_TITLE} (hold ${modKeyLabel()} to bypass)`}\n aria-label={VECTOR_SNAP_TITLE}\n onClick={() => controller.toggleSnapping()}\n >\n Snap\n </button>\n </div>\n )}\n {showPathEdit && (\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Path editing\">\n {VECTOR_PATH_ACTIONS.map((a) => (\n <button\n key={a.id}\n type=\"button\"\n data-vector-path-action={a.id}\n className={buttonClass}\n title={a.shortcut ? `${a.title} (${modKeyLabel()}+${a.shortcut})` : a.title}\n aria-label={a.title}\n disabled={!a.enabled(count, points)}\n onClick={() => void a.run(controller)}\n >\n {a.label}\n </button>\n ))}\n {VECTOR_EDIT_TOGGLES.map((t) => (\n <button\n key={t.key}\n type=\"button\"\n data-vector-edit={t.key}\n className={buttonClass}\n aria-pressed={editing[t.key]}\n title={t.title}\n aria-label={t.title}\n onClick={() => controller.setEditing({ [t.key]: !editing[t.key] })}\n >\n {t.label}\n </button>\n ))}\n {state.tool === 'pencil' && (\n <label className=\"flex items-center gap-1 text-xs text-foreground\">\n Smoothing\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.05}\n aria-label=\"Pencil smoothing\"\n className=\"h-4 w-20 accent-primary\"\n value={editing.pencilSmoothing}\n onChange={(e) => controller.setEditing({ pencilSmoothing: parseFloat(e.target.value) })}\n />\n </label>\n )}\n {state.tool === 'eraser' && (\n <label className=\"flex items-center gap-1 text-xs text-foreground\">\n Size\n <input\n type=\"number\"\n min={0.5}\n step={1}\n aria-label=\"Eraser size\"\n className=\"h-7 w-16 rounded border border-border bg-background px-1.5 text-xs\"\n value={editing.eraserSize}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n > 0) controller.setEditing({ eraserSize: n });\n }}\n />\n </label>\n )}\n {state.tool === 'paintBucket' && (\n <button\n type=\"button\"\n data-vector-fill-gap=\"\"\n className={buttonClass}\n aria-pressed={editing.fillGap > 0}\n title=\"Close small gaps between path ends when filling\"\n aria-label=\"Close gaps\"\n onClick={() => controller.setEditing({ fillGap: editing.fillGap > 0 ? 0 : VECTOR_FILL_GAP })}\n >\n Gaps\n </button>\n )}\n </div>\n )}\n {showArrange && (\n <>\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Combine\">\n {act('∪', 'Union', () => controller.booleanOp('union'), count < 2)}\n {act('−', 'Subtract', () => controller.booleanOp('subtract'), count < 2)}\n {act('∩', 'Intersect', () => controller.booleanOp('intersect'), count < 2)}\n {act('⊻', 'Exclude', () => controller.booleanOp('exclude'), count < 2)}\n {act('G', 'Group', () => controller.group(), count < 1)}\n {act('U', 'Ungroup', () => controller.ungroup(), !groupSelected)}\n </div>\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Pathfinder\">\n {VECTOR_PATHFINDER_ACTIONS.map((a) => (\n <button\n key={a.id}\n type=\"button\"\n data-vector-pathfinder={a.id}\n className={buttonClass}\n title={a.title}\n aria-label={a.title}\n disabled={count < a.min}\n onClick={() => void controller.pathfinder(a.id)}\n >\n {a.label}\n </button>\n ))}\n </div>\n <div className=\"ml-1 flex items-center gap-1\" role=\"group\" aria-label=\"Arrange\">\n {act('⇈', 'Bring to Front', () => controller.arrange('front'), count < 1)}\n {act('⇊', 'Send to Back', () => controller.arrange('back'), count < 1)}\n {act('⇤', 'Align Left', () => controller.align('left'), count < 1)}\n {act('↔', 'Align Center', () => controller.align('center'), count < 1)}\n {act('⇥', 'Align Right', () => controller.align('right'), count < 1)}\n {act('⤒', 'Align Top', () => controller.align('top'), count < 1)}\n {act('↕', 'Align Middle', () => controller.align('middle'), count < 1)}\n {act('⤓', 'Align Bottom', () => controller.align('bottom'), count < 1)}\n </div>\n </>\n )}\n </div>\n );\n}\n\nexport interface VectorStylePanelProps {\n controller: VectorEditorController;\n className?: string;\n}\n\nconst selectClass = 'h-7 min-w-0 flex-1 rounded border border-border bg-background px-1 text-xs';\nconst numberClass = 'h-7 w-16 rounded border border-border bg-background px-1.5 text-xs';\n\n/**\n * Fill, stroke, stroke width, alignment and width profile, arrowheads, live corner radius and opacity of the\n * selection (corners of the selected points with the direct tool); with nothing selected it\n * edits the defaults for new shapes.\n */\nexport function VectorStylePanel({ controller, className }: VectorStylePanelProps) {\n const state = useVectorEditorState(controller);\n const style = getVectorSelectionStyle(state);\n const d = state.defaults;\n const source = style ?? {\n fill: d.fill ?? null,\n stroke: d.stroke ?? null,\n strokeWidth: d.strokeWidth ?? 1,\n opacity: 1,\n strokeAlign: d.strokeAlign ?? 'center',\n startArrow: d.startArrow ?? null,\n endArrow: d.endArrow ?? null,\n arrowAlign: d.arrowAlign ?? 'extend',\n startArrowScale: d.startArrowScale ?? 1,\n endArrowScale: d.endArrowScale ?? 1,\n widthProfile: widthProfilePresetId(d.strokeWidthProfile),\n cornerRadius: d.cornerRadius,\n cornerKind: d.cornerKind ?? 'round',\n corners: 1,\n hasOpenPath: true,\n };\n const setCorners = (patch: { radius?: number; kind?: VectorCornerKind }) => {\n if (!style) controller.setDefaults({ ...(patch.radius !== undefined ? { cornerRadius: patch.radius } : {}), ...(patch.kind ? { cornerKind: patch.kind } : {}) });\n else if (patch.radius !== undefined) controller.setCornerRadius(patch.radius);\n else if (patch.kind) controller.setCornerKind(patch.kind);\n };\n const setProfile = (id: VectorWidthPreset) => {\n if (style) controller.setWidthProfile(id);\n else controller.setDefaults({ strokeWidthProfile: widthProfilePreset(id)?.length ? widthProfilePreset(id) : null });\n };\n const mixed = (key: keyof NonNullable<typeof style>['mixed']) => (style?.mixed[key] ? <span className=\"text-[11px] text-muted-foreground\">Mixed</span> : null);\n const arrowRow = (end: 'start' | 'end', label: string) => {\n const key = end === 'start' ? 'startArrow' : 'endArrow';\n const scaleKey = end === 'start' ? 'startArrowScale' : 'endArrowScale';\n return (\n <div className=\"flex items-center gap-2\" data-vector-style={key}>\n <span className=\"w-16 text-xs text-foreground\">{label}</span>\n <select aria-label={`${label} arrowhead`} className={selectClass} value={source[key] ?? ''} onChange={(e) => apply({ [key]: (e.target.value || null) as VectorArrowhead | null })}>\n <option value=\"\">None</option>\n {VECTOR_ARROWHEADS.map((h) => (\n <option key={h} value={h}>\n {VECTOR_ARROWHEAD_LABELS[h]}\n </option>\n ))}\n </select>\n <input\n type=\"number\"\n min={0.1}\n step={0.25}\n aria-label={`${label} arrowhead scale`}\n title=\"Scale (× stroke width)\"\n className={numberClass}\n value={source[scaleKey]}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n > 0) apply({ [scaleKey]: n });\n }}\n />\n </div>\n );\n };\n const apply = (patch: Record<string, unknown>) => {\n if (style) controller.setStyle(patch);\n else controller.setDefaults(patch);\n };\n const paintRow = (key: 'fill' | 'stroke', label: string) => {\n const paint = source[key];\n const hex = vectorPaintToHex(paint);\n const on = paint !== null && paint !== 'none';\n return (\n <div className=\"flex items-center gap-2\" data-vector-style={key}>\n <label className=\"flex w-16 items-center gap-1.5 text-xs text-foreground\">\n <input type=\"checkbox\" checked={on} aria-label={`${label} on`} onChange={(e) => apply({ [key]: e.target.checked ? (hex ?? '#000000') : null })} />\n {label}\n </label>\n <input\n type=\"color\"\n aria-label={`${label} colour`}\n className=\"h-7 w-10 cursor-pointer rounded border border-border bg-background disabled:opacity-40\"\n disabled={!on}\n value={hex ?? '#000000'}\n onChange={(e) => apply({ [key]: e.target.value })}\n />\n {on && !hex && <span className=\"truncate text-[11px] text-muted-foreground\">{typeof paint === 'string' ? paint : 'Gradient'}</span>}\n {style?.mixed[key] && <span className=\"text-[11px] text-muted-foreground\">Mixed</span>}\n </div>\n );\n };\n return (\n <div className={`space-y-2 ${className ?? ''}`} aria-label={style ? 'Selection style' : 'New shape style'}>\n <p className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">{style ? 'Selection' : 'New shapes'}</p>\n {paintRow('fill', 'Fill')}\n {paintRow('stroke', 'Stroke')}\n <label className=\"flex items-center gap-2 text-xs text-foreground\">\n <span className=\"w-16\">Width</span>\n <input\n type=\"number\"\n min={0}\n step={0.5}\n aria-label=\"Stroke width\"\n className=\"h-7 w-20 rounded border border-border bg-background px-1.5 text-xs\"\n value={source.strokeWidth}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n >= 0) apply({ strokeWidth: n });\n }}\n />\n </label>\n <label className=\"flex items-center gap-2 text-xs text-foreground\" data-vector-style=\"strokeAlign\">\n <span className=\"w-16\">Align</span>\n <select aria-label=\"Stroke alignment\" className={selectClass} value={source.strokeAlign} onChange={(e) => apply({ strokeAlign: e.target.value as VectorStrokeAlign })}>\n {(Object.keys(VECTOR_STROKE_ALIGN_LABELS) as VectorStrokeAlign[]).map((a) => (\n <option key={a} value={a}>\n {VECTOR_STROKE_ALIGN_LABELS[a]}\n </option>\n ))}\n </select>\n {mixed('strokeAlign')}\n </label>\n <div className=\"flex items-center gap-2 text-xs text-foreground\" data-vector-style=\"widthProfile\">\n <span className=\"w-16\">Profile</span>\n <select\n aria-label=\"Width profile\"\n className={selectClass}\n value={source.widthProfile}\n onChange={(e) => {\n if (e.target.value !== 'custom') setProfile(e.target.value as VectorWidthPreset);\n }}\n >\n {VECTOR_WIDTH_PRESETS.map((p) => (\n <option key={p.id} value={p.id}>\n {p.label}\n </option>\n ))}\n {source.widthProfile === 'custom' && (\n <option value=\"custom\" disabled>\n Custom\n </option>\n )}\n </select>\n <button\n type=\"button\"\n className={buttonClass}\n title=\"Reset to uniform width\"\n aria-label=\"Reset to uniform width\"\n disabled={source.widthProfile === 'uniform' && !style?.mixed.widthProfile}\n onClick={() => setProfile('uniform')}\n >\n ═\n </button>\n {mixed('widthProfile')}\n </div>\n {source.hasOpenPath && (\n <>\n {arrowRow('start', 'Start')}\n {arrowRow('end', 'End')}\n {(source.startArrow || source.endArrow) && (\n <label className=\"flex items-center gap-2 text-xs text-foreground\" data-vector-style=\"arrowAlign\">\n <span className=\"w-16\">Heads</span>\n <select aria-label=\"Arrowhead alignment\" className={selectClass} value={source.arrowAlign} onChange={(e) => apply({ arrowAlign: e.target.value })}>\n <option value=\"extend\">Tip past end</option>\n <option value=\"tip\">Tip at end</option>\n </select>\n </label>\n )}\n </>\n )}\n {source.corners > 0 && (\n <div className=\"flex items-center gap-2\" data-vector-style=\"corners\">\n <span className=\"w-16 text-xs text-foreground\">Corners</span>\n <input\n type=\"number\"\n min={0}\n step={1}\n aria-label=\"Corner radius\"\n className={numberClass}\n value={Math.round(source.cornerRadius * 100) / 100}\n onChange={(e) => {\n const n = parseFloat(e.target.value);\n if (Number.isFinite(n) && n >= 0) setCorners({ radius: n });\n }}\n />\n <select aria-label=\"Corner kind\" className={selectClass} value={source.cornerKind} onChange={(e) => setCorners({ kind: e.target.value as VectorCornerKind })}>\n {VECTOR_CORNER_KINDS.map((k) => (\n <option key={k} value={k}>\n {VECTOR_CORNER_KIND_LABELS[k]}\n </option>\n ))}\n </select>\n {mixed('cornerRadius')}\n </div>\n )}\n {style && (\n <label className=\"flex items-center gap-2 text-xs text-foreground\">\n <span className=\"w-16\">Opacity</span>\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.05}\n aria-label=\"Opacity\"\n className=\"h-4 flex-1 accent-primary\"\n value={source.opacity}\n onChange={(e) => apply({ opacity: parseFloat(e.target.value) })}\n />\n </label>\n )}\n </div>\n );\n}\n","import React from 'react';\nimport type { VectorEditorController, VectorTool } from '@pixerate/editor/vector';\nimport { VectorCanvas, type VectorCanvasProps } from './VectorCanvas';\nimport { VectorStylePanel, VectorToolbar } from './VectorToolbar';\n\nexport interface VectorEditorProps {\n controller: VectorEditorController;\n /** Tools in the toolbar (default: all). */\n tools?: readonly VectorTool[];\n /** The style sidebar (default `true`). */\n showStylePanel?: boolean;\n /** Canvas height (default 520px). */\n height?: number | string;\n canvasProps?: Omit<VectorCanvasProps, 'controller'>;\n className?: string;\n}\n\n/** Toolbar, canvas and style panel for a `VectorEditorController`. */\nexport function VectorEditor({ controller, tools, showStylePanel = true, height = 520, canvasProps, className }: VectorEditorProps) {\n return (\n <div className={`flex flex-col gap-2 ${className ?? ''}`} data-vector-editor=\"\">\n <VectorToolbar controller={controller} tools={tools} />\n <div className=\"flex min-h-0 flex-col gap-2 md:flex-row\">\n <div className=\"relative min-h-[320px] flex-1 overflow-hidden rounded-md border border-border bg-muted/40\" style={{ height }}>\n <VectorCanvas controller={controller} {...canvasProps} />\n </div>\n {showStylePanel && <VectorStylePanel controller={controller} className=\"w-full shrink-0 rounded-md border border-border p-3 md:w-56\" />}\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":["useEffect","useRef","useRef","useEffect","text","Fragment","jsx","jsxs","jsx","jsxs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/editor-react",
3
- "version": "0.26.0",
3
+ "version": "0.28.0",
4
4
  "description": "React bindings and prompt/rich-text components for @pixerate/editor",
5
5
  "author": "Pixerate",
6
6
  "license": "MIT",
@@ -107,7 +107,7 @@
107
107
  },
108
108
  "peerDependencies": {
109
109
  "@dagrejs/dagre": "^1.1.8",
110
- "@pixerate/editor": ">=0.36.0 <1.0.0-0",
110
+ "@pixerate/editor": ">=0.38.0 <1.0.0-0",
111
111
  "@tiptap/core": "^2.11.5",
112
112
  "@tiptap/pm": "^2.11.5",
113
113
  "@tiptap/react": "^2.11.5",
@@ -134,7 +134,7 @@
134
134
  "tsup": "^8.4.0",
135
135
  "typescript": "^5.7.3",
136
136
  "vitest": "^4.1.11",
137
- "@pixerate/editor": "0.36.0"
137
+ "@pixerate/editor": "0.38.0"
138
138
  },
139
139
  "scripts": {
140
140
  "build": "tsup",