@pixerate/editor-react 0.78.1 → 0.80.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.
Files changed (38) hide show
  1. package/dist/animation-editor/index.cjs +679 -37
  2. package/dist/animation-editor/index.cjs.map +1 -1
  3. package/dist/animation-editor/index.d.cts +29 -3
  4. package/dist/animation-editor/index.d.ts +29 -3
  5. package/dist/animation-editor/index.js +128 -37
  6. package/dist/animation-editor/index.js.map +1 -1
  7. package/dist/{chunk-S5SSL3ZO.js → chunk-VKWTKESA.js} +5 -5
  8. package/dist/{chunk-7RMNM3KC.js → chunk-WOQ3H7KA.js} +4 -4
  9. package/dist/chunk-WOQ3H7KA.js.map +1 -0
  10. package/dist/effects/index.cjs +3 -3
  11. package/dist/effects/index.cjs.map +1 -1
  12. package/dist/effects/index.d.cts +4 -2
  13. package/dist/effects/index.d.ts +4 -2
  14. package/dist/effects/index.js +1 -1
  15. package/dist/image-editor/index.cjs +3 -3
  16. package/dist/image-editor/index.cjs.map +1 -1
  17. package/dist/image-editor/index.js +3 -3
  18. package/dist/index.cjs +3 -3
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.js +3 -3
  21. package/dist/paint-editor/index.cjs +734 -19
  22. package/dist/paint-editor/index.cjs.map +1 -1
  23. package/dist/paint-editor/index.d.cts +22 -3
  24. package/dist/paint-editor/index.d.ts +22 -3
  25. package/dist/paint-editor/index.js +173 -19
  26. package/dist/paint-editor/index.js.map +1 -1
  27. package/dist/vector/index.cjs +649 -9
  28. package/dist/vector/index.cjs.map +1 -1
  29. package/dist/vector/index.d.cts +27 -3
  30. package/dist/vector/index.d.ts +27 -3
  31. package/dist/vector/index.js +98 -9
  32. package/dist/vector/index.js.map +1 -1
  33. package/dist/video-editor/index.cjs +3 -3
  34. package/dist/video-editor/index.cjs.map +1 -1
  35. package/dist/video-editor/index.js +1 -1
  36. package/package.json +3 -3
  37. package/dist/chunk-7RMNM3KC.js.map +0 -1
  38. /package/dist/{chunk-S5SSL3ZO.js.map → chunk-VKWTKESA.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/paint-editor/index.ts","../../src/paint-editor/usePaintEditor.ts","../../src/paint-editor/PaintCanvas.tsx","../../src/paint-editor/PaintToolbar.tsx","../../src/paint-editor/shared.tsx","../../src/paint-editor/BrushPanel.tsx","../../src/paint-editor/PaintGradientEditor.tsx","../../src/paint-editor/PaintGradientEditorView.tsx","../../src/paint-editor/PaperPanel.tsx","../../src/paint-editor/ColorPanel.tsx","../../src/paint-editor/PaintLayersPanel.tsx","../../src/paint-editor/WetPanel.tsx","../../src/paint-editor/StickerPanel.tsx","../../src/paint-editor/PaintEditor.tsx"],"sourcesContent":["export * from './usePaintEditor';\nexport * from './PaintCanvas';\nexport * from './PaintToolbar';\nexport * from './BrushPanel';\nexport * from './PaperPanel';\nexport * from './ColorPanel';\nexport * from './PaintLayersPanel';\nexport * from './WetPanel';\nexport * from './StickerPanel';\nexport * from './PaintEditor';\nexport { PaintSlider } from './shared';\nexport * from './PaintGradientEditor';\n","import { useMemo, useState, useSyncExternalStore } from 'react';\nimport { PaintDirector, PaintEditorController, PaintPresence, type PaintDirectorOptions, type PaintEditorOptions, type PaintEditorState } from '@pixerate/editor/paint-editor';\n\nexport interface UsePaintEditorReturn {\n controller: PaintEditorController;\n /** The controller's snapshot (a new object after every change). */\n state: PaintEditorState;\n}\n\n/**\n * Creates a `PaintEditorController` once (from `options`, read on the first render) or uses the\n * one given, and re-renders on every change.\n */\nexport function usePaintEditor(options: PaintEditorOptions | PaintEditorController = {}): UsePaintEditorReturn {\n const [controller] = useState(() => (options instanceof PaintEditorController ? options : new PaintEditorController(options)));\n const state = usePaintEditorState(controller);\n return useMemo(() => ({ controller, state }), [controller, state]);\n}\n\n/** Subscribes to a controller's state. */\nexport function usePaintEditorState(controller: PaintEditorController): PaintEditorState {\n return useSyncExternalStore(\n (notify) => controller.subscribe(notify),\n () => controller.getState(),\n () => controller.getState()\n );\n}\n\n/**\n * A `PaintPresence` and `PaintDirector` for a paint editor: pass `presence` to `PaintEditor` (or\n * `PaintCanvas`) and `director` to `createPaintEditorToolProvider`, so agent strokes are painted\n * live by a cursor on the canvas. Options are read on the first render.\n */\nexport function usePaintDirector(controller: PaintEditorController, options: Omit<PaintDirectorOptions, 'clock'> = {}): { presence: PaintPresence; director: PaintDirector } {\n const [value] = useState(() => {\n const presence = new PaintPresence();\n return { presence, director: new PaintDirector(controller, presence, options) };\n });\n return value;\n}\n","import React, { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport {\n PaintCanvasPresenter,\n PaintGesture,\n documentToScreen,\n drawWaterOverlay,\n startWetClock,\n fitZoom,\n guideOverlay,\n handlePaintShortcut,\n viewCssTransform,\n type PaintEditorController,\n type PaintPresence,\n type PaintTool,\n type PaintView,\n} from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\n\nexport interface PaintCanvasProps {\n controller: PaintEditorController;\n /** The active tool (default brush). */\n tool?: PaintTool;\n /** Draw the symmetry axes and perspective lines (default true). */\n showGuides?: boolean;\n /** Fit the canvas in the viewport on mount (default true). */\n fitOnMount?: boolean;\n /** Called with a refusal (hidden or locked layer). */\n onError?: (message: string | null) => void;\n /** Agent cursors to draw over the canvas (see `PaintDirector` and `usePaintDirector`). */\n presence?: PaintPresence;\n className?: string;\n}\n\n/**\n * The painting surface: a document-sized canvas the compositor draws into (only changed tiles are\n * uploaded), shown through the view's zoom, pan, rotation and mirroring as a CSS transform (the\n * pixels never resample). Pointer input goes through `PaintGesture`: coalesced samples, a predicted\n * tail drawn as a thin preview, palm rejection, middle-button pan, wheel zoom and Shift+wheel\n * rotation. Guides and floating reference images are drawn on top.\n */\nexport const PaintCanvas: React.FC<PaintCanvasProps> = ({ controller, tool = 'brush', showGuides = true, fitOnMount = true, onError, presence, className }) => {\n const state = usePaintEditorState(controller);\n const viewport = useRef<HTMLDivElement>(null);\n const canvas = useRef<HTMLCanvasElement>(null);\n const water = useRef<HTMLCanvasElement>(null);\n const [size, setSize] = useState({ width: 800, height: 600 });\n const measured = useRef(false);\n const [predicted, setPredicted] = useState<Array<{ x: number; y: number }>>([]);\n const presenter = useMemo(() => new PaintCanvasPresenter(controller), [controller]);\n const gesture = useMemo(\n () =>\n new PaintGesture(controller, () => {\n const r = viewport.current?.getBoundingClientRect();\n return { left: r?.left ?? 0, top: r?.top ?? 0, width: r?.width || size.width, height: r?.height || size.height };\n }),\n // The box reads the element when called; `size` is only the jsdom fallback.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [controller]\n );\n gesture.tool = tool;\n const { canvas: doc } = state.document;\n\n useEffect(() => {\n const el = viewport.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n const ro = new ResizeObserver(() => {\n if (!el.clientWidth || !el.clientHeight) return;\n measured.current = true;\n setSize({ width: el.clientWidth, height: el.clientHeight });\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n // Fit once per canvas size, after the viewport has been measured (or at once where it cannot be).\n const fitted = useRef<string | null>(null);\n useEffect(() => {\n const key = `${doc.width}x${doc.height}`;\n if (!fitOnMount || fitted.current === key) return;\n if (typeof ResizeObserver !== 'undefined' && !measured.current) return;\n fitted.current = key;\n controller.setView({ zoom: fitZoom(doc, size), pan: { x: 0, y: 0 } });\n }, [controller, doc, size, fitOnMount]);\n\n // Upload changed tiles whenever the state changes.\n useEffect(() => {\n const ctx = canvas.current?.getContext('2d');\n if (ctx && typeof ctx.createImageData === 'function') presenter.render(ctx as never);\n else controller.takeDirty();\n }, [state, presenter, controller]);\n\n // Wet paint flows with the display.\n useEffect(() => startWetClock(controller), [controller]);\n\n // The water overlay.\n useEffect(() => {\n const ctx = water.current?.getContext('2d');\n if (ctx && typeof ctx.createImageData === 'function') drawWaterOverlay(controller, ctx as never);\n }, [state, controller]);\n\n // Wheel needs a non-passive listener to prevent page scroll (see GOTCHAS).\n useEffect(() => {\n const el = viewport.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n gesture.wheel(e);\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [gesture]);\n\n const report = () => onError?.(gesture.error);\n const transform = viewCssTransform(state.view, doc, size);\n const lines = showGuides ? guideOverlay(controller) : [];\n\n return (\n <div\n ref={viewport}\n tabIndex={0}\n role=\"application\"\n aria-label=\"Paint canvas\"\n data-testid=\"paint-canvas\"\n className={`relative overflow-hidden bg-slate-950 outline-none touch-none select-none ${className ?? ''}`}\n style={{ cursor: tool === 'pan' ? 'grab' : tool === 'eyedropper' ? 'copy' : 'crosshair' }}\n onPointerDown={(e) => {\n viewport.current?.focus();\n if (gesture.down(e.nativeEvent)) (e.target as Element).setPointerCapture?.(e.pointerId);\n report();\n }}\n onPointerMove={(e) => {\n gesture.move(e.nativeEvent);\n if (gesture.predicted.length || predicted.length) setPredicted(gesture.predicted.map((p) => ({ x: p.x, y: p.y })));\n }}\n onPointerUp={(e) => {\n gesture.up(e.nativeEvent);\n setPredicted([]);\n }}\n onPointerCancel={() => {\n gesture.cancel();\n setPredicted([]);\n }}\n onKeyDown={(e) => {\n if (handlePaintShortcut(controller, gesture, e)) e.preventDefault();\n }}\n >\n <canvas\n ref={canvas}\n width={doc.width}\n height={doc.height}\n className=\"absolute left-0 top-0 shadow-2xl\"\n style={{ transform, transformOrigin: '0 0', imageRendering: state.view.zoom > 2 ? 'pixelated' : 'auto' }}\n />\n {state.wet.overlay && (\n <canvas\n ref={water}\n width={doc.width}\n height={doc.height}\n data-testid=\"paint-water-overlay\"\n className=\"absolute left-0 top-0 pointer-events-none opacity-60\"\n style={{ transform, transformOrigin: '0 0' }}\n />\n )}\n <svg className=\"absolute left-0 top-0 pointer-events-none overflow-visible\" width={doc.width} height={doc.height} style={{ transform, transformOrigin: '0 0' }} aria-hidden=\"true\">\n {lines.map((l, i) => (\n <line\n key={i}\n x1={l.from.x}\n y1={l.from.y}\n x2={l.to.x}\n y2={l.to.y}\n stroke={l.kind === 'symmetry' ? '#22d3ee' : l.kind === 'stencil' ? '#fbbf24' : '#f472b6'}\n strokeOpacity={l.kind === 'symmetry' || l.kind === 'stencil' ? 0.8 : 0.35}\n strokeWidth={1 / state.view.zoom}\n strokeDasharray={l.kind === 'symmetry' ? `${6 / state.view.zoom} ${4 / state.view.zoom}` : undefined}\n />\n ))}\n {predicted.length > 0 && (\n <polyline points={predicted.map((p) => `${p.x},${p.y}`).join(' ')} fill=\"none\" stroke={state.color} strokeOpacity={0.5} strokeWidth={Math.max(1, state.brush.tip.size / 2)} strokeLinecap=\"round\" />\n )}\n </svg>\n {state.guides.references\n .filter((r) => r.visible)\n .map((r) => (\n <ReferencePanel key={r.id} controller={controller} id={r.id} />\n ))}\n {presence && <PaintPresenceLayer presence={presence} view={state.view} canvas={doc} viewport={size} />}\n <div className=\"absolute bottom-1 right-2 text-[10px] text-slate-500 pointer-events-none\" data-testid=\"paint-view-status\">\n {Math.round(state.view.zoom * 100)}% · {Math.round(state.view.rotation)}°{state.view.mirror ? ' · mirrored' : ''}\n </div>\n </div>\n );\n};\n\n/**\n * Agent cursors and notes over the canvas. Positions are document pixels, placed through the view\n * (zoom, pan, rotation, mirroring), while the cursors themselves stay upright and unscaled.\n */\nexport const PaintPresenceLayer: React.FC<{ presence: PaintPresence; view: PaintView; canvas: { width: number; height: number }; viewport: { width: number; height: number } }> = ({ presence, view, canvas, viewport }) => {\n const { actors } = useSyncExternalStore(presence.subscribe, presence.getState, presence.getState);\n return (\n <div className=\"pointer-events-none absolute inset-0 overflow-hidden\" data-paint-presence=\"\" aria-hidden=\"true\">\n {actors.map((a) => {\n const p = documentToScreen(view, canvas, viewport, a.x, a.y);\n return (\n <div key={a.id} className=\"absolute\" style={{ left: p.x, top: p.y }} data-actor={a.id}>\n <svg width=\"18\" height=\"20\" viewBox=\"0 0 18 20\" className=\"drop-shadow-md\" style={{ transform: a.pressed ? 'scale(0.85)' : undefined, transformOrigin: '0 0' }}>\n <path d=\"M0 0 L0 15 L4.5 10.8 L7.6 17 L10.2 15.8 L7.2 9.7 L13.5 9.4 Z\" fill={a.color} stroke=\"white\" strokeWidth=\"1.4\" strokeLinejoin=\"round\" />\n </svg>\n <span className=\"absolute left-4 top-4 w-max max-w-[240px] rounded-md px-2 py-0.5 text-[11px] font-semibold text-white shadow\" style={{ background: a.color }}>\n {a.message ?? a.name}\n </span>\n </div>\n );\n })}\n </div>\n );\n};\n\n/** A floating reference image: drag its title bar to move it, click the image to pick a colour. */\nconst ReferencePanel: React.FC<{ controller: PaintEditorController; id: string }> = ({ controller, id }) => {\n const state = usePaintEditorState(controller);\n const ref = state.guides.references.find((r) => r.id === id);\n const drag = useRef<{ x: number; y: number; ox: number; oy: number } | null>(null);\n if (!ref) return null;\n const h = (ref.height / ref.width) * ref.displayWidth;\n return (\n <div\n className=\"absolute rounded border border-slate-700 bg-slate-900/95 shadow-xl\"\n style={{ left: ref.x, top: ref.y, width: ref.displayWidth }}\n data-testid=\"paint-reference\"\n onPointerDown={(e) => e.stopPropagation()}\n >\n <div\n className=\"flex items-center justify-between px-1.5 py-0.5 text-[10px] text-slate-300 cursor-move\"\n onPointerDown={(e) => {\n drag.current = { x: e.clientX, y: e.clientY, ox: ref.x, oy: ref.y };\n (e.target as Element).setPointerCapture?.(e.pointerId);\n }}\n onPointerMove={(e) => {\n const d = drag.current;\n if (d) controller.updateReferenceImage(id, { x: d.ox + e.clientX - d.x, y: d.oy + e.clientY - d.y });\n }}\n onPointerUp={() => (drag.current = null)}\n >\n <span className=\"truncate\">{ref.name}</span>\n <button type=\"button\" aria-label={`Hide ${ref.name}`} className=\"px-1 text-slate-400 hover:text-white\" onClick={() => controller.updateReferenceImage(id, { visible: false })}>\n ×\n </button>\n </div>\n <img\n src={ref.src}\n alt={ref.name}\n draggable={false}\n width={ref.displayWidth}\n height={h}\n className=\"block cursor-copy\"\n onClick={(e) => {\n const rect = (e.target as HTMLElement).getBoundingClientRect();\n const k = ref.width / (rect.width || ref.displayWidth);\n controller.setColor(controller.pickReferenceColor(id, Math.min(ref.width - 1, (e.clientX - rect.left) * k), Math.min(ref.height - 1, (e.clientY - rect.top) * k)));\n }}\n />\n </div>\n );\n};\n","import React, { useRef, useState } from 'react';\nimport { PAINT_TOOLS, SYMMETRY_MODES, decodeImageBlob, downloadBytes, quickStencil, timeLapseZip, type PaintEditorController, type PaintTool, type SymmetryMode } from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, button, chip, useAttempt } from './shared';\n\nexport interface PaintToolbarProps {\n controller: PaintEditorController;\n tool: PaintTool;\n onToolChange: (tool: PaintTool) => void;\n /** Base name of saved and exported files (default `painting`). */\n fileName?: string;\n className?: string;\n}\n\n/**\n * Tools (brush, eyedropper, pan, rotate view), undo / redo, view rotation, mirroring and reset,\n * the symmetry and perspective guides, stencils (ruler, circle, mask), the tracing image and reference images, the drawing hand,\n * and file actions: save / open JSON, export PNG, JPEG and PSD, a time-lapse (zipped frames, video\n * project and ffmpeg command) and a PNG repainted from the strokes at twice the size.\n */\nexport const PaintToolbar: React.FC<PaintToolbarProps> = ({ controller, tool, onToolChange, fileName = 'painting', className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const [busy, setBusy] = useState<string | null>(null);\n const [note, setNote] = useState<string | null>(null);\n const openRef = useRef<HTMLInputElement>(null);\n const tracingRef = useRef<HTMLInputElement>(null);\n const refRef = useRef<HTMLInputElement>(null);\n const { symmetry, perspective, tracing } = state.guides;\n const { canvas } = state.document;\n\n const exportImage = (format: 'image/png' | 'image/jpeg') =>\n attempt(async () => downloadBytes(await controller.exportImage({ format }), `${fileName}.${format === 'image/png' ? 'png' : 'jpg'}`, format));\n\n return (\n <div className={`flex flex-wrap items-center gap-1.5 text-xs text-slate-200 ${className ?? ''}`} role=\"toolbar\" aria-label=\"Paint toolbar\" data-testid=\"paint-toolbar\">\n {PAINT_TOOLS.map((t) => (\n <button key={t.id} type=\"button\" aria-pressed={tool === t.id} title={`${t.label} (${t.key.toUpperCase()})`} className={chip(tool === t.id)} onClick={() => onToolChange(t.id)}>\n {t.label}\n </button>\n ))}\n <span className=\"mx-1 h-4 w-px bg-slate-700\" />\n <button type=\"button\" className={button} disabled={!state.canUndo} title={state.undoLabel ? `Undo ${state.undoLabel}` : 'Undo'} onClick={() => controller.undo()}>\n Undo\n </button>\n <button type=\"button\" className={button} disabled={!state.canRedo} title={state.redoLabel ? `Redo ${state.redoLabel}` : 'Redo'} onClick={() => controller.redo()}>\n Redo\n </button>\n <span className=\"mx-1 h-4 w-px bg-slate-700\" />\n <button type=\"button\" className={button} aria-label=\"Rotate view left\" onClick={() => controller.setView({ rotation: state.view.rotation - 15 })}>\n ⟲\n </button>\n <button type=\"button\" className={button} aria-label=\"Rotate view right\" onClick={() => controller.setView({ rotation: state.view.rotation + 15 })}>\n ⟳\n </button>\n <button type=\"button\" className={chip(state.view.mirror)} aria-pressed={state.view.mirror} onClick={() => controller.setView({ mirror: !state.view.mirror })}>\n Mirror view\n </button>\n <button type=\"button\" className={button} onClick={() => controller.resetView()}>\n Reset view\n </button>\n <span className=\"mx-1 h-4 w-px bg-slate-700\" />\n <label className=\"flex items-center gap-1\">\n Symmetry\n <select\n aria-label=\"Symmetry\"\n value={symmetry.mode}\n onChange={(e) => controller.setSymmetry({ mode: e.target.value as SymmetryMode, center: symmetry.mode === 'off' ? { x: canvas.width / 2, y: canvas.height / 2 } : symmetry.center })}\n className=\"rounded bg-slate-800 px-1 py-0.5\"\n >\n {SYMMETRY_MODES.map((m) => (\n <option key={m} value={m}>\n {m}\n </option>\n ))}\n </select>\n </label>\n {symmetry.mode === 'kaleidoscope' && (\n <input\n type=\"number\"\n aria-label=\"Kaleidoscope segments\"\n min={2}\n max={32}\n value={symmetry.segments}\n onChange={(e) => controller.setSymmetry({ segments: Number(e.target.value) })}\n className=\"w-12 rounded bg-slate-800 px-1 py-0.5\"\n />\n )}\n <button\n type=\"button\"\n className={chip(perspective.enabled)}\n aria-pressed={perspective.enabled}\n onClick={() =>\n attempt(() =>\n controller.setPerspective(\n perspective.enabled ? { enabled: false } : { enabled: true, points: perspective.points.length ? perspective.points : [{ x: canvas.width / 2, y: canvas.height * 0.4 }] }\n )\n )\n }\n >\n Perspective\n </button>\n {perspective.enabled && (\n <select\n aria-label=\"Vanishing points\"\n value={perspective.points.length}\n onChange={(e) => {\n const n = Number(e.target.value);\n const y = canvas.height * 0.4;\n const pts = n === 1 ? [{ x: canvas.width / 2, y }] : n === 2 ? [{ x: -canvas.width * 0.5, y }, { x: canvas.width * 1.5, y }] : [{ x: -canvas.width * 0.5, y }, { x: canvas.width * 1.5, y }, { x: canvas.width / 2, y: canvas.height * 3 }];\n attempt(() => controller.setPerspective({ points: pts }));\n }}\n className=\"rounded bg-slate-800 px-1 py-0.5\"\n >\n <option value={1}>1-point</option>\n <option value={2}>2-point</option>\n <option value={3}>3-point</option>\n </select>\n )}\n <span className=\"mx-1 h-4 w-px bg-slate-700\" />\n <button type=\"button\" className={button} onClick={() => tracingRef.current?.click()}>\n Tracing image…\n </button>\n {tracing && (\n <>\n <input\n type=\"range\"\n aria-label=\"Tracing opacity\"\n min={0}\n max={1}\n step={0.05}\n value={tracing.opacity}\n onChange={(e) => controller.updateTracing({ opacity: Number(e.target.value) })}\n className=\"w-16 accent-indigo-500\"\n />\n <button type=\"button\" className={chip(tracing.sampleColors)} aria-pressed={tracing.sampleColors} onClick={() => controller.updateTracing({ sampleColors: !tracing.sampleColors })}>\n Trace colours\n </button>\n <button type=\"button\" className={chip(tracing.visible)} aria-pressed={tracing.visible} onClick={() => controller.updateTracing({ visible: !tracing.visible })}>\n Show tracing\n </button>\n <button type=\"button\" className={button} onClick={() => controller.clearTracingImage()}>\n Remove tracing\n </button>\n </>\n )}\n <button type=\"button\" className={button} onClick={() => refRef.current?.click()}>\n Reference…\n </button>\n <span className=\"flex items-center gap-1\" role=\"group\" aria-label=\"Stencils\">\n <button type=\"button\" className={button} title=\"A ruler: strokes that start near it follow it\" onClick={() => attempt(() => controller.addStencil(quickStencil('ruler', canvas)))}>\n Ruler\n </button>\n <button type=\"button\" className={button} title=\"A circle guide: strokes that start near it follow it\" onClick={() => attempt(() => controller.addStencil(quickStencil('circle', canvas)))}>\n Circle\n </button>\n <button type=\"button\" className={button} title=\"An ellipse mask: paint lands only inside it\" onClick={() => attempt(() => controller.addStencil(quickStencil('ellipse-mask', canvas)))}>\n Mask\n </button>\n {state.guides.stencils.length > 0 && (\n <button type=\"button\" className={button} onClick={() => attempt(() => controller.removeStencils())}>\n Clear stencils\n </button>\n )}\n </span>\n <button type=\"button\" className={button} title=\"Which hand holds the pen (palm rejection)\" onClick={() => controller.setHand(state.hand === 'right' ? 'left' : 'right')}>\n {state.hand === 'right' ? 'Right-handed' : 'Left-handed'}\n </button>\n <span className=\"mx-1 h-4 w-px bg-slate-700\" />\n <button type=\"button\" className={button} onClick={() => attempt(() => downloadBytes(JSON.stringify(controller.toJSON()), `${fileName}.paint.json`, 'application/json'))}>\n Save\n </button>\n <button type=\"button\" className={button} onClick={() => openRef.current?.click()}>\n Open…\n </button>\n <button type=\"button\" className={button} onClick={() => exportImage('image/png')}>\n PNG\n </button>\n <button type=\"button\" className={button} onClick={() => exportImage('image/jpeg')}>\n JPEG\n </button>\n <button type=\"button\" className={button} onClick={() => attempt(() => downloadBytes(controller.exportPsd().bytes, `${fileName}.psd`, 'image/vnd.adobe.photoshop'))}>\n PSD\n </button>\n <button\n type=\"button\"\n className={button}\n disabled={busy !== null}\n title=\"Repaint the painting from its strokes as a time-lapse: frames, a video project and the ffmpeg command, zipped\"\n onClick={() =>\n attempt(async () => {\n setBusy('Repainting…');\n try {\n const tl = await controller.timeLapse({ onProgress: (p) => setBusy(`Repainting… ${Math.round(p * 100)}%`) });\n downloadBytes(await timeLapseZip(tl), `${fileName}-timelapse.zip`, 'application/zip');\n setNote(`Time-lapse: ${tl.frames.length} frames, ${(tl.durationMs / 1000).toFixed(1)} s (run render.sh in the zip for the MP4).`);\n } finally {\n setBusy(null);\n }\n })\n }\n >\n Time-lapse\n </button>\n <button\n type=\"button\"\n className={button}\n disabled={busy !== null}\n title=\"Repaint the painting from its strokes at twice the size (more detail, not upscaled)\"\n onClick={() =>\n attempt(async () => {\n setBusy('Repainting at 2×…');\n try {\n downloadBytes(await controller.exportHighResPng({ scale: 2 }), `${fileName}@2x.png`, 'image/png');\n } finally {\n setBusy(null);\n }\n })\n }\n >\n PNG 2×\n </button>\n {(busy ?? note) && (\n <span className=\"text-[11px] text-slate-400\" data-testid=\"paint-replay-status\">\n {busy ?? note}\n </span>\n )}\n <input\n ref={openRef}\n type=\"file\"\n accept=\".json,application/json\"\n aria-label=\"Open painting\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) attempt(async () => controller.loadJSON(JSON.parse(await f.text())));\n e.target.value = '';\n }}\n />\n <input\n ref={tracingRef}\n type=\"file\"\n accept=\"image/*\"\n aria-label=\"Load tracing image\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) attempt(async () => controller.setTracingImage({ pixels: await decodeImageBlob(f) }));\n e.target.value = '';\n }}\n />\n <input\n ref={refRef}\n type=\"file\"\n accept=\"image/*\"\n aria-label=\"Add reference image\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) attempt(async () => controller.addReferenceImage({ pixels: await decodeImageBlob(f), name: f.name }));\n e.target.value = '';\n }}\n />\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React, { useEffect, useRef, useState } from 'react';\nimport type { SliderControl } from '@pixerate/editor/paint-editor';\n\nexport const chip = (on: boolean) => `px-2 py-1 rounded text-[11px] ${on ? 'bg-indigo-600 text-white' : 'bg-slate-800 text-slate-300 hover:text-white'}`;\nexport const button = 'px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-200 hover:bg-slate-700 disabled:opacity-40';\nexport const panel = 'flex flex-col gap-2 text-xs text-slate-200';\n\n/** Draws RGBA pixels into a canvas (nothing without a 2D context, as in jsdom). */\nexport const PixelCanvas: React.FC<{ pixels: { width: number; height: number; data: Uint8ClampedArray } | null; label: string; className?: string; style?: React.CSSProperties }> = ({ pixels, label, className, style }) => {\n const ref = useRef<HTMLCanvasElement>(null);\n useEffect(() => {\n const canvas = ref.current;\n const ctx = canvas?.getContext('2d');\n if (!canvas || !ctx || !pixels || typeof ctx.createImageData !== 'function') return;\n canvas.width = pixels.width;\n canvas.height = pixels.height;\n const img = ctx.createImageData(pixels.width, pixels.height);\n img.data.set(pixels.data);\n ctx.putImageData(img, 0, 0);\n }, [pixels]);\n return <canvas ref={ref} role=\"img\" aria-label={label} className={className} style={style} width={pixels?.width} height={pixels?.height} />;\n};\n\nconst fmt = (c: SliderControl, v: number) => (c.step >= 1 ? String(Math.round(v)) : v.toFixed(2));\n\n/**\n * A labelled range input. `onChange` runs while dragging; `onCommit` (if given) runs once on\n * release (the native `change` event), for settings that are undo steps.\n */\nexport const PaintSlider: React.FC<{ control: SliderControl; value: number; onChange?: (v: number) => void; onCommit?: (v: number) => void }> = ({ control, value, onChange, onCommit }) => {\n const [draft, setDraft] = useState<number | null>(null);\n const ref = useRef<HTMLInputElement>(null);\n const commit = useRef(onCommit);\n commit.current = onCommit;\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const done = () => {\n commit.current?.(Number(el.value));\n setDraft(null);\n };\n el.addEventListener('change', done);\n return () => el.removeEventListener('change', done);\n }, []);\n const shown = draft ?? value;\n return (\n <label className=\"flex flex-col gap-0.5\" data-path={control.path}>\n <span className=\"flex justify-between text-slate-400\">\n <span>{control.label}</span>\n <span className=\"font-mono\">{fmt(control, shown)}</span>\n </span>\n <input\n ref={ref}\n type=\"range\"\n aria-label={control.label}\n min={control.min}\n max={control.max}\n step={control.step}\n value={shown}\n onChange={(e) => {\n const v = Number(e.target.value);\n if (onCommit) setDraft(v);\n onChange?.(v);\n }}\n className=\"w-full accent-indigo-500\"\n />\n </label>\n );\n};\n\n/** Runs `fn`, turning a thrown error into a message. */\nexport function useAttempt(): [string | null, (fn: () => unknown) => void, (msg: string | null) => void] {\n const [error, setError] = useState<string | null>(null);\n const attempt = (fn: () => unknown) => {\n try {\n setError(null);\n const r = fn();\n if (r && typeof (r as Promise<unknown>).catch === 'function') (r as Promise<unknown>).catch((e) => setError(e instanceof Error ? e.message : String(e)));\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n }\n };\n return [error, attempt, setError];\n}\n\nexport const ErrorLine: React.FC<{ error: string | null }> = ({ error }) =>\n error ? (\n <p role=\"alert\" className=\"text-[11px] text-rose-400\">\n {error}\n </p>\n ) : null;\n\n/** A colour input that commits once when the picker closes (the native `change` event). */\nexport const CommitColorInput: React.FC<{ value: string; label: string; onCommit: (v: string) => void; className?: string }> = ({ value, label, onCommit, className }) => {\n const ref = useRef<HTMLInputElement>(null);\n const commit = useRef(onCommit);\n commit.current = onCommit;\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const done = () => commit.current(el.value);\n el.addEventListener('change', done);\n return () => el.removeEventListener('change', done);\n }, []);\n return <input ref={ref} type=\"color\" aria-label={label} defaultValue={value} key={value} className={className} />;\n};\n","import React, { useMemo, useRef, useState } from 'react';\nimport {\n BLEND_MENU_GROUPS,\n BRUSH_ROTATIONS,\n BRUSH_SLIDERS,\n brushEngineControls,\n brushLoadColor,\n downloadBytes,\n brushTakesPaint,\n patchBrushValue,\n patchPath,\n readPath,\n WET_TOOLS,\n WET_TOOL_LABELS,\n WET_MEDIA,\n WET_MEDIUM_LABELS,\n IMPASTO_TOOLS,\n IMPASTO_TOOL_LABELS,\n PARTICLE_KINDS,\n PARTICLE_KIND_LABELS,\n PARTICLE_RENDERS,\n PARTICLE_RENDER_LABELS,\n STAMP_KINDS,\n STAMP_LABELS,\n toggleStamp,\n type ParticleKind,\n type ParticleRender,\n type ImpastoTool,\n type WetMediumKind,\n type BlendMode,\n type BrushRotation,\n type WetTool,\n type PaintEditorController,\n} from '@pixerate/editor/paint-editor';\nimport { DEFAULT_PAINT_GRADIENT } from '@pixerate/editor/paint-editor';\nimport { PaintGradientEditor } from './PaintGradientEditor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, PaintSlider, PixelCanvas, button, chip, panel, useAttempt } from './shared';\n\nexport interface BrushPanelProps {\n controller: PaintEditorController;\n /** Thumbnail size in px (default 112 × 32). */\n thumbnailWidth?: number;\n thumbnailHeight?: number;\n className?: string;\n}\n\n/**\n * The brush library (thumbnails rendered from a test stroke on the current paper, grouped by\n * category) and the active brush's settings: size, opacity, flow, hardness, spacing, roundness,\n * angle, paper grain, position and pressure smoothing, dynamics, rotation mode and blend mode;\n * then the engine's own controls (`brushEngineControls`): blender strength and blend distance,\n * smudge strength and length, pick-up and mix ratios, RGB / pigment mixing, dirty brush,\n * the brush's own gradient paint (the multi-colour brush) and the brush load. Save the edited brush, import and export libraries as JSON.\n */\nexport const BrushPanel: React.FC<BrushPanelProps> = ({ controller, thumbnailWidth = 112, thumbnailHeight = 32, className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const [saveName, setSaveName] = useState('');\n const fileRef = useRef<HTMLInputElement>(null);\n const { brush, brushes } = state;\n const paper = state.document.paper;\n const thumbs = useMemo(\n () => new Map(brushes.map((b) => [b.id, controller.brushThumbnail(b.id, { width: thumbnailWidth, height: thumbnailHeight, color: '#26324a' })])),\n // Thumbnails follow the library and the paper.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [controller, brushes, paper, thumbnailWidth, thumbnailHeight]\n );\n const engine = brushEngineControls(brush);\n const carried = brushLoadColor(state.mixerLoad);\n const slug = (name: string) => name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 60) || 'brush';\n\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"brush-panel\">\n <div className=\"grid grid-cols-2 gap-1\" role=\"listbox\" aria-label=\"Brushes\">\n {brushes.map((b) => (\n <button\n key={b.id}\n type=\"button\"\n role=\"option\"\n aria-selected={brush.id === b.id}\n title={`${b.name} (${b.category})`}\n className={`flex flex-col items-start gap-0.5 rounded p-1 text-left ${brush.id === b.id ? 'bg-indigo-600/30 ring-1 ring-indigo-500' : 'bg-slate-900 hover:bg-slate-800'}`}\n onClick={() => controller.setBrush({ id: b.id })}\n >\n <PixelCanvas pixels={thumbs.get(b.id) ?? null} label={`${b.name} thumbnail`} className=\"rounded\" style={{ width: '100%', aspectRatio: `${thumbnailWidth} / ${thumbnailHeight}` }} />\n <span className=\"truncate text-[10px] text-slate-300\">{b.name}</span>\n </button>\n ))}\n </div>\n <div className=\"flex flex-col gap-1.5\">\n {BRUSH_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(brush, c.path)} onChange={(v) => controller.setBrush(patchPath(brush as never, c.path, v) as never)} />\n ))}\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Rotation</span>\n <select aria-label=\"Brush rotation\" value={brush.rotation} onChange={(e) => controller.setBrush({ rotation: e.target.value as BrushRotation })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {BRUSH_ROTATIONS.map((r) => (\n <option key={r} value={r}>\n {r === 'stroke' ? 'Follow stroke' : r === 'barrel' ? 'Pen barrel' : 'Fixed'}\n </option>\n ))}\n </select>\n </label>\n <label className=\"flex items-center gap-2\">\n <input type=\"checkbox\" checked={brush.tip.pressureSize} onChange={(e) => controller.setBrush({ tip: { pressureSize: e.target.checked } })} /> Pressure → size\n </label>\n <label className=\"flex items-center gap-2\">\n <input type=\"checkbox\" checked={brush.tip.pressureOpacity} onChange={(e) => controller.setBrush({ tip: { pressureOpacity: e.target.checked } })} /> Pressure → opacity\n </label>\n {brush.engine === 'dab' && (\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Blend</span>\n <select aria-label=\"Brush blend\" value={brush.tip.blend} onChange={(e) => controller.setBrush({ tip: { blend: e.target.value as BlendMode } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {BLEND_MENU_GROUPS.map((g) => (\n <optgroup key={g.label} label={g.label}>\n {g.modes.map((m) => (\n <option key={m.id} value={m.id} title={m.description}>\n {m.label}\n </option>\n ))}\n </optgroup>\n ))}\n </select>\n </label>\n )}\n </div>\n {engine && (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"brush-engine\">\n <span className=\"font-medium text-slate-300\">{engine.title}</span>\n {engine.wetTool && (\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Wet tool</span>\n <select aria-label=\"Wet tool\" value={brush.wet.tool} onChange={(e) => controller.setBrush({ wet: { tool: e.target.value as WetTool } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {WET_TOOLS.map((t) => (\n <option key={t} value={t}>\n {WET_TOOL_LABELS[t]}\n </option>\n ))}\n </select>\n </label>\n )}\n {engine.wetTool && (\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Medium</span>\n <select aria-label=\"Wet medium\" value={brush.wet.medium} onChange={(e) => controller.setBrush({ wet: { medium: e.target.value as WetMediumKind } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {WET_MEDIA.map((m) => (\n <option key={m} value={m}>\n {WET_MEDIUM_LABELS[m]}\n </option>\n ))}\n </select>\n </label>\n )}\n {engine.particleMenus && (\n <>\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Particles</span>\n <select aria-label=\"Particle kind\" value={brush.particle.kind} onChange={(e) => controller.setBrush({ particle: { kind: e.target.value as ParticleKind } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {PARTICLE_KINDS.map((k) => (\n <option key={k} value={k}>\n {PARTICLE_KIND_LABELS[k]}\n </option>\n ))}\n </select>\n </label>\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Drawn as</span>\n <select aria-label=\"Particle render\" value={brush.particle.render} onChange={(e) => controller.setBrush({ particle: { render: e.target.value as ParticleRender } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {PARTICLE_RENDERS.map((k) => (\n <option key={k} value={k}>\n {PARTICLE_RENDER_LABELS[k]}\n </option>\n ))}\n </select>\n </label>\n </>\n )}\n {engine.stickerStamps && (\n <div className=\"flex flex-wrap gap-1\" role=\"group\" aria-label=\"Sticker stamps\">\n {STAMP_KINDS.map((k) => (\n <button\n key={k}\n type=\"button\"\n aria-pressed={brush.sticker.stamps.includes(k)}\n className={`px-1.5 py-0.5 rounded text-[10px] ${brush.sticker.stamps.includes(k) ? 'bg-indigo-600 text-white' : 'bg-slate-800 text-slate-300'}`}\n onClick={() => controller.setBrush({ sticker: { stamps: toggleStamp(brush.sticker.stamps, k) } })}\n >\n {STAMP_LABELS[k]}\n </button>\n ))}\n </div>\n )}\n {engine.impastoTool && (\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Tool</span>\n <select aria-label=\"Impasto tool\" value={brush.impasto.tool} onChange={(e) => controller.setBrush({ impasto: { tool: e.target.value as ImpastoTool } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {IMPASTO_TOOLS.map((t) => (\n <option key={t} value={t}>\n {IMPASTO_TOOL_LABELS[t]}\n </option>\n ))}\n </select>\n </label>\n )}\n {engine.sliders.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(brush, c.path)} onChange={(v) => controller.setBrush(patchPath(brush as never, c.path, v) as never)} />\n ))}\n {engine.mixingPath && (\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Mixing</span>\n <select\n aria-label=\"Brush mixing\"\n value={engine.mixingPath === 'blender.mixing' ? brush.blender.mixing : engine.mixingPath === 'smudge.mixing' ? brush.smudge.mixing : brush.behavior.mixing}\n onChange={(e) => controller.setBrush(patchBrushValue(brush, engine.mixingPath!, e.target.value))}\n className=\"rounded bg-slate-800 px-1 py-0.5\"\n >\n <option value=\"pigment\">Pigment</option>\n <option value=\"rgb\">RGB</option>\n </select>\n </label>\n )}\n {engine.dirty && (\n <label className=\"flex items-center gap-2\" title=\"Keep the colour the brush picked up for the next stroke (needs Pick-up above 0)\">\n <input type=\"checkbox\" aria-label=\"Dirty brush\" checked={brush.behavior.dirty} onChange={(e) => controller.setBrush({ behavior: { dirty: e.target.checked } })} /> Dirty brush\n </label>\n )}\n {brushTakesPaint(brush) && (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"brush-gradient\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\" title=\"A gradient of the brush's own, used instead of the paint (the multi-colour brush)\">\n Brush gradient\n </span>\n <button\n type=\"button\"\n aria-pressed={brush.paint !== null}\n className={chip(brush.paint !== null)}\n onClick={() => attempt(() => controller.setBrush({ paint: brush.paint ? null : DEFAULT_PAINT_GRADIENT }))}\n >\n {brush.paint ? 'On' : 'Off'}\n </button>\n </div>\n {brush.paint && <PaintGradientEditor value={brush.paint} colors={{ paint: state.color, secondary: state.secondaryColor }} onChange={(g) => attempt(() => controller.setBrush({ paint: g }))} />}\n </div>\n )}\n {engine.load && (\n <div className=\"flex items-center gap-1\">\n <span className=\"text-slate-400\">Carries</span>\n <span aria-label=\"Brush load\" title={carried ?? 'Clean'} className=\"h-4 w-4 rounded ring-1 ring-slate-700\" style={{ background: carried ?? 'transparent' }} />\n {brush.engine === 'mixer' && (\n <button type=\"button\" className={button} onClick={() => controller.loadMixerBrush()}>\n Load\n </button>\n )}\n <button type=\"button\" className={button} onClick={() => controller.cleanMixerBrush(brush.engine === 'mixer')}>\n Clean\n </button>\n </div>\n )}\n </div>\n )}\n <div className=\"flex flex-wrap items-center gap-1\">\n <input value={saveName} placeholder=\"Brush name\" aria-label=\"Brush name\" onChange={(e) => setSaveName(e.target.value)} className=\"w-28 rounded bg-slate-800 px-1.5 py-0.5\" />\n <button type=\"button\" className={button} disabled={!saveName.trim()} onClick={() => attempt(() => (controller.saveBrush({ id: slug(saveName), name: saveName.trim() }), setSaveName('')))}>\n Save brush\n </button>\n <button type=\"button\" className={button} onClick={() => attempt(() => downloadBytes(JSON.stringify(controller.exportBrushes(), null, 2), 'brushes.json', 'application/json'))}>\n Export\n </button>\n <button type=\"button\" className={button} onClick={() => fileRef.current?.click()}>\n Import…\n </button>\n <input\n ref={fileRef}\n type=\"file\"\n accept=\".json,application/json\"\n aria-label=\"Import brushes\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) attempt(async () => controller.importBrushes(JSON.parse(await f.text())));\n e.target.value = '';\n }}\n />\n </div>\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React from 'react';\nimport { PAINT_GRADIENT_KIT } from '@pixerate/editor/paint-editor';\nimport { PaintGradientEditorView, type PaintGradientEditorProps } from './PaintGradientEditorView';\n\nexport type { PaintGradientEditorProps } from './PaintGradientEditorView';\n\n/** The gradient paint editor (see `PaintGradientEditorView`). */\nexport const PaintGradientEditor: React.FC<PaintGradientEditorProps> = (props) => <PaintGradientEditorView {...props} kit={PAINT_GRADIENT_KIT} />;\n","import React, { useState } from 'react';\nimport type { PaintGradientKit, PaintGradientMappingKind, PaintGradientRepeat, PaintGradientSource, PaintGradientSpace } from '@pixerate/editor/paint-editor';\n\nexport interface PaintGradientEditorProps {\n value: PaintGradientSource;\n onChange: (paint: PaintGradientSource) => void;\n /** What `paint` / `secondary` stops show as (the editor's two colours). */\n colors: { paint: string; secondary: string };\n className?: string;\n}\n\nexport interface PaintGradientEditorViewProps extends PaintGradientEditorProps {\n /** The gradient helpers (`PAINT_GRADIENT_KIT`, from the editor's own entry). */\n kit: PaintGradientKit;\n}\n\nconst button = 'px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-200 hover:bg-slate-700 disabled:opacity-40';\nconst select = 'rounded bg-slate-800 px-1 py-0.5 text-[11px]';\nconst number = 'w-16 rounded bg-slate-800 px-1 py-0.5 text-[11px]';\nconst pct = (v: number) => Math.round(v * 1000) / 10;\n\n/**\n * Gradient paint editor (the vector editor's stop ramp, for paint): click the ramp to add a stop,\n * pick a stop to edit its colour (or the paint / second colour), opacity, position and midpoint;\n * the mixing space, what moves the stroke along it (distance with length and repeat, pressure,\n * tilt, speed, direction, time, across the tip, random), softness, reverse, and starting presets.\n */\nexport const PaintGradientEditorView: React.FC<PaintGradientEditorViewProps> = ({ value, onChange, colors, className, kit }) => {\n const {\n PAINT_GRADIENT_MAPPINGS,\n PAINT_GRADIENT_MAPPING_LABELS,\n PAINT_GRADIENT_PRESETS,\n PAINT_GRADIENT_REPEATS,\n PAINT_GRADIENT_REPEAT_LABELS,\n PAINT_GRADIENT_SPACES,\n PAINT_GRADIENT_SPACE_LABELS,\n addPaintGradientStop,\n paintGradientMappingFor,\n paintSourceCss,\n removePaintGradientStop,\n reversePaintGradient,\n updatePaintGradientStop,\n } = kit;\n const [selected, setSelected] = useState(0);\n const sel = Math.min(selected, value.stops.length - 1);\n const stop = value.stops[sel];\n const map = value.map;\n const stopHex = (c: string) => (c === 'paint' ? colors.paint : c === 'secondary' ? colors.secondary : c);\n const patchStop = (patch: Parameters<PaintGradientKit['updatePaintGradientStop']>[2]) => {\n const r = updatePaintGradientStop(value, sel, patch);\n setSelected(r.index);\n onChange(r.paint);\n };\n return (\n <div className={`flex flex-col gap-1.5 text-xs text-slate-200 ${className ?? ''}`} data-testid=\"paint-gradient-editor\" aria-label=\"Gradient paint\">\n <div className=\"flex items-center gap-1\">\n <select aria-label=\"Gradient preset\" className={select} value=\"\" onChange={(e) => e.target.value && (setSelected(0), onChange(PAINT_GRADIENT_PRESETS[Number(e.target.value)].paint))}>\n <option value=\"\">Presets…</option>\n {PAINT_GRADIENT_PRESETS.map((p, i) => (\n <option key={p.name} value={i}>\n {p.name}\n </option>\n ))}\n </select>\n <button type=\"button\" className={button} onClick={() => onChange(reversePaintGradient(value))}>\n Reverse\n </button>\n </div>\n <div\n role=\"slider\"\n tabIndex={0}\n aria-label=\"Gradient ramp: click to add a stop\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={pct(stop.offset)}\n data-testid=\"paint-gradient-ramp\"\n className=\"relative h-6 cursor-copy rounded ring-1 ring-slate-700\"\n style={{ background: paintSourceCss(value, colors) }}\n onClick={(e) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const r = addPaintGradientStop(value, rect.width ? (e.clientX - rect.left) / rect.width : 0.5, colors);\n if (r.index >= 0) {\n setSelected(r.index);\n onChange(r.paint);\n }\n }}\n />\n <div className=\"relative h-4\" aria-label=\"Stops\">\n {value.stops.map((s, i) => (\n <button\n key={i}\n type=\"button\"\n aria-label={`Stop ${i + 1} at ${pct(s.offset)}%`}\n aria-pressed={i === sel}\n className={`absolute top-0 h-4 w-3 -translate-x-1/2 rounded-sm ring-1 ${i === sel ? 'ring-white' : 'ring-slate-600'}`}\n style={{ left: `${s.offset * 100}%`, background: stopHex(s.color) }}\n onClick={() => setSelected(i)}\n />\n ))}\n </div>\n <div className=\"flex flex-wrap items-center gap-1\" data-testid=\"paint-gradient-stop\">\n <select aria-label=\"Stop colour source\" className={select} value={stop.color === 'paint' || stop.color === 'secondary' ? stop.color : 'color'} onChange={(e) => patchStop({ color: e.target.value === 'color' ? stopHex(stop.color) : e.target.value })}>\n <option value=\"color\">Colour</option>\n <option value=\"paint\">Paint colour</option>\n <option value=\"secondary\">Second colour</option>\n </select>\n {stop.color !== 'paint' && stop.color !== 'secondary' && <input type=\"color\" aria-label=\"Stop colour\" value={stop.color} onChange={(e) => patchStop({ color: e.target.value })} className=\"h-6 w-8 rounded bg-transparent\" />}\n <label className=\"flex items-center gap-1\">\n At\n <input type=\"number\" aria-label=\"Stop position\" min={0} max={100} step={1} value={pct(stop.offset)} onChange={(e) => patchStop({ offset: Number(e.target.value) / 100 })} className={number} />%\n </label>\n <label className=\"flex items-center gap-1\">\n Opacity\n <input type=\"number\" aria-label=\"Stop opacity\" min={0} max={100} step={5} value={pct(stop.opacity ?? 1)} onChange={(e) => patchStop({ opacity: Number(e.target.value) / 100 })} className={number} />%\n </label>\n {sel < value.stops.length - 1 && (\n <label className=\"flex items-center gap-1\">\n Midpoint\n <input type=\"number\" aria-label=\"Stop midpoint\" min={5} max={95} step={1} value={pct(stop.midpoint ?? 0.5)} onChange={(e) => patchStop({ midpoint: Number(e.target.value) / 100 })} className={number} />%\n </label>\n )}\n <button type=\"button\" className={button} disabled={value.stops.length <= 2} onClick={() => (setSelected(Math.max(0, sel - 1)), onChange(removePaintGradientStop(value, sel)))}>\n Remove stop\n </button>\n </div>\n <div className=\"flex flex-wrap items-center gap-1\" data-testid=\"paint-gradient-mapping\">\n <select aria-label=\"Gradient follows\" className={select} value={map.by} onChange={(e) => onChange({ ...value, map: paintGradientMappingFor(e.target.value as PaintGradientMappingKind, map) })}>\n {PAINT_GRADIENT_MAPPINGS.map((m) => (\n <option key={m} value={m}>\n {PAINT_GRADIENT_MAPPING_LABELS[m]}\n </option>\n ))}\n </select>\n {map.by === 'distance' && (\n <>\n <input type=\"number\" aria-label=\"Gradient length\" min={1} max={100000} value={map.length} onChange={(e) => onChange({ ...value, map: { ...map, length: Math.max(1, Number(e.target.value) || 1) } })} className={number} />\n <select aria-label=\"Gradient length unit\" className={select} value={map.unit ?? 'px'} onChange={(e) => onChange({ ...value, map: { ...map, unit: e.target.value as 'px' | 'dabs' } })}>\n <option value=\"px\">px</option>\n <option value=\"dabs\">dabs</option>\n </select>\n </>\n )}\n {map.by === 'time' && <input type=\"number\" aria-label=\"Gradient duration\" min={1} max={600000} value={map.duration} onChange={(e) => onChange({ ...value, map: { ...map, duration: Math.max(1, Number(e.target.value) || 1) } })} className={number} />}\n {map.by === 'random' && <input type=\"number\" aria-label=\"Dabs per pick\" min={1} max={500} value={map.every ?? 1} onChange={(e) => onChange({ ...value, map: { ...map, every: Math.max(1, Math.round(Number(e.target.value) || 1)) } })} className={number} />}\n {(map.by === 'distance' || map.by === 'time') && (\n <select aria-label=\"Gradient repeat\" className={select} value={map.repeat ?? 'clamp'} onChange={(e) => onChange({ ...value, map: { ...map, repeat: e.target.value as PaintGradientRepeat } })}>\n {PAINT_GRADIENT_REPEATS.map((r) => (\n <option key={r} value={r}>\n {PAINT_GRADIENT_REPEAT_LABELS[r]}\n </option>\n ))}\n </select>\n )}\n </div>\n <div className=\"flex items-center gap-1\">\n <select aria-label=\"Gradient mixing\" className={select} value={value.space} onChange={(e) => onChange({ ...value, space: e.target.value as PaintGradientSpace })}>\n {PAINT_GRADIENT_SPACES.map((s) => (\n <option key={s} value={s}>\n {PAINT_GRADIENT_SPACE_LABELS[s]}\n </option>\n ))}\n </select>\n <label className=\"flex flex-1 items-center gap-1\">\n Softness\n <input type=\"range\" aria-label=\"Gradient softness\" min={0} max={1} step={0.05} value={value.softness ?? 1} onChange={(e) => onChange({ ...value, softness: Number(e.target.value) })} className=\"flex-1 accent-indigo-500\" />\n </label>\n </div>\n </div>\n );\n};\n","import React, { useMemo } from 'react';\nimport { LIGHT_SLIDERS, PAPER_FAMILIES, PAPER_LIBRARY, PAPER_SLIDERS, patchPath, readPath, renderPaper, type PaintEditorController } from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { CommitColorInput, ErrorLine, PaintSlider, PixelCanvas, panel, useAttempt } from './shared';\n\nexport interface PaperPanelProps {\n controller: PaintEditorController;\n className?: string;\n}\n\nconst SWATCH = { x: 0, y: 0, width: 64, height: 40 };\n\n/**\n * The paper library by family (each a generated grain preview) and the current paper's colour,\n * grain depth, scale, shading and contrast, the wet-media properties and metallic sheen (each\n * change one undo step; sliders commit on release); then the light for thick paint and metallic\n * paper (not an undo step) and Flatten relief for the active layer.\n */\nexport const PaperPanel: React.FC<PaperPanelProps> = ({ controller, className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const paper = state.document.paper;\n const previews = useMemo(() => new Map(PAPER_LIBRARY.map((p) => [p.preset, { ...SWATCH, data: renderPaper({ ...p, shading: Math.max(0.8, p.shading) }, SWATCH) }])), []);\n\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"paper-panel\">\n {PAPER_FAMILIES.map((family) => (\n <div key={family}>\n <div className=\"mb-0.5 text-[10px] uppercase tracking-wide text-slate-500\">{family}</div>\n <div className=\"flex flex-wrap gap-1\" role=\"listbox\" aria-label={`${family} papers`}>\n {PAPER_LIBRARY.filter((p) => p.family === family).map((p) => (\n <button\n key={p.preset}\n type=\"button\"\n role=\"option\"\n aria-selected={paper.preset === p.preset}\n title={p.name}\n className={`rounded p-0.5 ${paper.preset === p.preset ? 'ring-2 ring-indigo-500' : 'ring-1 ring-slate-700 hover:ring-slate-500'}`}\n onClick={() => attempt(() => controller.setPaper({ preset: p.preset }))}\n >\n <PixelCanvas pixels={previews.get(p.preset) ?? null} label={p.name} style={{ width: 48, height: 30 }} />\n </button>\n ))}\n </div>\n </div>\n ))}\n <div className=\"text-slate-300\">{paper.name}</div>\n <label className=\"flex items-center justify-between\">\n <span className=\"text-slate-400\">Colour</span>\n <CommitColorInput label=\"Paper colour\" value={paper.color} onCommit={(v) => attempt(() => controller.setPaper({ color: v }))} className=\"h-6 w-10 rounded bg-transparent\" />\n </label>\n {PAPER_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(paper, c.path)} onCommit={(v) => attempt(() => controller.setPaper(patchPath(paper as never, c.path, v) as never))} />\n ))}\n <label className=\"flex items-center gap-2\">\n <input type=\"checkbox\" checked={paper.tiling === 'mirror'} onChange={(e) => attempt(() => controller.setPaper({ tiling: e.target.checked ? 'mirror' : 'repeat' }))} /> Mirror tiling\n </label>\n <button type=\"button\" className=\"self-start px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-200 hover:bg-slate-700\" onClick={() => attempt(() => controller.setPaper({ seed: paper.seed + 1 }))}>\n New sheet\n </button>\n <div className=\"flex flex-col gap-1.5\" data-testid=\"light-panel\">\n <span className=\"font-medium text-slate-300\">Light (thick paint, metallic paper)</span>\n {LIGHT_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(controller.getLighting(), c.path)} onChange={(v) => attempt(() => controller.setLighting({ [c.path]: v }))} />\n ))}\n <button type=\"button\" className=\"self-start px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-200 hover:bg-slate-700\" onClick={() => attempt(() => controller.flattenRelief())}>\n Flatten relief\n </button>\n </div>\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React, { useMemo, useRef, useState } from 'react';\nimport {\n HARMONY_KINDS,\n MIXING_PAD_HEIGHT,\n MIXING_PAD_WIDTH,\n PAD_SAMPLE_SIZES,\n hsvToRgb,\n padSampleRadius,\n hueToWheel,\n parseHexColor,\n renderColorWheel,\n rgbToHexColor,\n rgbToHsv,\n wheelPick,\n wheelPoint,\n type ColorWheel,\n type HarmonyKind,\n type PaintEditorController,\n} from '@pixerate/editor/paint-editor';\nimport { DEFAULT_PAINT_GRADIENT, paintSourceCss } from '@pixerate/editor/paint-editor';\nimport { PaintGradientEditor } from './PaintGradientEditor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, PixelCanvas, button, chip, panel, useAttempt } from './shared';\n\nexport interface ColorPanelProps {\n controller: PaintEditorController;\n /** Wheel diameter in px (default 168). */\n wheelSize?: number;\n /** Show the mixing pad (default true). */\n mixingPad?: boolean;\n className?: string;\n}\n\ntype PadTool = 'paint' | 'knife' | 'pick';\n\n/**\n * Colour: a hue wheel (painter's RYB or RGB) with the chosen harmony marked on it, saturation and\n * value, the paint and second colours, harmony chips, swatches, and a mixing pad to paint on,\n * smear with a palette knife (pigment mixing) and pick from (with a sample size), mix the paint\n * and second colours in measured parts on, and keep by name.\n */\nexport const ColorPanel: React.FC<ColorPanelProps> = ({ controller, wheelSize = 168, mixingPad = true, className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const [wheel, setWheel] = useState<ColorWheel>('ryb');\n const [kind, setKind] = useState<HarmonyKind>('complementary');\n const [padTool, setPadTool] = useState<PadTool>('paint');\n const [sample, setSample] = useState(3);\n const [parts, setParts] = useState<[number, number]>([1, 1]);\n const [padName, setPadName] = useState('');\n const padPoints = useRef<Array<{ x: number; y: number; pressure?: number }> | null>(null);\n const ring = useMemo(() => renderColorWheel(wheelSize, wheel), [wheelSize, wheel]);\n const color = state.color;\n const harmony = useMemo(() => controller.harmony(kind, { color, wheel }), [controller, kind, color, wheel]);\n const [r, g, b] = parseHexColor(color);\n const hsv = rgbToHsv(r, g, b);\n const pad = useMemo(() => ({ width: MIXING_PAD_WIDTH, height: MIXING_PAD_HEIGHT, data: controller.mixingPad.pixels() }), [controller, state.mixingPadVersion]);\n const R = wheelSize / 2;\n const mid = R * 0.82;\n const setHsv = (s: number, v: number) => controller.setColor(rgbToHexColor(...hsvToRgb(hsv.h, s, v)));\n\n const padPoint = (e: React.PointerEvent) => {\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n const kx = MIXING_PAD_WIDTH / (rect.width || MIXING_PAD_WIDTH);\n const ky = MIXING_PAD_HEIGHT / (rect.height || MIXING_PAD_HEIGHT);\n const x = Math.min(MIXING_PAD_WIDTH, Math.max(0, (e.clientX - rect.left) * kx));\n const y = Math.min(MIXING_PAD_HEIGHT, Math.max(0, (e.clientY - rect.top) * ky));\n return e.pointerType === 'pen' && e.pressure > 0 ? { x, y, pressure: e.pressure } : { x, y };\n };\n\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"color-panel\">\n <div className=\"relative self-center\" style={{ width: wheelSize, height: wheelSize }}>\n <div\n role=\"slider\"\n aria-label=\"Hue wheel\"\n aria-valuemin={0}\n aria-valuemax={360}\n aria-valuenow={Math.round(hueToWheel(hsv.h, wheel))}\n tabIndex={0}\n className=\"absolute inset-0 cursor-crosshair\"\n onPointerDown={(e) => {\n const rect = e.currentTarget.getBoundingClientRect();\n controller.setColor(wheelPick(e.clientX - rect.left - R, e.clientY - rect.top - R, wheel, color));\n }}\n >\n <PixelCanvas pixels={ring} label=\"Colour wheel\" style={{ width: wheelSize, height: wheelSize }} />\n </div>\n <svg className=\"pointer-events-none absolute inset-0\" width={wheelSize} height={wheelSize} aria-hidden=\"true\">\n {harmony.map((h, i) => {\n const p = wheelPoint(h.angle, mid);\n return <circle key={i} cx={R + p.x} cy={R + p.y} r={i === 0 ? 7 : 5} fill={h.color} stroke=\"#fff\" strokeWidth={i === 0 ? 2 : 1} />;\n })}\n </svg>\n <div className=\"absolute rounded-full border border-slate-700\" style={{ left: R - R * 0.45, top: R - R * 0.45, width: R * 0.9, height: R * 0.9, background: color }} />\n </div>\n <div className=\"flex items-center gap-2\">\n <input type=\"color\" aria-label=\"Paint colour\" value={color} onChange={(e) => controller.setColor(e.target.value)} className=\"h-7 w-9 rounded bg-transparent\" />\n <input type=\"color\" aria-label=\"Second colour\" value={state.secondaryColor} onChange={(e) => controller.setSecondaryColor(e.target.value)} className=\"h-5 w-7 rounded bg-transparent\" />\n <button type=\"button\" className={button} title=\"Swap colours (X)\" onClick={() => controller.swapColors()}>\n Swap\n </button>\n <input\n aria-label=\"Hex colour\"\n defaultValue={color}\n key={color}\n onBlur={(e) => attempt(() => controller.setColor(e.target.value.startsWith('#') ? e.target.value : `#${e.target.value}`))}\n className=\"w-20 rounded bg-slate-800 px-1.5 py-0.5 font-mono\"\n />\n </div>\n <div className=\"flex items-center gap-2\" data-testid=\"paint-source\">\n <span\n className=\"h-5 flex-1 rounded ring-1 ring-slate-700\"\n aria-label={state.paint.type === 'gradient' ? 'Gradient paint' : 'Paint colour'}\n data-testid=\"paint-well\"\n style={{ background: paintSourceCss(state.paint, { paint: color, secondary: state.secondaryColor }) }}\n />\n <button\n type=\"button\"\n className={chip(state.paint.type === 'gradient')}\n aria-pressed={state.paint.type === 'gradient'}\n title=\"Paint that changes colour as the stroke goes\"\n onClick={() => attempt(() => (state.paint.type === 'gradient' ? controller.setColor(color) : controller.setPaint(DEFAULT_PAINT_GRADIENT)))}\n >\n Gradient\n </button>\n </div>\n {state.paint.type === 'gradient' && (\n <PaintGradientEditor value={state.paint} colors={{ paint: color, secondary: state.secondaryColor }} onChange={(g) => attempt(() => controller.setPaint(g))} />\n )}\n <label className=\"flex items-center gap-2\">\n <span className=\"w-16 text-slate-400\">Saturation</span>\n <input type=\"range\" aria-label=\"Saturation\" min={0} max={1} step={0.01} value={hsv.s} onChange={(e) => setHsv(Number(e.target.value), hsv.v)} className=\"flex-1 accent-indigo-500\" />\n </label>\n <label className=\"flex items-center gap-2\">\n <span className=\"w-16 text-slate-400\">Value</span>\n <input type=\"range\" aria-label=\"Value\" min={0} max={1} step={0.01} value={hsv.v} onChange={(e) => setHsv(hsv.s, Number(e.target.value))} className=\"flex-1 accent-indigo-500\" />\n </label>\n <div className=\"flex items-center gap-1\">\n <select aria-label=\"Harmony\" value={kind} onChange={(e) => setKind(e.target.value as HarmonyKind)} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {HARMONY_KINDS.map((k) => (\n <option key={k} value={k}>\n {k}\n </option>\n ))}\n </select>\n <button type=\"button\" className={chip(wheel === 'ryb')} aria-pressed={wheel === 'ryb'} onClick={() => setWheel('ryb')}>\n RYB\n </button>\n <button type=\"button\" className={chip(wheel === 'rgb')} aria-pressed={wheel === 'rgb'} onClick={() => setWheel('rgb')}>\n RGB\n </button>\n </div>\n <div className=\"flex flex-wrap gap-1\" aria-label=\"Harmony colours\">\n {harmony.map((h, i) => (\n <button key={i} type=\"button\" aria-label={`Use ${h.color}`} title={h.color} className=\"h-6 w-6 rounded ring-1 ring-slate-700\" style={{ background: h.color }} onClick={() => controller.setColor(h.color)} />\n ))}\n <button type=\"button\" className={button} onClick={() => harmony.forEach((h) => controller.addSwatch(h.color))}>\n + swatches\n </button>\n </div>\n <div className=\"flex flex-wrap gap-1\" role=\"listbox\" aria-label=\"Swatches\">\n {state.swatches.map((s, i) => (\n <button\n key={i}\n type=\"button\"\n role=\"option\"\n aria-selected={s.paint ? state.paint === s.paint : state.paint.type === 'color' && s.color === color}\n aria-label={s.name ?? (s.paint ? 'Gradient' : s.color)}\n title={`${s.name ?? (s.paint ? 'Gradient' : s.color)} (right-click to remove)`}\n className=\"h-5 w-5 rounded ring-1 ring-slate-700\"\n style={{ background: s.paint ? paintSourceCss(s.paint, { paint: color, secondary: state.secondaryColor }) : s.color }}\n onClick={() => attempt(() => (s.paint ? controller.setPaint(s.paint) : controller.setColor(s.color)))}\n onContextMenu={(e) => {\n e.preventDefault();\n controller.removeSwatch(i);\n }}\n />\n ))}\n <button type=\"button\" className={button} aria-label=\"Add swatch\" onClick={() => attempt(() => controller.addSwatch(state.paint))}>\n +\n </button>\n </div>\n {mixingPad && (\n <div className=\"flex flex-col gap-1\" data-testid=\"mixing-pad\">\n <div className=\"flex items-center gap-1\">\n <span className=\"text-slate-400\">Mixing pad</span>\n {(['paint', 'knife', 'pick'] as const).map((t) => (\n <button key={t} type=\"button\" aria-pressed={padTool === t} className={chip(padTool === t)} onClick={() => setPadTool(t)}>\n {t === 'paint' ? 'Paint' : t === 'knife' ? 'Knife' : 'Pick'}\n </button>\n ))}\n <button type=\"button\" className={button} onClick={() => controller.clearMixingPad()}>\n Clear\n </button>\n </div>\n <div\n role=\"application\"\n aria-label=\"Mixing pad\"\n className=\"touch-none cursor-crosshair\"\n onPointerDown={(e) => {\n const p = padPoint(e);\n if (padTool === 'pick') {\n attempt(() => controller.mixingPadPick(p.x, p.y, { setColor: true, radius: padSampleRadius(sample) }));\n return;\n }\n padPoints.current = [p];\n (e.target as Element).setPointerCapture?.(e.pointerId);\n }}\n onPointerMove={(e) => padPoints.current?.push(padPoint(e))}\n onPointerUp={() => {\n const pts = padPoints.current;\n padPoints.current = null;\n if (pts?.length) attempt(() => controller.mixingPadStroke(pts, { tool: padTool === 'knife' ? 'knife' : 'paint' }));\n }}\n >\n <PixelCanvas pixels={pad} label=\"Mixing pad pixels\" className=\"w-full rounded\" style={{ aspectRatio: `${MIXING_PAD_WIDTH} / ${MIXING_PAD_HEIGHT}` }} />\n </div>\n <div className=\"flex flex-wrap items-center gap-1\">\n <label className=\"flex items-center gap-1\">\n <span className=\"text-slate-400\">Sample</span>\n <select aria-label=\"Pick sample size\" value={sample} onChange={(e) => setSample(Number(e.target.value))} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {PAD_SAMPLE_SIZES.map((n) => (\n <option key={n} value={n}>\n {n === 1 ? '1 px' : `${n}×${n}`}\n </option>\n ))}\n </select>\n </label>\n </div>\n <div className=\"flex flex-wrap items-center gap-1\">\n <span className=\"h-4 w-4 rounded ring-1 ring-slate-700\" style={{ background: color }} />\n <input type=\"number\" aria-label=\"Paint colour parts\" min={0} max={20} value={parts[0]} onChange={(e) => setParts([Number(e.target.value), parts[1]])} className=\"w-10 rounded bg-slate-800 px-1 py-0.5\" />\n <span className=\"text-slate-500\">:</span>\n <input type=\"number\" aria-label=\"Second colour parts\" min={0} max={20} value={parts[1]} onChange={(e) => setParts([parts[0], Number(e.target.value)])} className=\"w-10 rounded bg-slate-800 px-1 py-0.5\" />\n <span className=\"h-4 w-4 rounded ring-1 ring-slate-700\" style={{ background: state.secondaryColor }} />\n <button\n type=\"button\"\n className={button}\n title=\"Mix the paint and second colours in these parts on the pad, and use the mix\"\n onClick={() =>\n attempt(() =>\n controller.mixOnPad(\n [\n { color, parts: parts[0] },\n { color: state.secondaryColor, parts: parts[1] },\n ],\n { setColor: true }\n )\n )\n }\n >\n Mix\n </button>\n </div>\n <div className=\"flex flex-wrap items-center gap-1\">\n <input value={padName} placeholder=\"Pad name\" aria-label=\"Pad name\" onChange={(e) => setPadName(e.target.value)} className=\"w-24 rounded bg-slate-800 px-1.5 py-0.5\" />\n <button type=\"button\" className={button} onClick={() => attempt(() => (controller.saveMixingPad(padName || undefined), setPadName('')))}>\n Keep pad\n </button>\n </div>\n {state.savedMixingPads.length > 0 && (\n <ul className=\"flex flex-col gap-0.5\" aria-label=\"Kept pads\">\n {state.savedMixingPads.map((p) => (\n <li key={p.id} className=\"flex items-center gap-1\">\n <button type=\"button\" className={`${button} flex-1 text-left`} onClick={() => attempt(() => controller.loadMixingPad(p.id))}>\n {p.name}\n </button>\n <button type=\"button\" className={button} aria-label={`Remove ${p.name}`} onClick={() => attempt(() => controller.removeMixingPad(p.id))}>\n ×\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n )}\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport { BLEND_MENU_GROUPS, type BlendMode, type PaintEditorController, type PaintLayerInfo } from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, button, chip, panel, useAttempt } from './shared';\n\nexport interface PaintLayersPanelProps {\n controller: PaintEditorController;\n className?: string;\n}\n\n/** Siblings of a layer, bottom first, and its index among them. */\nfunction siblingIndex(layers: PaintLayerInfo[], l: PaintLayerInfo): { index: number; count: number } {\n const sibs = layers.filter((x) => x.parentId === l.parentId).reverse();\n return { index: sibs.findIndex((x) => x.id === l.id), count: sibs.length };\n}\n\n/**\n * The layer stack, top first: visibility, names (double-click to rename), the active layer's\n * opacity, blend mode and locks, and new layer / group, duplicate, move up / down, merge down and\n * delete. Every change is one undo step.\n */\nexport const PaintLayersPanel: React.FC<PaintLayersPanelProps> = ({ controller, className }) => {\n usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const [renaming, setRenaming] = useState<string | null>(null);\n const layers = controller.listLayers();\n const active = layers.find((l) => l.active) ?? null;\n const move = (delta: number) => {\n if (!active) return;\n const { index, count } = siblingIndex(layers, active);\n const to = Math.min(count - 1, Math.max(0, index + delta));\n if (to !== index) attempt(() => controller.moveLayer(active.id, to));\n };\n\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"paint-layers-panel\">\n <div className=\"flex flex-wrap gap-1\">\n <button type=\"button\" className={button} onClick={() => attempt(() => controller.addLayer())}>\n New layer\n </button>\n <button type=\"button\" className={button} onClick={() => attempt(() => controller.addLayer({ type: 'group' }))}>\n New group\n </button>\n <button type=\"button\" className={button} disabled={!active} onClick={() => active && attempt(() => controller.duplicateLayer(active.id))}>\n Duplicate\n </button>\n <button type=\"button\" className={button} disabled={!active} aria-label=\"Move layer up\" onClick={() => move(1)}>\n ↑\n </button>\n <button type=\"button\" className={button} disabled={!active} aria-label=\"Move layer down\" onClick={() => move(-1)}>\n ↓\n </button>\n <button type=\"button\" className={button} disabled={!active} onClick={() => active && attempt(() => controller.mergeDown(active.id))}>\n Merge down\n </button>\n <button type=\"button\" className={button} disabled={!active || layers.length < 2} onClick={() => active && attempt(() => controller.removeLayer(active.id))}>\n Delete\n </button>\n </div>\n <ul role=\"tree\" aria-label=\"Layers\" className=\"flex flex-col gap-0.5\">\n {layers.map((l) => (\n <li\n key={l.id}\n role=\"treeitem\"\n aria-selected={l.active}\n className={`flex items-center gap-1.5 rounded px-1.5 py-1 cursor-pointer ${l.active ? 'bg-indigo-600/30 ring-1 ring-indigo-500' : 'hover:bg-slate-800'}`}\n style={{ paddingLeft: 6 + l.depth * 12 }}\n onClick={() => controller.setActiveLayer(l.id)}\n >\n <button\n type=\"button\"\n aria-label={l.visible ? `Hide ${l.name}` : `Show ${l.name}`}\n className={`w-5 text-[11px] ${l.visible ? 'text-slate-200' : 'text-slate-600'}`}\n onClick={(e) => {\n e.stopPropagation();\n attempt(() => controller.updateLayer(l.id, { visible: !l.visible }));\n }}\n >\n {l.visible ? '●' : '○'}\n </button>\n {renaming === l.id ? (\n <input\n autoFocus\n aria-label=\"Layer name\"\n defaultValue={l.name}\n className=\"flex-1 rounded bg-slate-800 px-1\"\n onClick={(e) => e.stopPropagation()}\n onBlur={(e) => {\n setRenaming(null);\n if (e.target.value.trim() && e.target.value !== l.name) attempt(() => controller.updateLayer(l.id, { name: e.target.value }));\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') (e.target as HTMLInputElement).blur();\n if (e.key === 'Escape') setRenaming(null);\n }}\n />\n ) : (\n <span className=\"flex-1 truncate\" onDoubleClick={() => setRenaming(l.id)}>\n {l.type === 'group' ? '▸ ' : ''}\n {l.name}\n </span>\n )}\n {l.locks.pixels || l.locks.all ? <span title=\"Locked\">🔒</span> : null}\n </li>\n ))}\n </ul>\n {active && (\n <div className=\"flex flex-col gap-1.5\">\n <label className=\"flex items-center gap-2\">\n <span className=\"w-14 text-slate-400\">Opacity</span>\n <input\n type=\"range\"\n aria-label=\"Layer opacity\"\n min={0}\n max={1}\n step={0.01}\n value={active.opacity}\n onChange={(e) => attempt(() => controller.updateLayer(active.id, { opacity: Number(e.target.value) }))}\n className=\"flex-1 accent-indigo-500\"\n />\n </label>\n <label className=\"flex items-center gap-2\">\n <span className=\"w-14 text-slate-400\">Blend</span>\n <select aria-label=\"Layer blend\" value={active.blend} onChange={(e) => attempt(() => controller.updateLayer(active.id, { blend: e.target.value as BlendMode }))} className=\"flex-1 rounded bg-slate-800 px-1 py-0.5\">\n {active.type === 'group' && <option value=\"pass-through\">Pass through</option>}\n {BLEND_MENU_GROUPS.map((g) => (\n <optgroup key={g.label} label={g.label}>\n {g.modes.map((m) => (\n <option key={m.id} value={m.id} title={m.description}>\n {m.label}\n </option>\n ))}\n </optgroup>\n ))}\n </select>\n </label>\n <div className=\"flex gap-1\">\n {(['pixels', 'transparency'] as const).map((k) => (\n <button key={k} type=\"button\" aria-pressed={Boolean(active.locks[k])} className={chip(Boolean(active.locks[k]))} onClick={() => attempt(() => controller.updateLayer(active.id, { locks: { [k]: !active.locks[k] } }))}>\n {k === 'pixels' ? 'Lock pixels' : 'Lock transparency'}\n </button>\n ))}\n <button type=\"button\" aria-pressed={active.clipped} className={chip(active.clipped)} onClick={() => attempt(() => controller.updateLayer(active.id, { clipped: !active.clipped }))}>\n Clip\n </button>\n </div>\n </div>\n )}\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React from 'react';\nimport { WET_FLOW_KINDS, WET_GPU_OPTIONS, WET_PARAM_SLIDERS, WET_SPEED_SLIDER, WET_TILT_SLIDERS, readPath, wetEngineSummary, type PaintEditorController, type WetFlowKind, type WetGpuMode } from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, PaintSlider, button, chip, panel, useAttempt } from './shared';\n\nexport interface WetPanelProps {\n controller: PaintEditorController;\n className?: string;\n}\n\nconst FLOW_LABELS: Record<WetFlowKind, string> = { none: 'None', linear: 'One way', swirl: 'Swirl', radial: 'Outwards', turbulent: 'Eddies' };\n\n/**\n * Wet media: whether paint is wet, Dry now, Pause / Resume, the water overlay and speed; Wet paper\n * on the active layer; canvas tilt; the active layer's wet settings (viscosity, evaporation, edge\n * darkening, granulation, blooms, bleed, pigment weight, lifting, staining) and flow map; and the\n * kernel in use, with a note when it runs slower than it could (no cross-origin isolation); and\n * Engine B, the WebGPU accelerator for large washes, with a switch to force the CPU.\n */\nexport const WetPanel: React.FC<WetPanelProps> = ({ controller, className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const wet = state.wet;\n const layerId = state.document.activeLayerId;\n const info = layerId ? controller.wetLayerInfo(layerId) : null;\n const backend = controller.wetState();\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"wet-panel\">\n <div className=\"flex items-center justify-between\">\n <span className={wet.wet ? 'text-sky-300' : 'text-slate-400'} data-testid=\"wet-status\">\n {wet.wet ? (wet.paused ? 'Wet (paused)' : 'Wet') : 'Dry'}\n </span>\n <span className=\"text-[10px] text-slate-500\">step {wet.clock}</span>\n </div>\n <div className=\"flex flex-wrap gap-1\">\n <button type=\"button\" className={button} disabled={!wet.layerIds.length} onClick={() => attempt(async () => (await controller.wetIdle(), controller.dryPaint()))}>\n Dry now\n </button>\n <button type=\"button\" className={chip(wet.paused)} aria-pressed={wet.paused} onClick={() => controller.setWetPaused(!wet.paused)}>\n {wet.paused ? 'Resume' : 'Pause'}\n </button>\n <button type=\"button\" className={chip(wet.overlay)} aria-pressed={wet.overlay} onClick={() => controller.setWaterOverlay(!wet.overlay)}>\n Water\n </button>\n <button type=\"button\" className={chip(wet.instantDry)} aria-pressed={wet.instantDry} title=\"Each wet stroke dries as soon as it ends\" onClick={() => controller.setInstantDry(!wet.instantDry)}>\n Instant dry\n </button>\n <button type=\"button\" className={button} disabled={!layerId} onClick={() => attempt(async () => (await controller.wetIdle(), controller.wetPaper({})))}>\n Wet paper\n </button>\n </div>\n <PaintSlider control={WET_SPEED_SLIDER} value={wet.speed} onChange={(v) => controller.setWetSpeed(v)} />\n {WET_TILT_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(wet.tilt, c.path)} onCommit={(v) => attempt(async () => (await controller.wetIdle(), controller.setCanvasTilt({ [c.path]: v })))} />\n ))}\n {info && (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"wet-layer\">\n <span className=\"font-medium text-slate-300\">This layer</span>\n {WET_PARAM_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(info.params, c.path)} onCommit={(v) => attempt(async () => (await controller.wetIdle(), controller.setWetParams(layerId!, { [c.path]: v })))} />\n ))}\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Flow map</span>\n <select aria-label=\"Flow map\" value={info.flow.kind} onChange={(e) => attempt(async () => (await controller.wetIdle(), controller.setFlowMap(layerId!, { kind: e.target.value as WetFlowKind })))} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {WET_FLOW_KINDS.map((k) => (\n <option key={k} value={k}>\n {FLOW_LABELS[k]}\n </option>\n ))}\n </select>\n </label>\n {info.flow.kind !== 'none' && (\n <PaintSlider\n control={{ path: 'strength', label: 'Flow strength', min: 0, max: 1, step: 0.01 }}\n value={info.flow.strength}\n onCommit={(v) => attempt(async () => (await controller.wetIdle(), controller.setFlowMap(layerId!, { strength: v })))}\n />\n )}\n </div>\n )}\n {backend.message && (\n <p className=\"text-[10px] text-amber-300\" data-testid=\"wet-message\">\n {backend.message}\n </p>\n )}\n {backend.backend && (\n <p className=\"text-[10px] text-slate-500\">\n {backend.backend.kind === 'wasm-threads' ? `WebAssembly, ${backend.backend.threads} threads` : backend.backend.kind === 'wasm' ? 'WebAssembly, one thread' : 'JavaScript'}\n </p>\n )}\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Engine</span>\n <select aria-label=\"Wet engine\" value={wet.gpu} onChange={(e) => attempt(() => controller.setWetEngine({ gpu: e.target.value as WetGpuMode }))} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {WET_GPU_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </label>\n <p className={`text-[10px] ${backend.engine.state === 'active' ? 'text-emerald-300' : 'text-slate-500'}`} data-testid=\"wet-engine\">\n {wetEngineSummary(backend.engine)}\n </p>\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport { STAMP_KINDS, STAMP_LABELS, STICKER_SLIDERS, readPath, type PaintEditorController, type StampKind } from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { CommitColorInput, ErrorLine, PaintSlider, button, panel, useAttempt } from './shared';\n\nexport interface StickerPanelProps {\n controller: PaintEditorController;\n className?: string;\n}\n\n/**\n * The active layer's stickers: pick one to change its stamp, size, rotation, opacity and colour,\n * bring it to the front or back, or delete it (each change one undo step). Shows nothing for a\n * layer without stickers.\n */\nexport const StickerPanel: React.FC<StickerPanelProps> = ({ controller, className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const [picked, setPicked] = useState<string | null>(null);\n const layerId = state.document.activeLayerId;\n const stickers = layerId ? (state.document.stickers?.[layerId] ?? []) : [];\n if (!stickers.length) return null;\n const sel = stickers.find((s) => s.id === picked) ?? null;\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"sticker-panel\">\n <span className=\"font-medium text-slate-300\">Stickers ({stickers.length})</span>\n <div className=\"flex max-h-24 flex-wrap gap-1 overflow-y-auto\" role=\"listbox\" aria-label=\"Stickers\">\n {stickers.map((s) => (\n <button key={s.id} type=\"button\" role=\"option\" aria-selected={s.id === picked} title={`${STAMP_LABELS[s.stamp]} ${s.id}`} className={`h-5 w-5 rounded ring-1 ${s.id === picked ? 'ring-indigo-400' : 'ring-slate-700'}`} style={{ background: s.color }} onClick={() => setPicked(s.id)} />\n ))}\n </div>\n {sel && (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"sticker-edit\">\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Stamp</span>\n <select aria-label=\"Sticker stamp\" value={sel.stamp} onChange={(e) => attempt(() => controller.updateSticker(layerId!, sel.id, { stamp: e.target.value as StampKind }))} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {STAMP_KINDS.map((k) => (\n <option key={k} value={k}>\n {STAMP_LABELS[k]}\n </option>\n ))}\n </select>\n </label>\n {STICKER_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(sel, c.path)} onCommit={(v) => attempt(() => controller.updateSticker(layerId!, sel.id, { [c.path]: v }))} />\n ))}\n <label className=\"flex items-center justify-between\">\n <span className=\"text-slate-400\">Colour</span>\n <CommitColorInput label=\"Sticker colour\" value={sel.color} onCommit={(v) => attempt(() => controller.updateSticker(layerId!, sel.id, { color: v }))} className=\"h-6 w-10 rounded bg-transparent\" />\n </label>\n <div className=\"flex flex-wrap gap-1\">\n <button type=\"button\" className={button} onClick={() => attempt(() => controller.arrangeStickers(layerId!, [sel.id], 'front'))}>\n To front\n </button>\n <button type=\"button\" className={button} onClick={() => attempt(() => controller.arrangeStickers(layerId!, [sel.id], 'back'))}>\n To back\n </button>\n <button type=\"button\" className={button} onClick={() => attempt(() => (controller.removeStickers(layerId!, [sel.id]), setPicked(null)))}>\n Delete\n </button>\n </div>\n </div>\n )}\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport type { PaintEditorController, PaintPresence, PaintTool } from '@pixerate/editor/paint-editor';\nimport { BrushPanel } from './BrushPanel';\nimport { ColorPanel } from './ColorPanel';\nimport { PaintCanvas } from './PaintCanvas';\nimport { PaintLayersPanel } from './PaintLayersPanel';\nimport { PaintToolbar } from './PaintToolbar';\nimport { PaperPanel } from './PaperPanel';\nimport { WetPanel } from './WetPanel';\nimport { StickerPanel } from './StickerPanel';\nimport { chip } from './shared';\n\nexport interface PaintEditorProps {\n controller: PaintEditorController;\n /** Base name of saved and exported files (default `painting`). */\n fileName?: string;\n /** Height of the editor (default 720 px). */\n height?: number | string;\n /** Agent cursors to draw over the canvas (see `usePaintDirector`). */\n presence?: PaintPresence;\n className?: string;\n}\n\ntype SideTab = 'color' | 'wet' | 'paper' | 'layers';\n\n/**\n * The paint editor: toolbar, brush library on the left, the canvas, and colour (wheel,\n * harmonies, swatches, mixing pad), wet media, paper and layers on the right.\n */\nexport const PaintEditor: React.FC<PaintEditorProps> = ({ controller, fileName, height = 720, presence, className }) => {\n const [tool, setTool] = useState<PaintTool>('brush');\n const [tab, setTab] = useState<SideTab>('color');\n const [error, setError] = useState<string | null>(null);\n return (\n <div className={`flex flex-col gap-2 rounded-xl border border-slate-800 bg-slate-900 p-2 ${className ?? ''}`} style={{ height }} data-testid=\"paint-editor\">\n <PaintToolbar controller={controller} tool={tool} onToolChange={setTool} fileName={fileName} />\n <div className=\"flex min-h-0 flex-1 gap-2\">\n <BrushPanel controller={controller} className=\"w-60 shrink-0 overflow-y-auto pr-1\" />\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <PaintCanvas controller={controller} tool={tool} onError={setError} presence={presence} className=\"flex-1 rounded-lg\" />\n {error && (\n <p role=\"alert\" className=\"mt-1 text-[11px] text-rose-400\">\n {error}\n </p>\n )}\n </div>\n <div className=\"flex w-64 shrink-0 flex-col gap-2 overflow-y-auto pr-1\">\n <div className=\"flex gap-1\" role=\"tablist\" aria-label=\"Paint panels\">\n {(['color', 'wet', 'paper', 'layers'] as const).map((t) => (\n <button key={t} type=\"button\" role=\"tab\" aria-selected={tab === t} className={chip(tab === t)} onClick={() => setTab(t)}>\n {t === 'color' ? 'Colour' : t === 'wet' ? 'Wet' : t === 'paper' ? 'Paper' : 'Layers'}\n </button>\n ))}\n </div>\n {tab === 'color' && <ColorPanel controller={controller} />}\n {tab === 'wet' && <WetPanel controller={controller} />}\n {tab === 'paper' && <PaperPanel controller={controller} />}\n {tab === 'layers' && <PaintLayersPanel controller={controller} />}\n {tab === 'layers' && <StickerPanel controller={controller} />}\n </div>\n </div>\n </div>\n );\n};\n"],"mappings":"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","names":["import_react","import_paint_editor","import_react","import_paint_editor","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_paint_editor","import_paint_editor","import_react","import_jsx_runtime","button","paintSourceCss","import_jsx_runtime","import_jsx_runtime","import_react","import_paint_editor","import_jsx_runtime","import_react","import_paint_editor","import_jsx_runtime","g","import_react","import_paint_editor","import_jsx_runtime","import_paint_editor","import_jsx_runtime","import_react","import_paint_editor","import_jsx_runtime","import_react","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../../src/paint-editor/index.ts","../../src/paint-editor/usePaintEditor.ts","../../src/paint-editor/PaintCanvas.tsx","../../src/paint-editor/PaintToolbar.tsx","../../src/paint-editor/shared.tsx","../../src/paint-editor/BrushPanel.tsx","../../src/paint-editor/PaintGradientEditor.tsx","../../src/paint-editor/PaintGradientEditorView.tsx","../../src/paint-editor/PaperPanel.tsx","../../src/paint-editor/ColorPanel.tsx","../../src/paint-editor/PaintLayersPanel.tsx","../../src/paint-editor/WetPanel.tsx","../../src/paint-editor/StickerPanel.tsx","../../src/paint-editor/PaintEditor.tsx","../../src/paint-editor/PaintEffectsPanel.tsx","../../src/effects/useEffects.ts","../../src/effects/EffectThumbnail.tsx","../../src/effects/EffectsBrowser.tsx","../../src/effects/EffectParameters.tsx","../../src/parameters/fields.tsx"],"sourcesContent":["export * from './usePaintEditor';\nexport * from './PaintCanvas';\nexport * from './PaintToolbar';\nexport * from './BrushPanel';\nexport * from './PaperPanel';\nexport * from './ColorPanel';\nexport * from './PaintLayersPanel';\nexport * from './WetPanel';\nexport * from './StickerPanel';\nexport * from './PaintEditor';\nexport { PaintSlider } from './shared';\nexport * from './PaintGradientEditor';\nexport * from './PaintEffectsPanel';\n","import { useMemo, useState, useSyncExternalStore } from 'react';\nimport { PaintDirector, PaintEditorController, PaintPresence, type PaintDirectorOptions, type PaintEditorOptions, type PaintEditorState } from '@pixerate/editor/paint-editor';\n\nexport interface UsePaintEditorReturn {\n controller: PaintEditorController;\n /** The controller's snapshot (a new object after every change). */\n state: PaintEditorState;\n}\n\n/**\n * Creates a `PaintEditorController` once (from `options`, read on the first render) or uses the\n * one given, and re-renders on every change.\n */\nexport function usePaintEditor(options: PaintEditorOptions | PaintEditorController = {}): UsePaintEditorReturn {\n const [controller] = useState(() => (options instanceof PaintEditorController ? options : new PaintEditorController(options)));\n const state = usePaintEditorState(controller);\n return useMemo(() => ({ controller, state }), [controller, state]);\n}\n\n/** Subscribes to a controller's state. */\nexport function usePaintEditorState(controller: PaintEditorController): PaintEditorState {\n return useSyncExternalStore(\n (notify) => controller.subscribe(notify),\n () => controller.getState(),\n () => controller.getState()\n );\n}\n\n/**\n * A `PaintPresence` and `PaintDirector` for a paint editor: pass `presence` to `PaintEditor` (or\n * `PaintCanvas`) and `director` to `createPaintEditorToolProvider`, so agent strokes are painted\n * live by a cursor on the canvas. Options are read on the first render.\n */\nexport function usePaintDirector(controller: PaintEditorController, options: Omit<PaintDirectorOptions, 'clock'> = {}): { presence: PaintPresence; director: PaintDirector } {\n const [value] = useState(() => {\n const presence = new PaintPresence();\n return { presence, director: new PaintDirector(controller, presence, options) };\n });\n return value;\n}\n","import React, { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react';\nimport {\n PaintCanvasPresenter,\n PaintGesture,\n documentToScreen,\n drawWaterOverlay,\n startWetClock,\n fitZoom,\n guideOverlay,\n handlePaintShortcut,\n viewCssTransform,\n type PaintEditorController,\n type PaintPresence,\n type PaintTool,\n type PaintView,\n} from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\n\nexport interface PaintCanvasProps {\n controller: PaintEditorController;\n /** The active tool (default brush). */\n tool?: PaintTool;\n /** Draw the symmetry axes and perspective lines (default true). */\n showGuides?: boolean;\n /** Fit the canvas in the viewport on mount (default true). */\n fitOnMount?: boolean;\n /** Called with a refusal (hidden or locked layer). */\n onError?: (message: string | null) => void;\n /** Agent cursors to draw over the canvas (see `PaintDirector` and `usePaintDirector`). */\n presence?: PaintPresence;\n className?: string;\n}\n\n/**\n * The painting surface: a document-sized canvas the compositor draws into (only changed tiles are\n * uploaded), shown through the view's zoom, pan, rotation and mirroring as a CSS transform (the\n * pixels never resample). Pointer input goes through `PaintGesture`: coalesced samples, a predicted\n * tail drawn as a thin preview, palm rejection, middle-button pan, wheel zoom and Shift+wheel\n * rotation. Guides and floating reference images are drawn on top.\n */\nexport const PaintCanvas: React.FC<PaintCanvasProps> = ({ controller, tool = 'brush', showGuides = true, fitOnMount = true, onError, presence, className }) => {\n const state = usePaintEditorState(controller);\n const viewport = useRef<HTMLDivElement>(null);\n const canvas = useRef<HTMLCanvasElement>(null);\n const water = useRef<HTMLCanvasElement>(null);\n const [size, setSize] = useState({ width: 800, height: 600 });\n const measured = useRef(false);\n const [predicted, setPredicted] = useState<Array<{ x: number; y: number }>>([]);\n const presenter = useMemo(() => new PaintCanvasPresenter(controller), [controller]);\n const gesture = useMemo(\n () =>\n new PaintGesture(controller, () => {\n const r = viewport.current?.getBoundingClientRect();\n return { left: r?.left ?? 0, top: r?.top ?? 0, width: r?.width || size.width, height: r?.height || size.height };\n }),\n // The box reads the element when called; `size` is only the jsdom fallback.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [controller]\n );\n gesture.tool = tool;\n const { canvas: doc } = state.document;\n\n useEffect(() => {\n const el = viewport.current;\n if (!el || typeof ResizeObserver === 'undefined') return;\n const ro = new ResizeObserver(() => {\n if (!el.clientWidth || !el.clientHeight) return;\n measured.current = true;\n setSize({ width: el.clientWidth, height: el.clientHeight });\n });\n ro.observe(el);\n return () => ro.disconnect();\n }, []);\n\n // Fit once per canvas size, after the viewport has been measured (or at once where it cannot be).\n const fitted = useRef<string | null>(null);\n useEffect(() => {\n const key = `${doc.width}x${doc.height}`;\n if (!fitOnMount || fitted.current === key) return;\n if (typeof ResizeObserver !== 'undefined' && !measured.current) return;\n fitted.current = key;\n controller.setView({ zoom: fitZoom(doc, size), pan: { x: 0, y: 0 } });\n }, [controller, doc, size, fitOnMount]);\n\n // Upload changed tiles whenever the state changes.\n useEffect(() => {\n const ctx = canvas.current?.getContext('2d');\n if (ctx && typeof ctx.createImageData === 'function') presenter.render(ctx as never);\n else controller.takeDirty();\n }, [state, presenter, controller]);\n\n // Wet paint flows with the display.\n useEffect(() => startWetClock(controller), [controller]);\n\n // The water overlay.\n useEffect(() => {\n const ctx = water.current?.getContext('2d');\n if (ctx && typeof ctx.createImageData === 'function') drawWaterOverlay(controller, ctx as never);\n }, [state, controller]);\n\n // Wheel needs a non-passive listener to prevent page scroll (see GOTCHAS).\n useEffect(() => {\n const el = viewport.current;\n if (!el) return;\n const onWheel = (e: WheelEvent) => {\n e.preventDefault();\n gesture.wheel(e);\n };\n el.addEventListener('wheel', onWheel, { passive: false });\n return () => el.removeEventListener('wheel', onWheel);\n }, [gesture]);\n\n const report = () => onError?.(gesture.error);\n const transform = viewCssTransform(state.view, doc, size);\n const lines = showGuides ? guideOverlay(controller) : [];\n\n return (\n <div\n ref={viewport}\n tabIndex={0}\n role=\"application\"\n aria-label=\"Paint canvas\"\n data-testid=\"paint-canvas\"\n className={`relative overflow-hidden bg-slate-950 outline-none touch-none select-none ${className ?? ''}`}\n style={{ cursor: tool === 'pan' ? 'grab' : tool === 'eyedropper' ? 'copy' : 'crosshair' }}\n onPointerDown={(e) => {\n viewport.current?.focus();\n if (gesture.down(e.nativeEvent)) (e.target as Element).setPointerCapture?.(e.pointerId);\n report();\n }}\n onPointerMove={(e) => {\n gesture.move(e.nativeEvent);\n if (gesture.predicted.length || predicted.length) setPredicted(gesture.predicted.map((p) => ({ x: p.x, y: p.y })));\n }}\n onPointerUp={(e) => {\n gesture.up(e.nativeEvent);\n setPredicted([]);\n }}\n onPointerCancel={() => {\n gesture.cancel();\n setPredicted([]);\n }}\n onKeyDown={(e) => {\n if (handlePaintShortcut(controller, gesture, e)) e.preventDefault();\n }}\n >\n <canvas\n ref={canvas}\n width={doc.width}\n height={doc.height}\n className=\"absolute left-0 top-0 shadow-2xl\"\n style={{ transform, transformOrigin: '0 0', imageRendering: state.view.zoom > 2 ? 'pixelated' : 'auto' }}\n />\n {state.wet.overlay && (\n <canvas\n ref={water}\n width={doc.width}\n height={doc.height}\n data-testid=\"paint-water-overlay\"\n className=\"absolute left-0 top-0 pointer-events-none opacity-60\"\n style={{ transform, transformOrigin: '0 0' }}\n />\n )}\n <svg className=\"absolute left-0 top-0 pointer-events-none overflow-visible\" width={doc.width} height={doc.height} style={{ transform, transformOrigin: '0 0' }} aria-hidden=\"true\">\n {lines.map((l, i) => (\n <line\n key={i}\n x1={l.from.x}\n y1={l.from.y}\n x2={l.to.x}\n y2={l.to.y}\n stroke={l.kind === 'symmetry' ? '#22d3ee' : l.kind === 'stencil' ? '#fbbf24' : '#f472b6'}\n strokeOpacity={l.kind === 'symmetry' || l.kind === 'stencil' ? 0.8 : 0.35}\n strokeWidth={1 / state.view.zoom}\n strokeDasharray={l.kind === 'symmetry' ? `${6 / state.view.zoom} ${4 / state.view.zoom}` : undefined}\n />\n ))}\n {predicted.length > 0 && (\n <polyline points={predicted.map((p) => `${p.x},${p.y}`).join(' ')} fill=\"none\" stroke={state.color} strokeOpacity={0.5} strokeWidth={Math.max(1, state.brush.tip.size / 2)} strokeLinecap=\"round\" />\n )}\n </svg>\n {state.guides.references\n .filter((r) => r.visible)\n .map((r) => (\n <ReferencePanel key={r.id} controller={controller} id={r.id} />\n ))}\n {presence && <PaintPresenceLayer presence={presence} view={state.view} canvas={doc} viewport={size} />}\n <div className=\"absolute bottom-1 right-2 text-[10px] text-slate-500 pointer-events-none\" data-testid=\"paint-view-status\">\n {Math.round(state.view.zoom * 100)}% · {Math.round(state.view.rotation)}°{state.view.mirror ? ' · mirrored' : ''}\n </div>\n </div>\n );\n};\n\n/**\n * Agent cursors and notes over the canvas. Positions are document pixels, placed through the view\n * (zoom, pan, rotation, mirroring), while the cursors themselves stay upright and unscaled.\n */\nexport const PaintPresenceLayer: React.FC<{ presence: PaintPresence; view: PaintView; canvas: { width: number; height: number }; viewport: { width: number; height: number } }> = ({ presence, view, canvas, viewport }) => {\n const { actors } = useSyncExternalStore(presence.subscribe, presence.getState, presence.getState);\n return (\n <div className=\"pointer-events-none absolute inset-0 overflow-hidden\" data-paint-presence=\"\" aria-hidden=\"true\">\n {actors.map((a) => {\n const p = documentToScreen(view, canvas, viewport, a.x, a.y);\n return (\n <div key={a.id} className=\"absolute\" style={{ left: p.x, top: p.y }} data-actor={a.id}>\n <svg width=\"18\" height=\"20\" viewBox=\"0 0 18 20\" className=\"drop-shadow-md\" style={{ transform: a.pressed ? 'scale(0.85)' : undefined, transformOrigin: '0 0' }}>\n <path d=\"M0 0 L0 15 L4.5 10.8 L7.6 17 L10.2 15.8 L7.2 9.7 L13.5 9.4 Z\" fill={a.color} stroke=\"white\" strokeWidth=\"1.4\" strokeLinejoin=\"round\" />\n </svg>\n <span className=\"absolute left-4 top-4 w-max max-w-[240px] rounded-md px-2 py-0.5 text-[11px] font-semibold text-white shadow\" style={{ background: a.color }}>\n {a.message ?? a.name}\n </span>\n </div>\n );\n })}\n </div>\n );\n};\n\n/** A floating reference image: drag its title bar to move it, click the image to pick a colour. */\nconst ReferencePanel: React.FC<{ controller: PaintEditorController; id: string }> = ({ controller, id }) => {\n const state = usePaintEditorState(controller);\n const ref = state.guides.references.find((r) => r.id === id);\n const drag = useRef<{ x: number; y: number; ox: number; oy: number } | null>(null);\n if (!ref) return null;\n const h = (ref.height / ref.width) * ref.displayWidth;\n return (\n <div\n className=\"absolute rounded border border-slate-700 bg-slate-900/95 shadow-xl\"\n style={{ left: ref.x, top: ref.y, width: ref.displayWidth }}\n data-testid=\"paint-reference\"\n onPointerDown={(e) => e.stopPropagation()}\n >\n <div\n className=\"flex items-center justify-between px-1.5 py-0.5 text-[10px] text-slate-300 cursor-move\"\n onPointerDown={(e) => {\n drag.current = { x: e.clientX, y: e.clientY, ox: ref.x, oy: ref.y };\n (e.target as Element).setPointerCapture?.(e.pointerId);\n }}\n onPointerMove={(e) => {\n const d = drag.current;\n if (d) controller.updateReferenceImage(id, { x: d.ox + e.clientX - d.x, y: d.oy + e.clientY - d.y });\n }}\n onPointerUp={() => (drag.current = null)}\n >\n <span className=\"truncate\">{ref.name}</span>\n <button type=\"button\" aria-label={`Hide ${ref.name}`} className=\"px-1 text-slate-400 hover:text-white\" onClick={() => controller.updateReferenceImage(id, { visible: false })}>\n ×\n </button>\n </div>\n <img\n src={ref.src}\n alt={ref.name}\n draggable={false}\n width={ref.displayWidth}\n height={h}\n className=\"block cursor-copy\"\n onClick={(e) => {\n const rect = (e.target as HTMLElement).getBoundingClientRect();\n const k = ref.width / (rect.width || ref.displayWidth);\n controller.setColor(controller.pickReferenceColor(id, Math.min(ref.width - 1, (e.clientX - rect.left) * k), Math.min(ref.height - 1, (e.clientY - rect.top) * k)));\n }}\n />\n </div>\n );\n};\n","import React, { useRef, useState } from 'react';\nimport { PAINT_TOOLS, SYMMETRY_MODES, decodeImageBlob, downloadBytes, quickStencil, timeLapseZip, type PaintEditorController, type PaintTool, type SymmetryMode } from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, button, chip, useAttempt } from './shared';\n\nexport interface PaintToolbarProps {\n controller: PaintEditorController;\n tool: PaintTool;\n onToolChange: (tool: PaintTool) => void;\n /** Base name of saved and exported files (default `painting`). */\n fileName?: string;\n className?: string;\n}\n\n/**\n * Tools (brush, eyedropper, pan, rotate view), undo / redo, view rotation, mirroring and reset,\n * the symmetry and perspective guides, stencils (ruler, circle, mask), the tracing image and reference images, the drawing hand,\n * and file actions: save / open JSON, export PNG, JPEG and PSD, a time-lapse (zipped frames, video\n * project and ffmpeg command) and a PNG repainted from the strokes at twice the size.\n */\nexport const PaintToolbar: React.FC<PaintToolbarProps> = ({ controller, tool, onToolChange, fileName = 'painting', className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const [busy, setBusy] = useState<string | null>(null);\n const [note, setNote] = useState<string | null>(null);\n const openRef = useRef<HTMLInputElement>(null);\n const tracingRef = useRef<HTMLInputElement>(null);\n const refRef = useRef<HTMLInputElement>(null);\n const { symmetry, perspective, tracing } = state.guides;\n const { canvas } = state.document;\n\n const exportImage = (format: 'image/png' | 'image/jpeg') =>\n attempt(async () => downloadBytes(await controller.exportImage({ format }), `${fileName}.${format === 'image/png' ? 'png' : 'jpg'}`, format));\n\n return (\n <div className={`flex flex-wrap items-center gap-1.5 text-xs text-slate-200 ${className ?? ''}`} role=\"toolbar\" aria-label=\"Paint toolbar\" data-testid=\"paint-toolbar\">\n {PAINT_TOOLS.map((t) => (\n <button key={t.id} type=\"button\" aria-pressed={tool === t.id} title={`${t.label} (${t.key.toUpperCase()})`} className={chip(tool === t.id)} onClick={() => onToolChange(t.id)}>\n {t.label}\n </button>\n ))}\n <span className=\"mx-1 h-4 w-px bg-slate-700\" />\n <button type=\"button\" className={button} disabled={!state.canUndo} title={state.undoLabel ? `Undo ${state.undoLabel}` : 'Undo'} onClick={() => controller.undo()}>\n Undo\n </button>\n <button type=\"button\" className={button} disabled={!state.canRedo} title={state.redoLabel ? `Redo ${state.redoLabel}` : 'Redo'} onClick={() => controller.redo()}>\n Redo\n </button>\n <span className=\"mx-1 h-4 w-px bg-slate-700\" />\n <button type=\"button\" className={button} aria-label=\"Rotate view left\" onClick={() => controller.setView({ rotation: state.view.rotation - 15 })}>\n ⟲\n </button>\n <button type=\"button\" className={button} aria-label=\"Rotate view right\" onClick={() => controller.setView({ rotation: state.view.rotation + 15 })}>\n ⟳\n </button>\n <button type=\"button\" className={chip(state.view.mirror)} aria-pressed={state.view.mirror} onClick={() => controller.setView({ mirror: !state.view.mirror })}>\n Mirror view\n </button>\n <button type=\"button\" className={button} onClick={() => controller.resetView()}>\n Reset view\n </button>\n <span className=\"mx-1 h-4 w-px bg-slate-700\" />\n <label className=\"flex items-center gap-1\">\n Symmetry\n <select\n aria-label=\"Symmetry\"\n value={symmetry.mode}\n onChange={(e) => controller.setSymmetry({ mode: e.target.value as SymmetryMode, center: symmetry.mode === 'off' ? { x: canvas.width / 2, y: canvas.height / 2 } : symmetry.center })}\n className=\"rounded bg-slate-800 px-1 py-0.5\"\n >\n {SYMMETRY_MODES.map((m) => (\n <option key={m} value={m}>\n {m}\n </option>\n ))}\n </select>\n </label>\n {symmetry.mode === 'kaleidoscope' && (\n <input\n type=\"number\"\n aria-label=\"Kaleidoscope segments\"\n min={2}\n max={32}\n value={symmetry.segments}\n onChange={(e) => controller.setSymmetry({ segments: Number(e.target.value) })}\n className=\"w-12 rounded bg-slate-800 px-1 py-0.5\"\n />\n )}\n <button\n type=\"button\"\n className={chip(perspective.enabled)}\n aria-pressed={perspective.enabled}\n onClick={() =>\n attempt(() =>\n controller.setPerspective(\n perspective.enabled ? { enabled: false } : { enabled: true, points: perspective.points.length ? perspective.points : [{ x: canvas.width / 2, y: canvas.height * 0.4 }] }\n )\n )\n }\n >\n Perspective\n </button>\n {perspective.enabled && (\n <select\n aria-label=\"Vanishing points\"\n value={perspective.points.length}\n onChange={(e) => {\n const n = Number(e.target.value);\n const y = canvas.height * 0.4;\n const pts = n === 1 ? [{ x: canvas.width / 2, y }] : n === 2 ? [{ x: -canvas.width * 0.5, y }, { x: canvas.width * 1.5, y }] : [{ x: -canvas.width * 0.5, y }, { x: canvas.width * 1.5, y }, { x: canvas.width / 2, y: canvas.height * 3 }];\n attempt(() => controller.setPerspective({ points: pts }));\n }}\n className=\"rounded bg-slate-800 px-1 py-0.5\"\n >\n <option value={1}>1-point</option>\n <option value={2}>2-point</option>\n <option value={3}>3-point</option>\n </select>\n )}\n <span className=\"mx-1 h-4 w-px bg-slate-700\" />\n <button type=\"button\" className={button} onClick={() => tracingRef.current?.click()}>\n Tracing image…\n </button>\n {tracing && (\n <>\n <input\n type=\"range\"\n aria-label=\"Tracing opacity\"\n min={0}\n max={1}\n step={0.05}\n value={tracing.opacity}\n onChange={(e) => controller.updateTracing({ opacity: Number(e.target.value) })}\n className=\"w-16 accent-indigo-500\"\n />\n <button type=\"button\" className={chip(tracing.sampleColors)} aria-pressed={tracing.sampleColors} onClick={() => controller.updateTracing({ sampleColors: !tracing.sampleColors })}>\n Trace colours\n </button>\n <button type=\"button\" className={chip(tracing.visible)} aria-pressed={tracing.visible} onClick={() => controller.updateTracing({ visible: !tracing.visible })}>\n Show tracing\n </button>\n <button type=\"button\" className={button} onClick={() => controller.clearTracingImage()}>\n Remove tracing\n </button>\n </>\n )}\n <button type=\"button\" className={button} onClick={() => refRef.current?.click()}>\n Reference…\n </button>\n <span className=\"flex items-center gap-1\" role=\"group\" aria-label=\"Stencils\">\n <button type=\"button\" className={button} title=\"A ruler: strokes that start near it follow it\" onClick={() => attempt(() => controller.addStencil(quickStencil('ruler', canvas)))}>\n Ruler\n </button>\n <button type=\"button\" className={button} title=\"A circle guide: strokes that start near it follow it\" onClick={() => attempt(() => controller.addStencil(quickStencil('circle', canvas)))}>\n Circle\n </button>\n <button type=\"button\" className={button} title=\"An ellipse mask: paint lands only inside it\" onClick={() => attempt(() => controller.addStencil(quickStencil('ellipse-mask', canvas)))}>\n Mask\n </button>\n {state.guides.stencils.length > 0 && (\n <button type=\"button\" className={button} onClick={() => attempt(() => controller.removeStencils())}>\n Clear stencils\n </button>\n )}\n </span>\n <button type=\"button\" className={button} title=\"Which hand holds the pen (palm rejection)\" onClick={() => controller.setHand(state.hand === 'right' ? 'left' : 'right')}>\n {state.hand === 'right' ? 'Right-handed' : 'Left-handed'}\n </button>\n <span className=\"mx-1 h-4 w-px bg-slate-700\" />\n <button type=\"button\" className={button} onClick={() => attempt(() => downloadBytes(JSON.stringify(controller.toJSON()), `${fileName}.paint.json`, 'application/json'))}>\n Save\n </button>\n <button type=\"button\" className={button} onClick={() => openRef.current?.click()}>\n Open…\n </button>\n <button type=\"button\" className={button} onClick={() => exportImage('image/png')}>\n PNG\n </button>\n <button type=\"button\" className={button} onClick={() => exportImage('image/jpeg')}>\n JPEG\n </button>\n <button type=\"button\" className={button} onClick={() => attempt(() => downloadBytes(controller.exportPsd().bytes, `${fileName}.psd`, 'image/vnd.adobe.photoshop'))}>\n PSD\n </button>\n <button\n type=\"button\"\n className={button}\n disabled={busy !== null}\n title=\"Repaint the painting from its strokes as a time-lapse: frames, a video project and the ffmpeg command, zipped\"\n onClick={() =>\n attempt(async () => {\n setBusy('Repainting…');\n try {\n const tl = await controller.timeLapse({ onProgress: (p) => setBusy(`Repainting… ${Math.round(p * 100)}%`) });\n downloadBytes(await timeLapseZip(tl), `${fileName}-timelapse.zip`, 'application/zip');\n setNote(`Time-lapse: ${tl.frames.length} frames, ${(tl.durationMs / 1000).toFixed(1)} s (run render.sh in the zip for the MP4).`);\n } finally {\n setBusy(null);\n }\n })\n }\n >\n Time-lapse\n </button>\n <button\n type=\"button\"\n className={button}\n disabled={busy !== null}\n title=\"Repaint the painting from its strokes at twice the size (more detail, not upscaled)\"\n onClick={() =>\n attempt(async () => {\n setBusy('Repainting at 2×…');\n try {\n downloadBytes(await controller.exportHighResPng({ scale: 2 }), `${fileName}@2x.png`, 'image/png');\n } finally {\n setBusy(null);\n }\n })\n }\n >\n PNG 2×\n </button>\n {(busy ?? note) && (\n <span className=\"text-[11px] text-slate-400\" data-testid=\"paint-replay-status\">\n {busy ?? note}\n </span>\n )}\n <input\n ref={openRef}\n type=\"file\"\n accept=\".json,application/json\"\n aria-label=\"Open painting\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) attempt(async () => controller.loadJSON(JSON.parse(await f.text())));\n e.target.value = '';\n }}\n />\n <input\n ref={tracingRef}\n type=\"file\"\n accept=\"image/*\"\n aria-label=\"Load tracing image\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) attempt(async () => controller.setTracingImage({ pixels: await decodeImageBlob(f) }));\n e.target.value = '';\n }}\n />\n <input\n ref={refRef}\n type=\"file\"\n accept=\"image/*\"\n aria-label=\"Add reference image\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) attempt(async () => controller.addReferenceImage({ pixels: await decodeImageBlob(f), name: f.name }));\n e.target.value = '';\n }}\n />\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React, { useEffect, useRef, useState } from 'react';\nimport type { SliderControl } from '@pixerate/editor/paint-editor';\n\nexport const chip = (on: boolean) => `px-2 py-1 rounded text-[11px] ${on ? 'bg-indigo-600 text-white' : 'bg-slate-800 text-slate-300 hover:text-white'}`;\nexport const button = 'px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-200 hover:bg-slate-700 disabled:opacity-40';\nexport const panel = 'flex flex-col gap-2 text-xs text-slate-200';\n\n/** Draws RGBA pixels into a canvas (nothing without a 2D context, as in jsdom). */\nexport const PixelCanvas: React.FC<{ pixels: { width: number; height: number; data: Uint8ClampedArray } | null; label: string; className?: string; style?: React.CSSProperties }> = ({ pixels, label, className, style }) => {\n const ref = useRef<HTMLCanvasElement>(null);\n useEffect(() => {\n const canvas = ref.current;\n const ctx = canvas?.getContext('2d');\n if (!canvas || !ctx || !pixels || typeof ctx.createImageData !== 'function') return;\n canvas.width = pixels.width;\n canvas.height = pixels.height;\n const img = ctx.createImageData(pixels.width, pixels.height);\n img.data.set(pixels.data);\n ctx.putImageData(img, 0, 0);\n }, [pixels]);\n return <canvas ref={ref} role=\"img\" aria-label={label} className={className} style={style} width={pixels?.width} height={pixels?.height} />;\n};\n\nconst fmt = (c: SliderControl, v: number) => (c.step >= 1 ? String(Math.round(v)) : v.toFixed(2));\n\n/**\n * A labelled range input. `onChange` runs while dragging; `onCommit` (if given) runs once on\n * release (the native `change` event), for settings that are undo steps.\n */\nexport const PaintSlider: React.FC<{ control: SliderControl; value: number; onChange?: (v: number) => void; onCommit?: (v: number) => void }> = ({ control, value, onChange, onCommit }) => {\n const [draft, setDraft] = useState<number | null>(null);\n const ref = useRef<HTMLInputElement>(null);\n const commit = useRef(onCommit);\n commit.current = onCommit;\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const done = () => {\n commit.current?.(Number(el.value));\n setDraft(null);\n };\n el.addEventListener('change', done);\n return () => el.removeEventListener('change', done);\n }, []);\n const shown = draft ?? value;\n return (\n <label className=\"flex flex-col gap-0.5\" data-path={control.path}>\n <span className=\"flex justify-between text-slate-400\">\n <span>{control.label}</span>\n <span className=\"font-mono\">{fmt(control, shown)}</span>\n </span>\n <input\n ref={ref}\n type=\"range\"\n aria-label={control.label}\n min={control.min}\n max={control.max}\n step={control.step}\n value={shown}\n onChange={(e) => {\n const v = Number(e.target.value);\n if (onCommit) setDraft(v);\n onChange?.(v);\n }}\n className=\"w-full accent-indigo-500\"\n />\n </label>\n );\n};\n\n/** Runs `fn`, turning a thrown error into a message. */\nexport function useAttempt(): [string | null, (fn: () => unknown) => void, (msg: string | null) => void] {\n const [error, setError] = useState<string | null>(null);\n const attempt = (fn: () => unknown) => {\n try {\n setError(null);\n const r = fn();\n if (r && typeof (r as Promise<unknown>).catch === 'function') (r as Promise<unknown>).catch((e) => setError(e instanceof Error ? e.message : String(e)));\n } catch (e) {\n setError(e instanceof Error ? e.message : String(e));\n }\n };\n return [error, attempt, setError];\n}\n\nexport const ErrorLine: React.FC<{ error: string | null }> = ({ error }) =>\n error ? (\n <p role=\"alert\" className=\"text-[11px] text-rose-400\">\n {error}\n </p>\n ) : null;\n\n/** A colour input that commits once when the picker closes (the native `change` event). */\nexport const CommitColorInput: React.FC<{ value: string; label: string; onCommit: (v: string) => void; className?: string }> = ({ value, label, onCommit, className }) => {\n const ref = useRef<HTMLInputElement>(null);\n const commit = useRef(onCommit);\n commit.current = onCommit;\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n const done = () => commit.current(el.value);\n el.addEventListener('change', done);\n return () => el.removeEventListener('change', done);\n }, []);\n return <input ref={ref} type=\"color\" aria-label={label} defaultValue={value} key={value} className={className} />;\n};\n","import React, { useMemo, useRef, useState } from 'react';\nimport {\n BLEND_MENU_GROUPS,\n BRUSH_ROTATIONS,\n BRUSH_SLIDERS,\n brushEngineControls,\n brushLoadColor,\n downloadBytes,\n brushTakesPaint,\n patchBrushValue,\n patchPath,\n readPath,\n WET_TOOLS,\n WET_TOOL_LABELS,\n WET_MEDIA,\n WET_MEDIUM_LABELS,\n IMPASTO_TOOLS,\n IMPASTO_TOOL_LABELS,\n PARTICLE_KINDS,\n PARTICLE_KIND_LABELS,\n PARTICLE_RENDERS,\n PARTICLE_RENDER_LABELS,\n STAMP_KINDS,\n STAMP_LABELS,\n toggleStamp,\n type ParticleKind,\n type ParticleRender,\n type ImpastoTool,\n type WetMediumKind,\n type BlendMode,\n type BrushRotation,\n type WetTool,\n type PaintEditorController,\n} from '@pixerate/editor/paint-editor';\nimport { DEFAULT_PAINT_GRADIENT } from '@pixerate/editor/paint-editor';\nimport { PaintGradientEditor } from './PaintGradientEditor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, PaintSlider, PixelCanvas, button, chip, panel, useAttempt } from './shared';\n\nexport interface BrushPanelProps {\n controller: PaintEditorController;\n /** Thumbnail size in px (default 112 × 32). */\n thumbnailWidth?: number;\n thumbnailHeight?: number;\n className?: string;\n}\n\n/**\n * The brush library (thumbnails rendered from a test stroke on the current paper, grouped by\n * category) and the active brush's settings: size, opacity, flow, hardness, spacing, roundness,\n * angle, paper grain, position and pressure smoothing, dynamics, rotation mode and blend mode;\n * then the engine's own controls (`brushEngineControls`): blender strength and blend distance,\n * smudge strength and length, pick-up and mix ratios, RGB / pigment mixing, dirty brush,\n * the brush's own gradient paint (the multi-colour brush) and the brush load. Save the edited brush, import and export libraries as JSON.\n */\nexport const BrushPanel: React.FC<BrushPanelProps> = ({ controller, thumbnailWidth = 112, thumbnailHeight = 32, className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const [saveName, setSaveName] = useState('');\n const fileRef = useRef<HTMLInputElement>(null);\n const { brush, brushes } = state;\n const paper = state.document.paper;\n const thumbs = useMemo(\n () => new Map(brushes.map((b) => [b.id, controller.brushThumbnail(b.id, { width: thumbnailWidth, height: thumbnailHeight, color: '#26324a' })])),\n // Thumbnails follow the library and the paper.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [controller, brushes, paper, thumbnailWidth, thumbnailHeight]\n );\n const engine = brushEngineControls(brush);\n const carried = brushLoadColor(state.mixerLoad);\n const slug = (name: string) => name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '').slice(0, 60) || 'brush';\n\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"brush-panel\">\n <div className=\"grid grid-cols-2 gap-1\" role=\"listbox\" aria-label=\"Brushes\">\n {brushes.map((b) => (\n <button\n key={b.id}\n type=\"button\"\n role=\"option\"\n aria-selected={brush.id === b.id}\n title={`${b.name} (${b.category})`}\n className={`flex flex-col items-start gap-0.5 rounded p-1 text-left ${brush.id === b.id ? 'bg-indigo-600/30 ring-1 ring-indigo-500' : 'bg-slate-900 hover:bg-slate-800'}`}\n onClick={() => controller.setBrush({ id: b.id })}\n >\n <PixelCanvas pixels={thumbs.get(b.id) ?? null} label={`${b.name} thumbnail`} className=\"rounded\" style={{ width: '100%', aspectRatio: `${thumbnailWidth} / ${thumbnailHeight}` }} />\n <span className=\"truncate text-[10px] text-slate-300\">{b.name}</span>\n </button>\n ))}\n </div>\n <div className=\"flex flex-col gap-1.5\">\n {BRUSH_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(brush, c.path)} onChange={(v) => controller.setBrush(patchPath(brush as never, c.path, v) as never)} />\n ))}\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Rotation</span>\n <select aria-label=\"Brush rotation\" value={brush.rotation} onChange={(e) => controller.setBrush({ rotation: e.target.value as BrushRotation })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {BRUSH_ROTATIONS.map((r) => (\n <option key={r} value={r}>\n {r === 'stroke' ? 'Follow stroke' : r === 'barrel' ? 'Pen barrel' : 'Fixed'}\n </option>\n ))}\n </select>\n </label>\n <label className=\"flex items-center gap-2\">\n <input type=\"checkbox\" checked={brush.tip.pressureSize} onChange={(e) => controller.setBrush({ tip: { pressureSize: e.target.checked } })} /> Pressure → size\n </label>\n <label className=\"flex items-center gap-2\">\n <input type=\"checkbox\" checked={brush.tip.pressureOpacity} onChange={(e) => controller.setBrush({ tip: { pressureOpacity: e.target.checked } })} /> Pressure → opacity\n </label>\n {brush.engine === 'dab' && (\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Blend</span>\n <select aria-label=\"Brush blend\" value={brush.tip.blend} onChange={(e) => controller.setBrush({ tip: { blend: e.target.value as BlendMode } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {BLEND_MENU_GROUPS.map((g) => (\n <optgroup key={g.label} label={g.label}>\n {g.modes.map((m) => (\n <option key={m.id} value={m.id} title={m.description}>\n {m.label}\n </option>\n ))}\n </optgroup>\n ))}\n </select>\n </label>\n )}\n </div>\n {engine && (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"brush-engine\">\n <span className=\"font-medium text-slate-300\">{engine.title}</span>\n {engine.wetTool && (\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Wet tool</span>\n <select aria-label=\"Wet tool\" value={brush.wet.tool} onChange={(e) => controller.setBrush({ wet: { tool: e.target.value as WetTool } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {WET_TOOLS.map((t) => (\n <option key={t} value={t}>\n {WET_TOOL_LABELS[t]}\n </option>\n ))}\n </select>\n </label>\n )}\n {engine.wetTool && (\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Medium</span>\n <select aria-label=\"Wet medium\" value={brush.wet.medium} onChange={(e) => controller.setBrush({ wet: { medium: e.target.value as WetMediumKind } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {WET_MEDIA.map((m) => (\n <option key={m} value={m}>\n {WET_MEDIUM_LABELS[m]}\n </option>\n ))}\n </select>\n </label>\n )}\n {engine.particleMenus && (\n <>\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Particles</span>\n <select aria-label=\"Particle kind\" value={brush.particle.kind} onChange={(e) => controller.setBrush({ particle: { kind: e.target.value as ParticleKind } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {PARTICLE_KINDS.map((k) => (\n <option key={k} value={k}>\n {PARTICLE_KIND_LABELS[k]}\n </option>\n ))}\n </select>\n </label>\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Drawn as</span>\n <select aria-label=\"Particle render\" value={brush.particle.render} onChange={(e) => controller.setBrush({ particle: { render: e.target.value as ParticleRender } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {PARTICLE_RENDERS.map((k) => (\n <option key={k} value={k}>\n {PARTICLE_RENDER_LABELS[k]}\n </option>\n ))}\n </select>\n </label>\n </>\n )}\n {engine.stickerStamps && (\n <div className=\"flex flex-wrap gap-1\" role=\"group\" aria-label=\"Sticker stamps\">\n {STAMP_KINDS.map((k) => (\n <button\n key={k}\n type=\"button\"\n aria-pressed={brush.sticker.stamps.includes(k)}\n className={`px-1.5 py-0.5 rounded text-[10px] ${brush.sticker.stamps.includes(k) ? 'bg-indigo-600 text-white' : 'bg-slate-800 text-slate-300'}`}\n onClick={() => controller.setBrush({ sticker: { stamps: toggleStamp(brush.sticker.stamps, k) } })}\n >\n {STAMP_LABELS[k]}\n </button>\n ))}\n </div>\n )}\n {engine.impastoTool && (\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Tool</span>\n <select aria-label=\"Impasto tool\" value={brush.impasto.tool} onChange={(e) => controller.setBrush({ impasto: { tool: e.target.value as ImpastoTool } })} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {IMPASTO_TOOLS.map((t) => (\n <option key={t} value={t}>\n {IMPASTO_TOOL_LABELS[t]}\n </option>\n ))}\n </select>\n </label>\n )}\n {engine.sliders.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(brush, c.path)} onChange={(v) => controller.setBrush(patchPath(brush as never, c.path, v) as never)} />\n ))}\n {engine.mixingPath && (\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Mixing</span>\n <select\n aria-label=\"Brush mixing\"\n value={engine.mixingPath === 'blender.mixing' ? brush.blender.mixing : engine.mixingPath === 'smudge.mixing' ? brush.smudge.mixing : brush.behavior.mixing}\n onChange={(e) => controller.setBrush(patchBrushValue(brush, engine.mixingPath!, e.target.value))}\n className=\"rounded bg-slate-800 px-1 py-0.5\"\n >\n <option value=\"pigment\">Pigment</option>\n <option value=\"rgb\">RGB</option>\n </select>\n </label>\n )}\n {engine.dirty && (\n <label className=\"flex items-center gap-2\" title=\"Keep the colour the brush picked up for the next stroke (needs Pick-up above 0)\">\n <input type=\"checkbox\" aria-label=\"Dirty brush\" checked={brush.behavior.dirty} onChange={(e) => controller.setBrush({ behavior: { dirty: e.target.checked } })} /> Dirty brush\n </label>\n )}\n {brushTakesPaint(brush) && (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"brush-gradient\">\n <div className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\" title=\"A gradient of the brush's own, used instead of the paint (the multi-colour brush)\">\n Brush gradient\n </span>\n <button\n type=\"button\"\n aria-pressed={brush.paint !== null}\n className={chip(brush.paint !== null)}\n onClick={() => attempt(() => controller.setBrush({ paint: brush.paint ? null : DEFAULT_PAINT_GRADIENT }))}\n >\n {brush.paint ? 'On' : 'Off'}\n </button>\n </div>\n {brush.paint && <PaintGradientEditor value={brush.paint} colors={{ paint: state.color, secondary: state.secondaryColor }} onChange={(g) => attempt(() => controller.setBrush({ paint: g }))} />}\n </div>\n )}\n {engine.load && (\n <div className=\"flex items-center gap-1\">\n <span className=\"text-slate-400\">Carries</span>\n <span aria-label=\"Brush load\" title={carried ?? 'Clean'} className=\"h-4 w-4 rounded ring-1 ring-slate-700\" style={{ background: carried ?? 'transparent' }} />\n {brush.engine === 'mixer' && (\n <button type=\"button\" className={button} onClick={() => controller.loadMixerBrush()}>\n Load\n </button>\n )}\n <button type=\"button\" className={button} onClick={() => controller.cleanMixerBrush(brush.engine === 'mixer')}>\n Clean\n </button>\n </div>\n )}\n </div>\n )}\n <div className=\"flex flex-wrap items-center gap-1\">\n <input value={saveName} placeholder=\"Brush name\" aria-label=\"Brush name\" onChange={(e) => setSaveName(e.target.value)} className=\"w-28 rounded bg-slate-800 px-1.5 py-0.5\" />\n <button type=\"button\" className={button} disabled={!saveName.trim()} onClick={() => attempt(() => (controller.saveBrush({ id: slug(saveName), name: saveName.trim() }), setSaveName('')))}>\n Save brush\n </button>\n <button type=\"button\" className={button} onClick={() => attempt(() => downloadBytes(JSON.stringify(controller.exportBrushes(), null, 2), 'brushes.json', 'application/json'))}>\n Export\n </button>\n <button type=\"button\" className={button} onClick={() => fileRef.current?.click()}>\n Import…\n </button>\n <input\n ref={fileRef}\n type=\"file\"\n accept=\".json,application/json\"\n aria-label=\"Import brushes\"\n className=\"hidden\"\n onChange={(e) => {\n const f = e.target.files?.[0];\n if (f) attempt(async () => controller.importBrushes(JSON.parse(await f.text())));\n e.target.value = '';\n }}\n />\n </div>\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React from 'react';\nimport { PAINT_GRADIENT_KIT } from '@pixerate/editor/paint-editor';\nimport { PaintGradientEditorView, type PaintGradientEditorProps } from './PaintGradientEditorView';\n\nexport type { PaintGradientEditorProps } from './PaintGradientEditorView';\n\n/** The gradient paint editor (see `PaintGradientEditorView`). */\nexport const PaintGradientEditor: React.FC<PaintGradientEditorProps> = (props) => <PaintGradientEditorView {...props} kit={PAINT_GRADIENT_KIT} />;\n","import React, { useState } from 'react';\nimport type { PaintGradientKit, PaintGradientMappingKind, PaintGradientRepeat, PaintGradientSource, PaintGradientSpace } from '@pixerate/editor/paint-editor';\n\nexport interface PaintGradientEditorProps {\n value: PaintGradientSource;\n onChange: (paint: PaintGradientSource) => void;\n /** What `paint` / `secondary` stops show as (the editor's two colours). */\n colors: { paint: string; secondary: string };\n className?: string;\n}\n\nexport interface PaintGradientEditorViewProps extends PaintGradientEditorProps {\n /** The gradient helpers (`PAINT_GRADIENT_KIT`, from the editor's own entry). */\n kit: PaintGradientKit;\n}\n\nconst button = 'px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-200 hover:bg-slate-700 disabled:opacity-40';\nconst select = 'rounded bg-slate-800 px-1 py-0.5 text-[11px]';\nconst number = 'w-16 rounded bg-slate-800 px-1 py-0.5 text-[11px]';\nconst pct = (v: number) => Math.round(v * 1000) / 10;\n\n/**\n * Gradient paint editor (the vector editor's stop ramp, for paint): click the ramp to add a stop,\n * pick a stop to edit its colour (or the paint / second colour), opacity, position and midpoint;\n * the mixing space, what moves the stroke along it (distance with length and repeat, pressure,\n * tilt, speed, direction, time, across the tip, random), softness, reverse, and starting presets.\n */\nexport const PaintGradientEditorView: React.FC<PaintGradientEditorViewProps> = ({ value, onChange, colors, className, kit }) => {\n const {\n PAINT_GRADIENT_MAPPINGS,\n PAINT_GRADIENT_MAPPING_LABELS,\n PAINT_GRADIENT_PRESETS,\n PAINT_GRADIENT_REPEATS,\n PAINT_GRADIENT_REPEAT_LABELS,\n PAINT_GRADIENT_SPACES,\n PAINT_GRADIENT_SPACE_LABELS,\n addPaintGradientStop,\n paintGradientMappingFor,\n paintSourceCss,\n removePaintGradientStop,\n reversePaintGradient,\n updatePaintGradientStop,\n } = kit;\n const [selected, setSelected] = useState(0);\n const sel = Math.min(selected, value.stops.length - 1);\n const stop = value.stops[sel];\n const map = value.map;\n const stopHex = (c: string) => (c === 'paint' ? colors.paint : c === 'secondary' ? colors.secondary : c);\n const patchStop = (patch: Parameters<PaintGradientKit['updatePaintGradientStop']>[2]) => {\n const r = updatePaintGradientStop(value, sel, patch);\n setSelected(r.index);\n onChange(r.paint);\n };\n return (\n <div className={`flex flex-col gap-1.5 text-xs text-slate-200 ${className ?? ''}`} data-testid=\"paint-gradient-editor\" aria-label=\"Gradient paint\">\n <div className=\"flex items-center gap-1\">\n <select aria-label=\"Gradient preset\" className={select} value=\"\" onChange={(e) => e.target.value && (setSelected(0), onChange(PAINT_GRADIENT_PRESETS[Number(e.target.value)].paint))}>\n <option value=\"\">Presets…</option>\n {PAINT_GRADIENT_PRESETS.map((p, i) => (\n <option key={p.name} value={i}>\n {p.name}\n </option>\n ))}\n </select>\n <button type=\"button\" className={button} onClick={() => onChange(reversePaintGradient(value))}>\n Reverse\n </button>\n </div>\n <div\n role=\"slider\"\n tabIndex={0}\n aria-label=\"Gradient ramp: click to add a stop\"\n aria-valuemin={0}\n aria-valuemax={100}\n aria-valuenow={pct(stop.offset)}\n data-testid=\"paint-gradient-ramp\"\n className=\"relative h-6 cursor-copy rounded ring-1 ring-slate-700\"\n style={{ background: paintSourceCss(value, colors) }}\n onClick={(e) => {\n const rect = e.currentTarget.getBoundingClientRect();\n const r = addPaintGradientStop(value, rect.width ? (e.clientX - rect.left) / rect.width : 0.5, colors);\n if (r.index >= 0) {\n setSelected(r.index);\n onChange(r.paint);\n }\n }}\n />\n <div className=\"relative h-4\" aria-label=\"Stops\">\n {value.stops.map((s, i) => (\n <button\n key={i}\n type=\"button\"\n aria-label={`Stop ${i + 1} at ${pct(s.offset)}%`}\n aria-pressed={i === sel}\n className={`absolute top-0 h-4 w-3 -translate-x-1/2 rounded-sm ring-1 ${i === sel ? 'ring-white' : 'ring-slate-600'}`}\n style={{ left: `${s.offset * 100}%`, background: stopHex(s.color) }}\n onClick={() => setSelected(i)}\n />\n ))}\n </div>\n <div className=\"flex flex-wrap items-center gap-1\" data-testid=\"paint-gradient-stop\">\n <select aria-label=\"Stop colour source\" className={select} value={stop.color === 'paint' || stop.color === 'secondary' ? stop.color : 'color'} onChange={(e) => patchStop({ color: e.target.value === 'color' ? stopHex(stop.color) : e.target.value })}>\n <option value=\"color\">Colour</option>\n <option value=\"paint\">Paint colour</option>\n <option value=\"secondary\">Second colour</option>\n </select>\n {stop.color !== 'paint' && stop.color !== 'secondary' && <input type=\"color\" aria-label=\"Stop colour\" value={stop.color} onChange={(e) => patchStop({ color: e.target.value })} className=\"h-6 w-8 rounded bg-transparent\" />}\n <label className=\"flex items-center gap-1\">\n At\n <input type=\"number\" aria-label=\"Stop position\" min={0} max={100} step={1} value={pct(stop.offset)} onChange={(e) => patchStop({ offset: Number(e.target.value) / 100 })} className={number} />%\n </label>\n <label className=\"flex items-center gap-1\">\n Opacity\n <input type=\"number\" aria-label=\"Stop opacity\" min={0} max={100} step={5} value={pct(stop.opacity ?? 1)} onChange={(e) => patchStop({ opacity: Number(e.target.value) / 100 })} className={number} />%\n </label>\n {sel < value.stops.length - 1 && (\n <label className=\"flex items-center gap-1\">\n Midpoint\n <input type=\"number\" aria-label=\"Stop midpoint\" min={5} max={95} step={1} value={pct(stop.midpoint ?? 0.5)} onChange={(e) => patchStop({ midpoint: Number(e.target.value) / 100 })} className={number} />%\n </label>\n )}\n <button type=\"button\" className={button} disabled={value.stops.length <= 2} onClick={() => (setSelected(Math.max(0, sel - 1)), onChange(removePaintGradientStop(value, sel)))}>\n Remove stop\n </button>\n </div>\n <div className=\"flex flex-wrap items-center gap-1\" data-testid=\"paint-gradient-mapping\">\n <select aria-label=\"Gradient follows\" className={select} value={map.by} onChange={(e) => onChange({ ...value, map: paintGradientMappingFor(e.target.value as PaintGradientMappingKind, map) })}>\n {PAINT_GRADIENT_MAPPINGS.map((m) => (\n <option key={m} value={m}>\n {PAINT_GRADIENT_MAPPING_LABELS[m]}\n </option>\n ))}\n </select>\n {map.by === 'distance' && (\n <>\n <input type=\"number\" aria-label=\"Gradient length\" min={1} max={100000} value={map.length} onChange={(e) => onChange({ ...value, map: { ...map, length: Math.max(1, Number(e.target.value) || 1) } })} className={number} />\n <select aria-label=\"Gradient length unit\" className={select} value={map.unit ?? 'px'} onChange={(e) => onChange({ ...value, map: { ...map, unit: e.target.value as 'px' | 'dabs' } })}>\n <option value=\"px\">px</option>\n <option value=\"dabs\">dabs</option>\n </select>\n </>\n )}\n {map.by === 'time' && <input type=\"number\" aria-label=\"Gradient duration\" min={1} max={600000} value={map.duration} onChange={(e) => onChange({ ...value, map: { ...map, duration: Math.max(1, Number(e.target.value) || 1) } })} className={number} />}\n {map.by === 'random' && <input type=\"number\" aria-label=\"Dabs per pick\" min={1} max={500} value={map.every ?? 1} onChange={(e) => onChange({ ...value, map: { ...map, every: Math.max(1, Math.round(Number(e.target.value) || 1)) } })} className={number} />}\n {(map.by === 'distance' || map.by === 'time') && (\n <select aria-label=\"Gradient repeat\" className={select} value={map.repeat ?? 'clamp'} onChange={(e) => onChange({ ...value, map: { ...map, repeat: e.target.value as PaintGradientRepeat } })}>\n {PAINT_GRADIENT_REPEATS.map((r) => (\n <option key={r} value={r}>\n {PAINT_GRADIENT_REPEAT_LABELS[r]}\n </option>\n ))}\n </select>\n )}\n </div>\n <div className=\"flex items-center gap-1\">\n <select aria-label=\"Gradient mixing\" className={select} value={value.space} onChange={(e) => onChange({ ...value, space: e.target.value as PaintGradientSpace })}>\n {PAINT_GRADIENT_SPACES.map((s) => (\n <option key={s} value={s}>\n {PAINT_GRADIENT_SPACE_LABELS[s]}\n </option>\n ))}\n </select>\n <label className=\"flex flex-1 items-center gap-1\">\n Softness\n <input type=\"range\" aria-label=\"Gradient softness\" min={0} max={1} step={0.05} value={value.softness ?? 1} onChange={(e) => onChange({ ...value, softness: Number(e.target.value) })} className=\"flex-1 accent-indigo-500\" />\n </label>\n </div>\n </div>\n );\n};\n","import React, { useMemo } from 'react';\nimport { LIGHT_SLIDERS, PAPER_FAMILIES, PAPER_LIBRARY, PAPER_SLIDERS, patchPath, readPath, renderPaper, type PaintEditorController } from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { CommitColorInput, ErrorLine, PaintSlider, PixelCanvas, panel, useAttempt } from './shared';\n\nexport interface PaperPanelProps {\n controller: PaintEditorController;\n className?: string;\n}\n\nconst SWATCH = { x: 0, y: 0, width: 64, height: 40 };\n\n/**\n * The paper library by family (each a generated grain preview) and the current paper's colour,\n * grain depth, scale, shading and contrast, the wet-media properties and metallic sheen (each\n * change one undo step; sliders commit on release); then the light for thick paint and metallic\n * paper (not an undo step) and Flatten relief for the active layer.\n */\nexport const PaperPanel: React.FC<PaperPanelProps> = ({ controller, className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const paper = state.document.paper;\n const previews = useMemo(() => new Map(PAPER_LIBRARY.map((p) => [p.preset, { ...SWATCH, data: renderPaper({ ...p, shading: Math.max(0.8, p.shading) }, SWATCH) }])), []);\n\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"paper-panel\">\n {PAPER_FAMILIES.map((family) => (\n <div key={family}>\n <div className=\"mb-0.5 text-[10px] uppercase tracking-wide text-slate-500\">{family}</div>\n <div className=\"flex flex-wrap gap-1\" role=\"listbox\" aria-label={`${family} papers`}>\n {PAPER_LIBRARY.filter((p) => p.family === family).map((p) => (\n <button\n key={p.preset}\n type=\"button\"\n role=\"option\"\n aria-selected={paper.preset === p.preset}\n title={p.name}\n className={`rounded p-0.5 ${paper.preset === p.preset ? 'ring-2 ring-indigo-500' : 'ring-1 ring-slate-700 hover:ring-slate-500'}`}\n onClick={() => attempt(() => controller.setPaper({ preset: p.preset }))}\n >\n <PixelCanvas pixels={previews.get(p.preset) ?? null} label={p.name} style={{ width: 48, height: 30 }} />\n </button>\n ))}\n </div>\n </div>\n ))}\n <div className=\"text-slate-300\">{paper.name}</div>\n <label className=\"flex items-center justify-between\">\n <span className=\"text-slate-400\">Colour</span>\n <CommitColorInput label=\"Paper colour\" value={paper.color} onCommit={(v) => attempt(() => controller.setPaper({ color: v }))} className=\"h-6 w-10 rounded bg-transparent\" />\n </label>\n {PAPER_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(paper, c.path)} onCommit={(v) => attempt(() => controller.setPaper(patchPath(paper as never, c.path, v) as never))} />\n ))}\n <label className=\"flex items-center gap-2\">\n <input type=\"checkbox\" checked={paper.tiling === 'mirror'} onChange={(e) => attempt(() => controller.setPaper({ tiling: e.target.checked ? 'mirror' : 'repeat' }))} /> Mirror tiling\n </label>\n <button type=\"button\" className=\"self-start px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-200 hover:bg-slate-700\" onClick={() => attempt(() => controller.setPaper({ seed: paper.seed + 1 }))}>\n New sheet\n </button>\n <div className=\"flex flex-col gap-1.5\" data-testid=\"light-panel\">\n <span className=\"font-medium text-slate-300\">Light (thick paint, metallic paper)</span>\n {LIGHT_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(controller.getLighting(), c.path)} onChange={(v) => attempt(() => controller.setLighting({ [c.path]: v }))} />\n ))}\n <button type=\"button\" className=\"self-start px-2 py-1 rounded text-[11px] bg-slate-800 text-slate-200 hover:bg-slate-700\" onClick={() => attempt(() => controller.flattenRelief())}>\n Flatten relief\n </button>\n </div>\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React, { useMemo, useRef, useState } from 'react';\nimport {\n HARMONY_KINDS,\n MIXING_PAD_HEIGHT,\n MIXING_PAD_WIDTH,\n PAD_SAMPLE_SIZES,\n hsvToRgb,\n padSampleRadius,\n hueToWheel,\n parseHexColor,\n renderColorWheel,\n rgbToHexColor,\n rgbToHsv,\n wheelPick,\n wheelPoint,\n type ColorWheel,\n type HarmonyKind,\n type PaintEditorController,\n} from '@pixerate/editor/paint-editor';\nimport { DEFAULT_PAINT_GRADIENT, paintSourceCss } from '@pixerate/editor/paint-editor';\nimport { PaintGradientEditor } from './PaintGradientEditor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, PixelCanvas, button, chip, panel, useAttempt } from './shared';\n\nexport interface ColorPanelProps {\n controller: PaintEditorController;\n /** Wheel diameter in px (default 168). */\n wheelSize?: number;\n /** Show the mixing pad (default true). */\n mixingPad?: boolean;\n className?: string;\n}\n\ntype PadTool = 'paint' | 'knife' | 'pick';\n\n/**\n * Colour: a hue wheel (painter's RYB or RGB) with the chosen harmony marked on it, saturation and\n * value, the paint and second colours, harmony chips, swatches, and a mixing pad to paint on,\n * smear with a palette knife (pigment mixing) and pick from (with a sample size), mix the paint\n * and second colours in measured parts on, and keep by name.\n */\nexport const ColorPanel: React.FC<ColorPanelProps> = ({ controller, wheelSize = 168, mixingPad = true, className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const [wheel, setWheel] = useState<ColorWheel>('ryb');\n const [kind, setKind] = useState<HarmonyKind>('complementary');\n const [padTool, setPadTool] = useState<PadTool>('paint');\n const [sample, setSample] = useState(3);\n const [parts, setParts] = useState<[number, number]>([1, 1]);\n const [padName, setPadName] = useState('');\n const padPoints = useRef<Array<{ x: number; y: number; pressure?: number }> | null>(null);\n const ring = useMemo(() => renderColorWheel(wheelSize, wheel), [wheelSize, wheel]);\n const color = state.color;\n const harmony = useMemo(() => controller.harmony(kind, { color, wheel }), [controller, kind, color, wheel]);\n const [r, g, b] = parseHexColor(color);\n const hsv = rgbToHsv(r, g, b);\n const pad = useMemo(() => ({ width: MIXING_PAD_WIDTH, height: MIXING_PAD_HEIGHT, data: controller.mixingPad.pixels() }), [controller, state.mixingPadVersion]);\n const R = wheelSize / 2;\n const mid = R * 0.82;\n const setHsv = (s: number, v: number) => controller.setColor(rgbToHexColor(...hsvToRgb(hsv.h, s, v)));\n\n const padPoint = (e: React.PointerEvent) => {\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n const kx = MIXING_PAD_WIDTH / (rect.width || MIXING_PAD_WIDTH);\n const ky = MIXING_PAD_HEIGHT / (rect.height || MIXING_PAD_HEIGHT);\n const x = Math.min(MIXING_PAD_WIDTH, Math.max(0, (e.clientX - rect.left) * kx));\n const y = Math.min(MIXING_PAD_HEIGHT, Math.max(0, (e.clientY - rect.top) * ky));\n return e.pointerType === 'pen' && e.pressure > 0 ? { x, y, pressure: e.pressure } : { x, y };\n };\n\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"color-panel\">\n <div className=\"relative self-center\" style={{ width: wheelSize, height: wheelSize }}>\n <div\n role=\"slider\"\n aria-label=\"Hue wheel\"\n aria-valuemin={0}\n aria-valuemax={360}\n aria-valuenow={Math.round(hueToWheel(hsv.h, wheel))}\n tabIndex={0}\n className=\"absolute inset-0 cursor-crosshair\"\n onPointerDown={(e) => {\n const rect = e.currentTarget.getBoundingClientRect();\n controller.setColor(wheelPick(e.clientX - rect.left - R, e.clientY - rect.top - R, wheel, color));\n }}\n >\n <PixelCanvas pixels={ring} label=\"Colour wheel\" style={{ width: wheelSize, height: wheelSize }} />\n </div>\n <svg className=\"pointer-events-none absolute inset-0\" width={wheelSize} height={wheelSize} aria-hidden=\"true\">\n {harmony.map((h, i) => {\n const p = wheelPoint(h.angle, mid);\n return <circle key={i} cx={R + p.x} cy={R + p.y} r={i === 0 ? 7 : 5} fill={h.color} stroke=\"#fff\" strokeWidth={i === 0 ? 2 : 1} />;\n })}\n </svg>\n <div className=\"absolute rounded-full border border-slate-700\" style={{ left: R - R * 0.45, top: R - R * 0.45, width: R * 0.9, height: R * 0.9, background: color }} />\n </div>\n <div className=\"flex items-center gap-2\">\n <input type=\"color\" aria-label=\"Paint colour\" value={color} onChange={(e) => controller.setColor(e.target.value)} className=\"h-7 w-9 rounded bg-transparent\" />\n <input type=\"color\" aria-label=\"Second colour\" value={state.secondaryColor} onChange={(e) => controller.setSecondaryColor(e.target.value)} className=\"h-5 w-7 rounded bg-transparent\" />\n <button type=\"button\" className={button} title=\"Swap colours (X)\" onClick={() => controller.swapColors()}>\n Swap\n </button>\n <input\n aria-label=\"Hex colour\"\n defaultValue={color}\n key={color}\n onBlur={(e) => attempt(() => controller.setColor(e.target.value.startsWith('#') ? e.target.value : `#${e.target.value}`))}\n className=\"w-20 rounded bg-slate-800 px-1.5 py-0.5 font-mono\"\n />\n </div>\n <div className=\"flex items-center gap-2\" data-testid=\"paint-source\">\n <span\n className=\"h-5 flex-1 rounded ring-1 ring-slate-700\"\n aria-label={state.paint.type === 'gradient' ? 'Gradient paint' : 'Paint colour'}\n data-testid=\"paint-well\"\n style={{ background: paintSourceCss(state.paint, { paint: color, secondary: state.secondaryColor }) }}\n />\n <button\n type=\"button\"\n className={chip(state.paint.type === 'gradient')}\n aria-pressed={state.paint.type === 'gradient'}\n title=\"Paint that changes colour as the stroke goes\"\n onClick={() => attempt(() => (state.paint.type === 'gradient' ? controller.setColor(color) : controller.setPaint(DEFAULT_PAINT_GRADIENT)))}\n >\n Gradient\n </button>\n </div>\n {state.paint.type === 'gradient' && (\n <PaintGradientEditor value={state.paint} colors={{ paint: color, secondary: state.secondaryColor }} onChange={(g) => attempt(() => controller.setPaint(g))} />\n )}\n <label className=\"flex items-center gap-2\">\n <span className=\"w-16 text-slate-400\">Saturation</span>\n <input type=\"range\" aria-label=\"Saturation\" min={0} max={1} step={0.01} value={hsv.s} onChange={(e) => setHsv(Number(e.target.value), hsv.v)} className=\"flex-1 accent-indigo-500\" />\n </label>\n <label className=\"flex items-center gap-2\">\n <span className=\"w-16 text-slate-400\">Value</span>\n <input type=\"range\" aria-label=\"Value\" min={0} max={1} step={0.01} value={hsv.v} onChange={(e) => setHsv(hsv.s, Number(e.target.value))} className=\"flex-1 accent-indigo-500\" />\n </label>\n <div className=\"flex items-center gap-1\">\n <select aria-label=\"Harmony\" value={kind} onChange={(e) => setKind(e.target.value as HarmonyKind)} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {HARMONY_KINDS.map((k) => (\n <option key={k} value={k}>\n {k}\n </option>\n ))}\n </select>\n <button type=\"button\" className={chip(wheel === 'ryb')} aria-pressed={wheel === 'ryb'} onClick={() => setWheel('ryb')}>\n RYB\n </button>\n <button type=\"button\" className={chip(wheel === 'rgb')} aria-pressed={wheel === 'rgb'} onClick={() => setWheel('rgb')}>\n RGB\n </button>\n </div>\n <div className=\"flex flex-wrap gap-1\" aria-label=\"Harmony colours\">\n {harmony.map((h, i) => (\n <button key={i} type=\"button\" aria-label={`Use ${h.color}`} title={h.color} className=\"h-6 w-6 rounded ring-1 ring-slate-700\" style={{ background: h.color }} onClick={() => controller.setColor(h.color)} />\n ))}\n <button type=\"button\" className={button} onClick={() => harmony.forEach((h) => controller.addSwatch(h.color))}>\n + swatches\n </button>\n </div>\n <div className=\"flex flex-wrap gap-1\" role=\"listbox\" aria-label=\"Swatches\">\n {state.swatches.map((s, i) => (\n <button\n key={i}\n type=\"button\"\n role=\"option\"\n aria-selected={s.paint ? state.paint === s.paint : state.paint.type === 'color' && s.color === color}\n aria-label={s.name ?? (s.paint ? 'Gradient' : s.color)}\n title={`${s.name ?? (s.paint ? 'Gradient' : s.color)} (right-click to remove)`}\n className=\"h-5 w-5 rounded ring-1 ring-slate-700\"\n style={{ background: s.paint ? paintSourceCss(s.paint, { paint: color, secondary: state.secondaryColor }) : s.color }}\n onClick={() => attempt(() => (s.paint ? controller.setPaint(s.paint) : controller.setColor(s.color)))}\n onContextMenu={(e) => {\n e.preventDefault();\n controller.removeSwatch(i);\n }}\n />\n ))}\n <button type=\"button\" className={button} aria-label=\"Add swatch\" onClick={() => attempt(() => controller.addSwatch(state.paint))}>\n +\n </button>\n </div>\n {mixingPad && (\n <div className=\"flex flex-col gap-1\" data-testid=\"mixing-pad\">\n <div className=\"flex items-center gap-1\">\n <span className=\"text-slate-400\">Mixing pad</span>\n {(['paint', 'knife', 'pick'] as const).map((t) => (\n <button key={t} type=\"button\" aria-pressed={padTool === t} className={chip(padTool === t)} onClick={() => setPadTool(t)}>\n {t === 'paint' ? 'Paint' : t === 'knife' ? 'Knife' : 'Pick'}\n </button>\n ))}\n <button type=\"button\" className={button} onClick={() => controller.clearMixingPad()}>\n Clear\n </button>\n </div>\n <div\n role=\"application\"\n aria-label=\"Mixing pad\"\n className=\"touch-none cursor-crosshair\"\n onPointerDown={(e) => {\n const p = padPoint(e);\n if (padTool === 'pick') {\n attempt(() => controller.mixingPadPick(p.x, p.y, { setColor: true, radius: padSampleRadius(sample) }));\n return;\n }\n padPoints.current = [p];\n (e.target as Element).setPointerCapture?.(e.pointerId);\n }}\n onPointerMove={(e) => padPoints.current?.push(padPoint(e))}\n onPointerUp={() => {\n const pts = padPoints.current;\n padPoints.current = null;\n if (pts?.length) attempt(() => controller.mixingPadStroke(pts, { tool: padTool === 'knife' ? 'knife' : 'paint' }));\n }}\n >\n <PixelCanvas pixels={pad} label=\"Mixing pad pixels\" className=\"w-full rounded\" style={{ aspectRatio: `${MIXING_PAD_WIDTH} / ${MIXING_PAD_HEIGHT}` }} />\n </div>\n <div className=\"flex flex-wrap items-center gap-1\">\n <label className=\"flex items-center gap-1\">\n <span className=\"text-slate-400\">Sample</span>\n <select aria-label=\"Pick sample size\" value={sample} onChange={(e) => setSample(Number(e.target.value))} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {PAD_SAMPLE_SIZES.map((n) => (\n <option key={n} value={n}>\n {n === 1 ? '1 px' : `${n}×${n}`}\n </option>\n ))}\n </select>\n </label>\n </div>\n <div className=\"flex flex-wrap items-center gap-1\">\n <span className=\"h-4 w-4 rounded ring-1 ring-slate-700\" style={{ background: color }} />\n <input type=\"number\" aria-label=\"Paint colour parts\" min={0} max={20} value={parts[0]} onChange={(e) => setParts([Number(e.target.value), parts[1]])} className=\"w-10 rounded bg-slate-800 px-1 py-0.5\" />\n <span className=\"text-slate-500\">:</span>\n <input type=\"number\" aria-label=\"Second colour parts\" min={0} max={20} value={parts[1]} onChange={(e) => setParts([parts[0], Number(e.target.value)])} className=\"w-10 rounded bg-slate-800 px-1 py-0.5\" />\n <span className=\"h-4 w-4 rounded ring-1 ring-slate-700\" style={{ background: state.secondaryColor }} />\n <button\n type=\"button\"\n className={button}\n title=\"Mix the paint and second colours in these parts on the pad, and use the mix\"\n onClick={() =>\n attempt(() =>\n controller.mixOnPad(\n [\n { color, parts: parts[0] },\n { color: state.secondaryColor, parts: parts[1] },\n ],\n { setColor: true }\n )\n )\n }\n >\n Mix\n </button>\n </div>\n <div className=\"flex flex-wrap items-center gap-1\">\n <input value={padName} placeholder=\"Pad name\" aria-label=\"Pad name\" onChange={(e) => setPadName(e.target.value)} className=\"w-24 rounded bg-slate-800 px-1.5 py-0.5\" />\n <button type=\"button\" className={button} onClick={() => attempt(() => (controller.saveMixingPad(padName || undefined), setPadName('')))}>\n Keep pad\n </button>\n </div>\n {state.savedMixingPads.length > 0 && (\n <ul className=\"flex flex-col gap-0.5\" aria-label=\"Kept pads\">\n {state.savedMixingPads.map((p) => (\n <li key={p.id} className=\"flex items-center gap-1\">\n <button type=\"button\" className={`${button} flex-1 text-left`} onClick={() => attempt(() => controller.loadMixingPad(p.id))}>\n {p.name}\n </button>\n <button type=\"button\" className={button} aria-label={`Remove ${p.name}`} onClick={() => attempt(() => controller.removeMixingPad(p.id))}>\n ×\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n )}\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport { BLEND_MENU_GROUPS, type BlendMode, type PaintEditorController, type PaintLayerInfo } from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, button, chip, panel, useAttempt } from './shared';\n\nexport interface PaintLayersPanelProps {\n controller: PaintEditorController;\n className?: string;\n}\n\n/** Siblings of a layer, bottom first, and its index among them. */\nfunction siblingIndex(layers: PaintLayerInfo[], l: PaintLayerInfo): { index: number; count: number } {\n const sibs = layers.filter((x) => x.parentId === l.parentId).reverse();\n return { index: sibs.findIndex((x) => x.id === l.id), count: sibs.length };\n}\n\n/**\n * The layer stack, top first: visibility, names (double-click to rename), the active layer's\n * opacity, blend mode and locks, and new layer / group, duplicate, move up / down, merge down and\n * delete. Every change is one undo step.\n */\nexport const PaintLayersPanel: React.FC<PaintLayersPanelProps> = ({ controller, className }) => {\n usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const [renaming, setRenaming] = useState<string | null>(null);\n const layers = controller.listLayers();\n const active = layers.find((l) => l.active) ?? null;\n const move = (delta: number) => {\n if (!active) return;\n const { index, count } = siblingIndex(layers, active);\n const to = Math.min(count - 1, Math.max(0, index + delta));\n if (to !== index) attempt(() => controller.moveLayer(active.id, to));\n };\n\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"paint-layers-panel\">\n <div className=\"flex flex-wrap gap-1\">\n <button type=\"button\" className={button} onClick={() => attempt(() => controller.addLayer())}>\n New layer\n </button>\n <button type=\"button\" className={button} onClick={() => attempt(() => controller.addLayer({ type: 'group' }))}>\n New group\n </button>\n <button type=\"button\" className={button} disabled={!active} onClick={() => active && attempt(() => controller.duplicateLayer(active.id))}>\n Duplicate\n </button>\n <button type=\"button\" className={button} disabled={!active} aria-label=\"Move layer up\" onClick={() => move(1)}>\n ↑\n </button>\n <button type=\"button\" className={button} disabled={!active} aria-label=\"Move layer down\" onClick={() => move(-1)}>\n ↓\n </button>\n <button type=\"button\" className={button} disabled={!active} onClick={() => active && attempt(() => controller.mergeDown(active.id))}>\n Merge down\n </button>\n <button type=\"button\" className={button} disabled={!active || layers.length < 2} onClick={() => active && attempt(() => controller.removeLayer(active.id))}>\n Delete\n </button>\n </div>\n <ul role=\"tree\" aria-label=\"Layers\" className=\"flex flex-col gap-0.5\">\n {layers.map((l) => (\n <li\n key={l.id}\n role=\"treeitem\"\n aria-selected={l.active}\n className={`flex items-center gap-1.5 rounded px-1.5 py-1 cursor-pointer ${l.active ? 'bg-indigo-600/30 ring-1 ring-indigo-500' : 'hover:bg-slate-800'}`}\n style={{ paddingLeft: 6 + l.depth * 12 }}\n onClick={() => controller.setActiveLayer(l.id)}\n >\n <button\n type=\"button\"\n aria-label={l.visible ? `Hide ${l.name}` : `Show ${l.name}`}\n className={`w-5 text-[11px] ${l.visible ? 'text-slate-200' : 'text-slate-600'}`}\n onClick={(e) => {\n e.stopPropagation();\n attempt(() => controller.updateLayer(l.id, { visible: !l.visible }));\n }}\n >\n {l.visible ? '●' : '○'}\n </button>\n {renaming === l.id ? (\n <input\n autoFocus\n aria-label=\"Layer name\"\n defaultValue={l.name}\n className=\"flex-1 rounded bg-slate-800 px-1\"\n onClick={(e) => e.stopPropagation()}\n onBlur={(e) => {\n setRenaming(null);\n if (e.target.value.trim() && e.target.value !== l.name) attempt(() => controller.updateLayer(l.id, { name: e.target.value }));\n }}\n onKeyDown={(e) => {\n if (e.key === 'Enter') (e.target as HTMLInputElement).blur();\n if (e.key === 'Escape') setRenaming(null);\n }}\n />\n ) : (\n <span className=\"flex-1 truncate\" onDoubleClick={() => setRenaming(l.id)}>\n {l.type === 'group' ? '▸ ' : ''}\n {l.name}\n </span>\n )}\n {l.locks.pixels || l.locks.all ? <span title=\"Locked\">🔒</span> : null}\n </li>\n ))}\n </ul>\n {active && (\n <div className=\"flex flex-col gap-1.5\">\n <label className=\"flex items-center gap-2\">\n <span className=\"w-14 text-slate-400\">Opacity</span>\n <input\n type=\"range\"\n aria-label=\"Layer opacity\"\n min={0}\n max={1}\n step={0.01}\n value={active.opacity}\n onChange={(e) => attempt(() => controller.updateLayer(active.id, { opacity: Number(e.target.value) }))}\n className=\"flex-1 accent-indigo-500\"\n />\n </label>\n <label className=\"flex items-center gap-2\">\n <span className=\"w-14 text-slate-400\">Blend</span>\n <select aria-label=\"Layer blend\" value={active.blend} onChange={(e) => attempt(() => controller.updateLayer(active.id, { blend: e.target.value as BlendMode }))} className=\"flex-1 rounded bg-slate-800 px-1 py-0.5\">\n {active.type === 'group' && <option value=\"pass-through\">Pass through</option>}\n {BLEND_MENU_GROUPS.map((g) => (\n <optgroup key={g.label} label={g.label}>\n {g.modes.map((m) => (\n <option key={m.id} value={m.id} title={m.description}>\n {m.label}\n </option>\n ))}\n </optgroup>\n ))}\n </select>\n </label>\n <div className=\"flex gap-1\">\n {(['pixels', 'transparency'] as const).map((k) => (\n <button key={k} type=\"button\" aria-pressed={Boolean(active.locks[k])} className={chip(Boolean(active.locks[k]))} onClick={() => attempt(() => controller.updateLayer(active.id, { locks: { [k]: !active.locks[k] } }))}>\n {k === 'pixels' ? 'Lock pixels' : 'Lock transparency'}\n </button>\n ))}\n <button type=\"button\" aria-pressed={active.clipped} className={chip(active.clipped)} onClick={() => attempt(() => controller.updateLayer(active.id, { clipped: !active.clipped }))}>\n Clip\n </button>\n </div>\n </div>\n )}\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React from 'react';\nimport { WET_FLOW_KINDS, WET_GPU_OPTIONS, WET_PARAM_SLIDERS, WET_SPEED_SLIDER, WET_TILT_SLIDERS, readPath, wetEngineSummary, type PaintEditorController, type WetFlowKind, type WetGpuMode } from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, PaintSlider, button, chip, panel, useAttempt } from './shared';\n\nexport interface WetPanelProps {\n controller: PaintEditorController;\n className?: string;\n}\n\nconst FLOW_LABELS: Record<WetFlowKind, string> = { none: 'None', linear: 'One way', swirl: 'Swirl', radial: 'Outwards', turbulent: 'Eddies' };\n\n/**\n * Wet media: whether paint is wet, Dry now, Pause / Resume, the water overlay and speed; Wet paper\n * on the active layer; canvas tilt; the active layer's wet settings (viscosity, evaporation, edge\n * darkening, granulation, blooms, bleed, pigment weight, lifting, staining) and flow map; and the\n * kernel in use, with a note when it runs slower than it could (no cross-origin isolation); and\n * Engine B, the WebGPU accelerator for large washes, with a switch to force the CPU.\n */\nexport const WetPanel: React.FC<WetPanelProps> = ({ controller, className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const wet = state.wet;\n const layerId = state.document.activeLayerId;\n const info = layerId ? controller.wetLayerInfo(layerId) : null;\n const backend = controller.wetState();\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"wet-panel\">\n <div className=\"flex items-center justify-between\">\n <span className={wet.wet ? 'text-sky-300' : 'text-slate-400'} data-testid=\"wet-status\">\n {wet.wet ? (wet.paused ? 'Wet (paused)' : 'Wet') : 'Dry'}\n </span>\n <span className=\"text-[10px] text-slate-500\">step {wet.clock}</span>\n </div>\n <div className=\"flex flex-wrap gap-1\">\n <button type=\"button\" className={button} disabled={!wet.layerIds.length} onClick={() => attempt(async () => (await controller.wetIdle(), controller.dryPaint()))}>\n Dry now\n </button>\n <button type=\"button\" className={chip(wet.paused)} aria-pressed={wet.paused} onClick={() => controller.setWetPaused(!wet.paused)}>\n {wet.paused ? 'Resume' : 'Pause'}\n </button>\n <button type=\"button\" className={chip(wet.overlay)} aria-pressed={wet.overlay} onClick={() => controller.setWaterOverlay(!wet.overlay)}>\n Water\n </button>\n <button type=\"button\" className={chip(wet.instantDry)} aria-pressed={wet.instantDry} title=\"Each wet stroke dries as soon as it ends\" onClick={() => controller.setInstantDry(!wet.instantDry)}>\n Instant dry\n </button>\n <button type=\"button\" className={button} disabled={!layerId} onClick={() => attempt(async () => (await controller.wetIdle(), controller.wetPaper({})))}>\n Wet paper\n </button>\n </div>\n <PaintSlider control={WET_SPEED_SLIDER} value={wet.speed} onChange={(v) => controller.setWetSpeed(v)} />\n {WET_TILT_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(wet.tilt, c.path)} onCommit={(v) => attempt(async () => (await controller.wetIdle(), controller.setCanvasTilt({ [c.path]: v })))} />\n ))}\n {info && (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"wet-layer\">\n <span className=\"font-medium text-slate-300\">This layer</span>\n {WET_PARAM_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(info.params, c.path)} onCommit={(v) => attempt(async () => (await controller.wetIdle(), controller.setWetParams(layerId!, { [c.path]: v })))} />\n ))}\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Flow map</span>\n <select aria-label=\"Flow map\" value={info.flow.kind} onChange={(e) => attempt(async () => (await controller.wetIdle(), controller.setFlowMap(layerId!, { kind: e.target.value as WetFlowKind })))} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {WET_FLOW_KINDS.map((k) => (\n <option key={k} value={k}>\n {FLOW_LABELS[k]}\n </option>\n ))}\n </select>\n </label>\n {info.flow.kind !== 'none' && (\n <PaintSlider\n control={{ path: 'strength', label: 'Flow strength', min: 0, max: 1, step: 0.01 }}\n value={info.flow.strength}\n onCommit={(v) => attempt(async () => (await controller.wetIdle(), controller.setFlowMap(layerId!, { strength: v })))}\n />\n )}\n </div>\n )}\n {backend.message && (\n <p className=\"text-[10px] text-amber-300\" data-testid=\"wet-message\">\n {backend.message}\n </p>\n )}\n {backend.backend && (\n <p className=\"text-[10px] text-slate-500\">\n {backend.backend.kind === 'wasm-threads' ? `WebAssembly, ${backend.backend.threads} threads` : backend.backend.kind === 'wasm' ? 'WebAssembly, one thread' : 'JavaScript'}\n </p>\n )}\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Engine</span>\n <select aria-label=\"Wet engine\" value={wet.gpu} onChange={(e) => attempt(() => controller.setWetEngine({ gpu: e.target.value as WetGpuMode }))} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {WET_GPU_OPTIONS.map((o) => (\n <option key={o.value} value={o.value}>\n {o.label}\n </option>\n ))}\n </select>\n </label>\n <p className={`text-[10px] ${backend.engine.state === 'active' ? 'text-emerald-300' : 'text-slate-500'}`} data-testid=\"wet-engine\">\n {wetEngineSummary(backend.engine)}\n </p>\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport { STAMP_KINDS, STAMP_LABELS, STICKER_SLIDERS, readPath, type PaintEditorController, type StampKind } from '@pixerate/editor/paint-editor';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { CommitColorInput, ErrorLine, PaintSlider, button, panel, useAttempt } from './shared';\n\nexport interface StickerPanelProps {\n controller: PaintEditorController;\n className?: string;\n}\n\n/**\n * The active layer's stickers: pick one to change its stamp, size, rotation, opacity and colour,\n * bring it to the front or back, or delete it (each change one undo step). Shows nothing for a\n * layer without stickers.\n */\nexport const StickerPanel: React.FC<StickerPanelProps> = ({ controller, className }) => {\n const state = usePaintEditorState(controller);\n const [error, attempt] = useAttempt();\n const [picked, setPicked] = useState<string | null>(null);\n const layerId = state.document.activeLayerId;\n const stickers = layerId ? (state.document.stickers?.[layerId] ?? []) : [];\n if (!stickers.length) return null;\n const sel = stickers.find((s) => s.id === picked) ?? null;\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"sticker-panel\">\n <span className=\"font-medium text-slate-300\">Stickers ({stickers.length})</span>\n <div className=\"flex max-h-24 flex-wrap gap-1 overflow-y-auto\" role=\"listbox\" aria-label=\"Stickers\">\n {stickers.map((s) => (\n <button key={s.id} type=\"button\" role=\"option\" aria-selected={s.id === picked} title={`${STAMP_LABELS[s.stamp]} ${s.id}`} className={`h-5 w-5 rounded ring-1 ${s.id === picked ? 'ring-indigo-400' : 'ring-slate-700'}`} style={{ background: s.color }} onClick={() => setPicked(s.id)} />\n ))}\n </div>\n {sel && (\n <div className=\"flex flex-col gap-1.5\" data-testid=\"sticker-edit\">\n <label className=\"flex items-center justify-between gap-2\">\n <span className=\"text-slate-400\">Stamp</span>\n <select aria-label=\"Sticker stamp\" value={sel.stamp} onChange={(e) => attempt(() => controller.updateSticker(layerId!, sel.id, { stamp: e.target.value as StampKind }))} className=\"rounded bg-slate-800 px-1 py-0.5\">\n {STAMP_KINDS.map((k) => (\n <option key={k} value={k}>\n {STAMP_LABELS[k]}\n </option>\n ))}\n </select>\n </label>\n {STICKER_SLIDERS.map((c) => (\n <PaintSlider key={c.path} control={c} value={readPath(sel, c.path)} onCommit={(v) => attempt(() => controller.updateSticker(layerId!, sel.id, { [c.path]: v }))} />\n ))}\n <label className=\"flex items-center justify-between\">\n <span className=\"text-slate-400\">Colour</span>\n <CommitColorInput label=\"Sticker colour\" value={sel.color} onCommit={(v) => attempt(() => controller.updateSticker(layerId!, sel.id, { color: v }))} className=\"h-6 w-10 rounded bg-transparent\" />\n </label>\n <div className=\"flex flex-wrap gap-1\">\n <button type=\"button\" className={button} onClick={() => attempt(() => controller.arrangeStickers(layerId!, [sel.id], 'front'))}>\n To front\n </button>\n <button type=\"button\" className={button} onClick={() => attempt(() => controller.arrangeStickers(layerId!, [sel.id], 'back'))}>\n To back\n </button>\n <button type=\"button\" className={button} onClick={() => attempt(() => (controller.removeStickers(layerId!, [sel.id]), setPicked(null)))}>\n Delete\n </button>\n </div>\n </div>\n )}\n <ErrorLine error={error} />\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport type { PaintEditorController, PaintPresence, PaintTool } from '@pixerate/editor/paint-editor';\nimport { BrushPanel } from './BrushPanel';\nimport { ColorPanel } from './ColorPanel';\nimport { PaintCanvas } from './PaintCanvas';\nimport { PaintLayersPanel } from './PaintLayersPanel';\nimport { PaintToolbar } from './PaintToolbar';\nimport { PaperPanel } from './PaperPanel';\nimport { WetPanel } from './WetPanel';\nimport { StickerPanel } from './StickerPanel';\nimport { PaintEffectsPanel, usePaintEffectsProvider } from './PaintEffectsPanel';\nimport { chip } from './shared';\n\nexport interface PaintEditorProps {\n controller: PaintEditorController;\n /** Base name of saved and exported files (default `painting`). */\n fileName?: string;\n /** Height of the editor (default 720 px). */\n height?: number | string;\n /** Agent cursors to draw over the canvas (see `usePaintDirector`). */\n presence?: PaintPresence;\n className?: string;\n}\n\ntype SideTab = 'color' | 'wet' | 'paper' | 'layers' | 'effects';\n\n/**\n * The paint editor: toolbar, brush library on the left, the canvas, and colour (wheel,\n * harmonies, swatches, mixing pad), wet media, paper and layers on the right, and provider effects\n * when an effects provider is registered.\n */\nexport const PaintEditor: React.FC<PaintEditorProps> = ({ controller, fileName, height = 720, presence, className }) => {\n const [tool, setTool] = useState<PaintTool>('brush');\n const [tab, setTab] = useState<SideTab>('color');\n const [error, setError] = useState<string | null>(null);\n const effects = usePaintEffectsProvider(controller);\n const tabs: SideTab[] = effects ? ['color', 'wet', 'paper', 'layers', 'effects'] : ['color', 'wet', 'paper', 'layers'];\n return (\n <div className={`flex flex-col gap-2 rounded-xl border border-slate-800 bg-slate-900 p-2 ${className ?? ''}`} style={{ height }} data-testid=\"paint-editor\">\n <PaintToolbar controller={controller} tool={tool} onToolChange={setTool} fileName={fileName} />\n <div className=\"flex min-h-0 flex-1 gap-2\">\n <BrushPanel controller={controller} className=\"w-60 shrink-0 overflow-y-auto pr-1\" />\n <div className=\"flex min-w-0 flex-1 flex-col\">\n <PaintCanvas controller={controller} tool={tool} onError={setError} presence={presence} className=\"flex-1 rounded-lg\" />\n {error && (\n <p role=\"alert\" className=\"mt-1 text-[11px] text-rose-400\">\n {error}\n </p>\n )}\n </div>\n <div className=\"flex w-64 shrink-0 flex-col gap-2 overflow-y-auto pr-1\">\n <div className=\"flex gap-1\" role=\"tablist\" aria-label=\"Paint panels\">\n {tabs.map((t) => (\n <button key={t} type=\"button\" role=\"tab\" aria-selected={tab === t} className={chip(tab === t)} onClick={() => setTab(t)}>\n {t === 'color' ? 'Colour' : t === 'wet' ? 'Wet' : t === 'paper' ? 'Paper' : t === 'layers' ? 'Layers' : 'Effects'}\n </button>\n ))}\n </div>\n {tab === 'color' && <ColorPanel controller={controller} />}\n {tab === 'wet' && <WetPanel controller={controller} />}\n {tab === 'paper' && <PaperPanel controller={controller} />}\n {tab === 'layers' && <PaintLayersPanel controller={controller} />}\n {tab === 'layers' && <StickerPanel controller={controller} />}\n {tab === 'effects' && effects && <PaintEffectsPanel controller={controller} />}\n </div>\n </div>\n </div>\n );\n};\n","import React, { useEffect, useRef, useState } from 'react';\nimport { createPaintEffectsToolProvider, PAPER_EFFECT_BLENDS, type PaintEditorController, type PaintEffectsToolProviderOptions, type PaperEffectBlend } from '@pixerate/editor/paint-editor';\nimport type { EffectProvider } from '@pixerate/editor/effects';\nimport type { ToolRegistry } from '@pixerate/editor/tools';\nimport { EffectParameters, EffectsBrowser, useEffectDescription } from '../effects';\nimport { usePaintEditorState } from './usePaintEditor';\nimport { ErrorLine, button, panel, useAttempt } from './shared';\n\nexport interface PaintEffectsPanelProps {\n controller: PaintEditorController;\n className?: string;\n}\n\n/** The controller's effects provider, following `setEffectsProvider`. */\nexport function usePaintEffectsProvider(controller: PaintEditorController): EffectProvider | null {\n const [provider, setProvider] = useState(controller.effectsProvider);\n useEffect(() => {\n setProvider(controller.effectsProvider);\n return controller.effects.subscribe(setProvider);\n }, [controller]);\n return provider;\n}\n\n/** Registers the paint effect tools (`set_paper_effect`, `add_effect_layer`, `apply_effect`, …) while mounted. */\nexport function usePaintEffectsTools(registry: ToolRegistry | null | undefined, controller: PaintEditorController, options: PaintEffectsToolProviderOptions = {}): void {\n const { id, namespace, readOnly } = options;\n useEffect(() => {\n if (!registry) return;\n return registry.register(createPaintEffectsToolProvider(controller, { id, namespace, readOnly }));\n }, [registry, controller, id, namespace, readOnly]);\n}\n\n/** One effect's controls from the provider; the first change of a drag records the undo step, later ones join it. */\nfunction Controls({ provider, effect, name, values, apply }: { provider: EffectProvider | null; effect: string; name?: string; values: Readonly<Record<string, unknown>>; apply: (values: Record<string, unknown>, commit: boolean) => void }) {\n const { description, error } = useEffectDescription(provider, effect);\n const drags = useRef(new Set<string>());\n if (!provider) return <p className=\"text-[11px] text-slate-400\">No effects provider: \"{name ?? effect}\" is kept as it was drawn.</p>;\n if (error) return <p className=\"text-[11px] text-amber-400\">{error}</p>;\n if (!description) return <p className=\"text-[11px] text-slate-400\">Loading…</p>;\n const commit = (gesture: string | null) => {\n if (!gesture || drags.current.has(gesture)) return !gesture;\n drags.current.add(gesture);\n return true;\n };\n return (\n <EffectParameters\n description={description}\n values={values}\n onChange={(k, v, gesture) => apply({ [k]: v }, commit(gesture))}\n onReset={(k) => apply({ [k]: null }, true)}\n onPreset={(v) => apply({ ...v }, true)}\n />\n );\n}\n\ntype Browse = null | 'paper' | 'layer' | 'fill' | 'light';\n\nconst BROWSERS: Record<Exclude<Browse, null>, { uses: ('generator' | 'overlay' | 'title' | 'filter')[]; title: string }> = {\n paper: { uses: ['generator'], title: 'Effect paper' },\n layer: { uses: ['generator', 'overlay', 'title'], title: 'Effect layer' },\n fill: { uses: ['generator', 'overlay', 'title'], title: 'Fill the layer' },\n light: { uses: ['filter'], title: 'Light on the paint' },\n};\n\n/**\n * Provider effects in the paint editor: effect paper (a generator over the sheet, multiplied so\n * the grain shows), effect layers, effect fills and light baked onto the active layer's dried\n * paint; plus the controls of the effect paper and of an active effect layer. Each change is one\n * undo step (a slider drag is one). Without a provider it says why nothing can be added.\n */\nexport const PaintEffectsPanel: React.FC<PaintEffectsPanelProps> = ({ controller, className }) => {\n const state = usePaintEditorState(controller);\n const provider = usePaintEffectsProvider(controller);\n const [error, attempt] = useAttempt();\n const [browse, setBrowse] = useState<Browse>(null);\n const [busy, setBusy] = useState(false);\n const paper = controller.getPaperEffect();\n const activeId = state.document.activeLayerId;\n const layerEffect = activeId ? controller.getEffectLayer(activeId) : undefined;\n const active = activeId ? controller.getLayer(activeId) : undefined;\n const run = (work: () => Promise<unknown>) =>\n attempt(() => {\n setBusy(true);\n return work().finally(() => setBusy(false));\n });\n const pick = (id: string) => {\n const kind = browse;\n setBrowse(null);\n if (kind === 'paper') run(() => controller.setPaperEffect(id));\n else if (kind === 'layer') run(() => controller.addEffectLayer(id));\n else if (kind === 'fill') run(() => controller.fillLayerWithEffect(id));\n else if (kind === 'light' && activeId) run(() => controller.applyLightEffect(activeId, id));\n };\n const toggle = (b: Exclude<Browse, null>) => setBrowse(browse === b ? null : b);\n const pixel = active?.type === 'pixel';\n return (\n <div className={`${panel} ${className ?? ''}`} data-testid=\"paint-effects-panel\" aria-busy={busy}>\n <div className=\"flex flex-wrap items-center gap-1\">\n <span className=\"flex-1 font-medium text-slate-300\">Effects</span>\n <button type=\"button\" className={button} disabled={!provider} aria-pressed={browse === 'paper'} onClick={() => toggle('paper')}>\n Paper…\n </button>\n <button type=\"button\" className={button} disabled={!provider} aria-pressed={browse === 'layer'} onClick={() => toggle('layer')}>\n Layer…\n </button>\n <button type=\"button\" className={button} disabled={!provider || !pixel} aria-pressed={browse === 'fill'} onClick={() => toggle('fill')}>\n Fill…\n </button>\n <button type=\"button\" className={button} disabled={!provider || !pixel} aria-pressed={browse === 'light'} onClick={() => toggle('light')} title=\"Bake a light, glow or grade into the active layer's dried paint\">\n Light…\n </button>\n </div>\n {!provider && <p className=\"text-[11px] text-slate-400\">No effects provider is registered. Effects in the painting are kept.</p>}\n {browse && <EffectsBrowser provider={provider} uses={BROWSERS[browse].uses} title={BROWSERS[browse].title} onPick={(e) => pick(e.id)} />}\n {paper && (\n <div className=\"flex flex-col gap-1 rounded border border-slate-700 p-1\" data-effect-part=\"paper\">\n <div className=\"flex items-center gap-1\">\n <span className=\"flex-1 truncate\">Paper: {paper.name ?? paper.effect}</span>\n <button type=\"button\" className={button} aria-label=\"Remove the effect paper\" onClick={() => run(() => controller.setPaperEffect(null))}>\n ✕\n </button>\n </div>\n <label className=\"flex items-center gap-1\">\n <span className=\"w-14 text-[11px] text-slate-400\">Opacity</span>\n <input\n type=\"range\"\n min={0}\n max={1}\n step={0.01}\n className=\"flex-1\"\n aria-label=\"Effect paper opacity\"\n defaultValue={paper.opacity}\n key={`o${paper.opacity}`}\n onPointerUp={(e) => {\n const opacity = Number(e.currentTarget.value);\n run(() => controller.updatePaperEffect({ opacity }));\n }}\n onKeyUp={(e) => {\n const opacity = Number(e.currentTarget.value);\n run(() => controller.updatePaperEffect({ opacity }));\n }}\n />\n </label>\n <label className=\"flex items-center gap-1\">\n <span className=\"w-14 text-[11px] text-slate-400\">Blend</span>\n <select className=\"flex-1 rounded bg-slate-800 px-1 py-0.5 text-[11px]\" aria-label=\"Effect paper blend\" value={paper.blend} onChange={(e) => {\n const blend = e.currentTarget.value as PaperEffectBlend;\n run(() => controller.updatePaperEffect({ blend }));\n }}>\n {PAPER_EFFECT_BLENDS.map((b) => (\n <option key={b} value={b}>\n {b}\n </option>\n ))}\n </select>\n </label>\n <Controls provider={provider} effect={paper.effect} name={paper.name} values={paper.values} apply={(values, commit) => run(() => controller.updatePaperEffect({ values: values as never }, commit))} />\n </div>\n )}\n {layerEffect && activeId && (\n <div className=\"flex flex-col gap-1 rounded border border-slate-700 p-1\" data-effect-part=\"layer\">\n <div className=\"flex items-center gap-1\">\n <span className=\"flex-1 truncate\">Layer: {layerEffect.name ?? layerEffect.effect}</span>\n <button type=\"button\" className={button} title=\"Keep the pixels as a plain layer\" onClick={() => attempt(() => controller.rasterizeEffectLayer(activeId))}>\n Rasterize\n </button>\n </div>\n <Controls provider={provider} effect={layerEffect.effect} name={layerEffect.name} values={layerEffect.values} apply={(values, commit) => run(() => controller.updateEffectLayer(activeId, { values: values as never }, commit))} />\n </div>\n )}\n <ErrorLine error={error} />\n </div>\n );\n};\n","import { useEffect, useState } from 'react';\nimport type { EffectDescription, EffectProvider } from '@pixerate/editor/effects';\n\n/** Anything that takes an effects provider: every editor controller with effects support. */\nexport interface EffectsHost {\n useEffects(provider: EffectProvider): () => void;\n}\n\n/**\n * Registers `provider` with an editor while mounted (or while it is the one passed), and removes it\n * again on unmount. Pass `null` or `undefined` for no provider: the editor then behaves as without\n * effects support.\n */\nexport function useEffects(host: EffectsHost | null | undefined, provider: EffectProvider | null | undefined): void {\n useEffect(() => {\n if (!host || !provider) return;\n return host.useEffects(provider);\n }, [host, provider]);\n}\n\n/** An effect's description from the provider, loaded when `effect` changes (`null` while loading or on error). */\nexport function useEffectDescription(provider: EffectProvider | null | undefined, effect: string | null | undefined): { description: EffectDescription | null; error: string | null } {\n const [state, setState] = useState<{ key: string; description: EffectDescription | null; error: string | null }>({ key: '', description: null, error: null });\n const key = provider && effect ? `${provider.id}:${effect}` : '';\n useEffect(() => {\n if (!provider || !effect) return;\n let live = true;\n Promise.resolve()\n .then(() => provider.describe(effect))\n .then(\n (description) => live && setState({ key, description, error: null }),\n (e: unknown) => live && setState({ key, description: null, error: e instanceof Error ? e.message : String(e) }),\n );\n return () => {\n live = false;\n };\n }, [provider, effect, key]);\n return state.key === key ? { description: state.description, error: state.error } : { description: null, error: null };\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { renderEffectThumbnail, type EffectProvider, type EffectSummary } from '@pixerate/editor/effects';\n\nexport interface EffectThumbnailProps {\n provider: EffectProvider;\n effect: EffectSummary;\n /** Pixel size of the preview (default 96 × 54). */\n width?: number;\n height?: number;\n className?: string;\n}\n\n/**\n * A preview of an effect drawn by the provider's own renderer (filters on a sample picture,\n * transitions half way, generators mid-way through). Motion effects and failures show a label.\n */\nexport function EffectThumbnail({ provider, effect, width = 96, height = 54, className = '' }: EffectThumbnailProps) {\n const ref = useRef<HTMLCanvasElement>(null);\n const [failed, setFailed] = useState(effect.kind === 'motion');\n useEffect(() => {\n if (effect.kind === 'motion') return;\n let live = true;\n renderEffectThumbnail(provider, effect, { width, height }).then(\n (pixels) => {\n const ctx = live ? ref.current?.getContext('2d') : null;\n if (!ctx || typeof ImageData === 'undefined') return;\n ctx.putImageData(new ImageData(new Uint8ClampedArray(pixels.data), pixels.width, pixels.height), 0, 0);\n },\n () => live && setFailed(true),\n );\n return () => {\n live = false;\n };\n }, [provider, effect, width, height]);\n return (\n <div\n className={`relative overflow-hidden rounded border border-border bg-[repeating-conic-gradient(#8884_0_25%,transparent_0_50%)] bg-[length:12px_12px] ${className}`}\n style={{ aspectRatio: `${width} / ${height}` }}\n data-effect-thumbnail={effect.id}\n >\n {failed ? (\n <span className=\"absolute inset-0 flex items-center justify-center text-[10px] text-muted-foreground\">{effect.kind === 'motion' ? 'Motion' : 'No preview'}</span>\n ) : (\n <canvas ref={ref} width={width} height={height} className=\"h-full w-full\" aria-hidden=\"true\" />\n )}\n </div>\n );\n}\n","import React, { useEffect, useMemo, useState } from 'react';\nimport { EFFECT_USE_LABELS, type EffectKind, type EffectProvider, type EffectSummary, type EffectUse } from '@pixerate/editor/effects';\nimport { EffectThumbnail } from './EffectThumbnail';\n\nexport interface EffectsBrowserProps {\n /** The editor's provider; without one the browser says effects are unavailable. */\n provider: EffectProvider | null | undefined;\n /** Only effects with one of these uses (default: all but motion). */\n uses?: readonly EffectUse[];\n /** Only effects of these kinds (default: any). */\n kinds?: readonly EffectKind[];\n /** Called with the effect the user picks. */\n onPick: (effect: EffectSummary) => void;\n /** Draw previews with the provider's renderer (default true). */\n thumbnails?: boolean;\n /** Heading (default \"Effects\"). */\n title?: React.ReactNode;\n className?: string;\n}\n\n/**\n * Browses a provider's effects: a search box, a category filter (and a use filter when more than\n * one use is allowed), and a grid of effects with previews. Picking one calls `onPick`.\n */\nexport function EffectsBrowser({ provider, uses, kinds, onPick, thumbnails = true, title = 'Effects', className = '' }: EffectsBrowserProps) {\n const [all, setAll] = useState<readonly EffectSummary[]>([]);\n const [query, setQuery] = useState('');\n const [category, setCategory] = useState('');\n const [use, setUse] = useState<EffectUse | ''>('');\n const [error, setError] = useState<string | null>(null);\n useEffect(() => {\n if (!provider) return setAll([]);\n let live = true;\n Promise.resolve()\n .then(() => provider.list())\n .then(\n (list) => live && (setAll(list), setError(null)),\n (e: unknown) => live && setError(e instanceof Error ? e.message : String(e)),\n );\n return () => {\n live = false;\n };\n }, [provider]);\n const [found, setFound] = useState<readonly EffectSummary[]>([]);\n useEffect(() => {\n if (!provider) return setFound([]);\n let live = true;\n Promise.resolve()\n .then(() => provider.search(query, { ...(category ? { category } : {}), ...(use ? { use } : {}) }))\n .then((list) => live && setFound(list), () => live && setFound([]));\n return () => {\n live = false;\n };\n }, [provider, query, category, use]);\n const allowed = (e: EffectSummary) => (!kinds || kinds.includes(e.kind)) && (uses ? e.kind !== 'motion' || uses.includes('motion') : e.kind !== 'motion') && (!uses || e.uses.some((u) => uses.includes(u)));\n const categories = useMemo(() => [...new Set(all.filter(allowed).map((e) => e.category))], [all, uses, kinds]);\n const shown = found.filter(allowed);\n if (!provider)\n return (\n <div className={`rounded-md border border-dashed border-border p-3 text-xs text-muted-foreground ${className}`} data-effects-browser=\"\" data-effects-unavailable=\"\">\n No effects provider is registered, so effects cannot be added. Effects already in the document are kept.\n </div>\n );\n return (\n <section className={`flex flex-col gap-2 ${className}`} data-effects-browser=\"\" aria-label=\"Effects browser\">\n {title && <h3 className=\"text-xs font-semibold\">{title}</h3>}\n <div className=\"flex flex-wrap gap-1\">\n <input\n type=\"search\"\n className=\"min-w-0 flex-1 rounded border border-border bg-transparent px-1.5 py-0.5 text-xs\"\n placeholder=\"Search effects\"\n aria-label=\"Search effects\"\n value={query}\n onChange={(e) => setQuery(e.currentTarget.value)}\n />\n <select className=\"rounded border border-border bg-transparent px-1 py-0.5 text-xs\" aria-label=\"Category\" value={category} onChange={(e) => setCategory(e.currentTarget.value)}>\n <option value=\"\">All categories</option>\n {categories.map((c) => (\n <option key={c} value={c}>\n {c}\n </option>\n ))}\n </select>\n {uses && uses.length > 1 && (\n <select className=\"rounded border border-border bg-transparent px-1 py-0.5 text-xs\" aria-label=\"Use\" value={use} onChange={(e) => setUse(e.currentTarget.value as EffectUse | '')}>\n <option value=\"\">Any use</option>\n {uses.map((u) => (\n <option key={u} value={u}>\n {EFFECT_USE_LABELS[u]}\n </option>\n ))}\n </select>\n )}\n </div>\n {error && <p role=\"alert\" className=\"text-[11px] text-destructive\">{error}</p>}\n <ul className=\"grid max-h-96 grid-cols-[repeat(auto-fill,minmax(6.5rem,1fr))] gap-1.5 overflow-y-auto\" role=\"list\">\n {shown.map((e) => (\n <li key={e.id}>\n <button\n type=\"button\"\n className=\"flex w-full flex-col gap-1 rounded border border-transparent p-1 text-left hover:border-border focus-visible:border-border\"\n title={e.description ?? e.name}\n data-effect-id={e.id}\n onClick={() => onPick(e)}\n >\n {thumbnails && <EffectThumbnail provider={provider} effect={e} />}\n <span className=\"truncate text-[11px] font-medium\">{e.name}</span>\n <span className=\"truncate text-[10px] text-muted-foreground\">{e.uses.map((u) => EFFECT_USE_LABELS[u]).join(' · ')}</span>\n </button>\n </li>\n ))}\n </ul>\n {!shown.length && !error && <p className=\"text-[11px] text-muted-foreground\">No effects match.</p>}\n </section>\n );\n}\n","import React, { useId, useMemo } from 'react';\nimport { effectFieldValue, effectParameterFields, type EffectDescription } from '@pixerate/editor/effects';\nimport { parameterLabel, parameterValuesEqual, type ParameterValue } from '@pixerate/editor/parameters';\nimport { ParameterFieldControl } from '../parameters/fields';\n\nexport interface EffectParametersProps {\n /** The effect's description (`describe`). */\n description: EffectDescription;\n /** Its saved values; controls left out show their defaults. */\n values: Readonly<Record<string, unknown>>;\n /**\n * A control changed. While a slider or colour drag is under way `gesture` is a key unique to\n * that drag, so the host can fold its changes into one undo step; otherwise `null`.\n */\n onChange: (control: string, value: ParameterValue, gesture: string | null) => void;\n /** Resets one control to its default. */\n onReset?: (control: string) => void;\n /** Controls that are keyframed: shown read-only with a note (edit them as keyframes). */\n keyframed?: ReadonlySet<string>;\n /** Applies a preset's values. */\n onPreset?: (values: Readonly<Record<string, unknown>>) => void;\n disabled?: boolean;\n className?: string;\n}\n\n/**\n * The parameter panel of an effect, generated from its JSON Schema controls: sliders for bounded\n * numbers, switches, choices, colour pickers, vectors and text, with each control's description,\n * per-control reset and the effect's presets.\n */\nexport function EffectParameters({ description, values, onChange, onReset, keyframed, onPreset, disabled = false, className = '' }: EffectParametersProps) {\n const fields = useMemo(() => effectParameterFields(description), [description]);\n const idBase = useId();\n const gesture = React.useRef<string | null>(null);\n const count = React.useRef(0);\n return (\n <div className={`space-y-2 ${className}`} data-effect-parameters={description.id}>\n {onPreset && description.presets.length > 0 && (\n <select\n className=\"w-full rounded border border-border bg-transparent px-1 py-0.5 text-xs\"\n aria-label={`${description.name} presets`}\n value=\"\"\n disabled={disabled}\n onChange={(e) => {\n const preset = description.presets.find((p) => p.name === e.currentTarget.value);\n if (preset) onPreset({ ...description.defaults, ...preset.values });\n }}\n >\n <option value=\"\">Presets…</option>\n {description.presets.map((p) => (\n <option key={p.name} value={p.name}>\n {p.name}\n </option>\n ))}\n </select>\n )}\n {fields.map((field) => {\n const label = parameterLabel(field);\n const inputId = `${idBase}-${field.id}`;\n const keyed = keyframed?.has(field.id) ?? false;\n const value = effectFieldValue(field, values[field.id]);\n const changed = !keyed && !parameterValuesEqual(value, field.default);\n return (\n <div key={field.id} className=\"space-y-1\" data-effect-control={field.id}>\n <div className=\"flex items-center gap-1.5\">\n <label htmlFor={inputId} className=\"min-w-0 flex-1 truncate text-xs font-medium\" title={field.description}>\n {label}\n </label>\n {keyed && <span className=\"text-[10px] text-muted-foreground\">keyframed</span>}\n {onReset && changed && !disabled && (\n <button type=\"button\" className=\"rounded px-1 text-[11px] text-muted-foreground hover:text-foreground\" aria-label={`Reset ${label}`} onClick={() => onReset(field.id)}>\n ↺\n </button>\n )}\n </div>\n <ParameterFieldControl\n field={field}\n value={value}\n id={inputId}\n disabled={disabled || keyed}\n onChange={(v) => onChange(field.id, v, gesture.current)}\n onGestureStart={() => (gesture.current = `${idBase}:${field.id}:${++count.current}`)}\n onGestureEnd={() => (gesture.current = null)}\n />\n </div>\n );\n })}\n {!fields.length && <p className=\"text-[11px] text-muted-foreground\">No controls.</p>}\n </div>\n );\n}\n","import React, { useRef } from 'react';\nimport {\n choiceOptionLabel,\n formatParameterNumber,\n getChoiceOptions,\n isSliderField,\n normalizeHexColor,\n parameterLabel,\n parameterStep,\n parseParameterNumberInput,\n clampParameterNumber,\n vectorComponentField,\n vectorSize,\n type BooleanParameterField,\n type ChoiceParameterField,\n type ColorParameterField,\n type ImageParameterField,\n type NumberParameterField,\n type ParameterField,\n type ParameterKeyState,\n type ParameterValue,\n type TextParameterField,\n type VectorParameterField,\n} from '@pixerate/editor/parameters';\n\n/** Props every field control takes. Controls are controller-free: wire them to anything. */\nexport interface ParameterControlProps<F extends ParameterField, V extends ParameterValue> {\n field: F;\n value: V;\n onChange: (value: V) => void;\n /** A continuous edit (slider drag, colour pick) started: merge changes into one undo step. */\n onGestureStart?: () => void;\n onGestureEnd?: () => void;\n disabled?: boolean;\n /** DOM id of the main input (for a `<label htmlFor>`). */\n id?: string;\n}\n\nexport const parameterInputClass =\n 'h-7 w-full min-w-0 rounded-md border border-input bg-background px-2 text-xs text-foreground tabular-nums focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:cursor-not-allowed disabled:opacity-50';\nexport const parameterButtonClass =\n 'inline-flex h-7 items-center justify-center gap-1 rounded-md border border-input bg-background px-2 text-xs text-foreground hover:bg-muted focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:pointer-events-none disabled:opacity-50';\nconst rangeClass = 'h-4 w-full min-w-0 flex-1 cursor-pointer accent-primary disabled:cursor-not-allowed disabled:opacity-50';\n\ntype CommitInputProps = {\n value: string;\n /** Called with the text and the element (e.g. to show the stored value again after a refused edit). */\n onCommit: (value: string, input: HTMLInputElement | HTMLTextAreaElement) => void;\n multiline?: boolean;\n} & Omit<React.InputHTMLAttributes<HTMLInputElement> & React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'value' | 'onChange' | 'defaultValue'>;\n\n/** A text box that commits on blur or Enter (Mod+Enter when multiline) and resets on Escape. */\nexport function ParameterCommitInput({ value, onCommit, multiline, className, onKeyDown, ...rest }: CommitInputProps) {\n const commit = (el: HTMLInputElement | HTMLTextAreaElement) => {\n if (el.value !== value) onCommit(el.value, el);\n };\n const keyDown = (e: React.KeyboardEvent<HTMLInputElement & HTMLTextAreaElement>) => {\n onKeyDown?.(e);\n if (e.defaultPrevented) return;\n if (e.key === 'Enter' && (!multiline || e.metaKey || e.ctrlKey)) {\n e.preventDefault();\n commit(e.currentTarget);\n }\n if (e.key === 'Escape') e.currentTarget.value = value;\n };\n const props = {\n defaultValue: value,\n className: className ?? parameterInputClass,\n onBlur: (e: React.FocusEvent<HTMLInputElement & HTMLTextAreaElement>) => commit(e.currentTarget),\n onKeyDown: keyDown,\n ...rest,\n };\n // `key` remounts the box when the value changes from outside.\n return multiline ? (\n <textarea key={value} {...props} className={`${props.className} h-auto min-h-[3.5rem] py-1`} />\n ) : (\n <input key={value} type=\"text\" {...props} />\n );\n}\n\nconst plainNumber = (field: NumberParameterField, value: number) => formatParameterNumber({ ...field, unit: undefined }, value);\n\n/** A number box: type a value (units allowed), or step with the arrow keys (Shift ×10). */\nexport function ParameterNumberInput({\n field,\n value,\n onChange,\n disabled,\n id,\n 'aria-label': ariaLabel,\n}: ParameterControlProps<NumberParameterField, number> & { 'aria-label'?: string }) {\n return (\n <div className=\"relative min-w-0 flex-1\">\n <ParameterCommitInput\n id={id}\n inputMode=\"decimal\"\n aria-label={ariaLabel ?? parameterLabel(field)}\n value={plainNumber(field, value)}\n disabled={disabled || field.readOnly}\n className={`${parameterInputClass} ${field.unit ? 'pr-6' : ''}`}\n onCommit={(text, input) => {\n const n = parseParameterNumberInput(field, text);\n // Show the stored value again when the text was not a number or clamps to it.\n if (n === null || n === value) input.value = plainNumber(field, value);\n else onChange(n);\n }}\n onKeyDown={(e) => {\n if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') return;\n e.preventDefault();\n const step = parameterStep(field) * (e.shiftKey ? 10 : 1);\n onChange(clampParameterNumber(field, value + (e.key === 'ArrowUp' ? step : -step)));\n }}\n />\n {field.unit && (\n <span className=\"pointer-events-none absolute right-2 top-1/2 -translate-y-1/2 text-[10px] text-muted-foreground\">{field.unit}</span>\n )}\n </div>\n );\n}\n\n/** A slider plus number box for `number` / `int` fields (number box only for `control: 'input'` or unbounded fields). */\nexport function ParameterSlider(props: ParameterControlProps<NumberParameterField, number>) {\n const { field, value, onChange, onGestureStart, onGestureEnd, disabled } = props;\n const dragging = useRef(false);\n const end = () => {\n if (!dragging.current) return;\n dragging.current = false;\n onGestureEnd?.();\n };\n if (!isSliderField(field)) return <ParameterNumberInput {...props} />;\n const step = parameterStep(field);\n return (\n <div className=\"flex items-center gap-2\">\n <input\n type=\"range\"\n aria-label={parameterLabel(field)}\n aria-valuetext={formatParameterNumber(field, value)}\n min={field.min}\n max={field.max}\n step={step}\n value={value}\n disabled={disabled || field.readOnly}\n className={rangeClass}\n onPointerDown={() => {\n if (dragging.current) return;\n dragging.current = true;\n onGestureStart?.();\n }}\n onPointerUp={end}\n onPointerCancel={end}\n onBlur={end}\n onChange={(e) => onChange(clampParameterNumber(field, Number(e.target.value)))}\n />\n <div className=\"w-20 shrink-0\">\n <ParameterNumberInput {...props} id={props.id} aria-label={`${parameterLabel(field)} value`} />\n </div>\n </div>\n );\n}\n\n/** An on/off switch for `boolean` fields. */\nexport function ParameterToggle({ field, value, onChange, disabled, id }: ParameterControlProps<BooleanParameterField, boolean>) {\n return (\n <button\n type=\"button\"\n role=\"switch\"\n id={id}\n aria-checked={value}\n aria-label={parameterLabel(field)}\n disabled={disabled || field.readOnly}\n onClick={() => onChange(!value)}\n className={`relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border border-transparent transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:opacity-50 ${\n value ? 'bg-primary' : 'bg-muted'\n }`}\n >\n <span\n className={`pointer-events-none block h-4 w-4 rounded-full bg-background shadow transition-transform ${value ? 'translate-x-4' : 'translate-x-0.5'}`}\n />\n </button>\n );\n}\n\n/** A dropdown (or segmented buttons with `control: 'segmented'`) for `choice` fields. */\nexport function ParameterSelect({ field, value, onChange, disabled, id }: ParameterControlProps<ChoiceParameterField, string | number>) {\n const options = getChoiceOptions(field);\n const off = disabled || field.readOnly;\n if (field.control === 'segmented') {\n return (\n <div role=\"radiogroup\" aria-label={parameterLabel(field)} className=\"inline-flex flex-wrap rounded-md border border-input bg-muted p-0.5\">\n {options.map((o) => (\n <button\n key={String(o.value)}\n type=\"button\"\n role=\"radio\"\n aria-checked={o.value === value}\n title={o.description}\n disabled={off}\n onClick={() => onChange(o.value)}\n className={`rounded px-2 py-0.5 text-xs disabled:opacity-50 ${\n o.value === value ? 'bg-background text-foreground shadow-sm' : 'text-muted-foreground hover:text-foreground'\n }`}\n >\n {choiceOptionLabel(o)}\n </button>\n ))}\n </div>\n );\n }\n const index = options.findIndex((o) => o.value === value);\n return (\n <select\n id={id}\n aria-label={parameterLabel(field)}\n value={String(index)}\n disabled={off}\n onChange={(e) => {\n const option = options[Number(e.target.value)];\n if (option) onChange(option.value);\n }}\n className={parameterInputClass}\n >\n {options.map((o, i) => (\n <option key={String(o.value)} value={String(i)} title={o.description}>\n {choiceOptionLabel(o)}\n </option>\n ))}\n </select>\n );\n}\n\n/** A colour picker with a hex box, an alpha slider (with `alpha`) and swatches. */\nexport function ParameterColor({ field, value, onChange, onGestureStart, onGestureEnd, disabled, id }: ParameterControlProps<ColorParameterField, string>) {\n const picking = useRef(false);\n const alpha = !!field.alpha;\n const hex = normalizeHexColor(value, true) ?? '#000000ff';\n const rgb = hex.slice(0, 7);\n const a = hex.slice(7);\n const off = disabled || field.readOnly;\n const start = () => {\n if (picking.current) return;\n picking.current = true;\n onGestureStart?.();\n };\n const end = () => {\n if (!picking.current) return;\n picking.current = false;\n onGestureEnd?.();\n };\n return (\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-2\">\n <span className=\"relative h-7 w-9 shrink-0 overflow-hidden rounded-md border border-input bg-[repeating-conic-gradient(#d4d4d8_0_25%,#fff_0_50%)] bg-[length:8px_8px]\">\n <span className=\"absolute inset-0\" style={{ background: alpha ? hex : rgb }} />\n <input\n type=\"color\"\n aria-label={parameterLabel(field)}\n value={rgb}\n disabled={off}\n className=\"absolute inset-0 h-full w-full cursor-pointer opacity-0 disabled:cursor-not-allowed\"\n onChange={(e) => {\n start();\n onChange(alpha ? `${e.target.value}${a}` : e.target.value);\n }}\n onBlur={end}\n />\n </span>\n <ParameterCommitInput\n id={id}\n aria-label={`${parameterLabel(field)} hex`}\n value={alpha ? hex : rgb}\n disabled={off}\n spellCheck={false}\n className={`${parameterInputClass} font-mono`}\n onCommit={(text) => {\n const next = normalizeHexColor(text, alpha);\n if (next) onChange(next);\n }}\n />\n </div>\n {alpha && (\n <input\n type=\"range\"\n aria-label={`${parameterLabel(field)} opacity`}\n min={0}\n max={255}\n step={1}\n value={parseInt(a, 16)}\n disabled={off}\n className={rangeClass}\n onPointerDown={start}\n onPointerUp={end}\n onPointerCancel={end}\n onBlur={end}\n onChange={(e) => onChange(`${rgb}${Number(e.target.value).toString(16).padStart(2, '0')}`)}\n />\n )}\n {field.swatches && field.swatches.length > 0 && (\n <div className=\"flex flex-wrap gap-1\">\n {field.swatches.map((s) => {\n const swatch = normalizeHexColor(s, alpha);\n if (!swatch) return null;\n return (\n <button\n key={s}\n type=\"button\"\n title={swatch}\n aria-label={`${parameterLabel(field)} ${swatch}`}\n aria-pressed={swatch === (alpha ? hex : rgb)}\n disabled={off}\n onClick={() => onChange(swatch)}\n className=\"h-5 w-5 rounded border border-input aria-pressed:ring-1 aria-pressed:ring-primary\"\n style={{ background: swatch }}\n />\n );\n })}\n </div>\n )}\n </div>\n );\n}\n\n/** One number box per component for `vector` fields. */\nexport function ParameterVector({ field, value, onChange, disabled, id }: ParameterControlProps<VectorParameterField, number[]>) {\n const size = vectorSize(field);\n return (\n <div className=\"grid gap-1.5\" style={{ gridTemplateColumns: `repeat(${size}, minmax(0, 1fr))` }}>\n {Array.from({ length: size }, (_, i) => {\n const component = vectorComponentField(field, i);\n return (\n <label key={i} className=\"flex min-w-0 items-center gap-1\">\n <span className=\"w-3 shrink-0 text-[10px] uppercase text-muted-foreground\">{component.label}</span>\n <ParameterNumberInput\n field={component}\n value={value[i] ?? 0}\n id={i === 0 ? id : undefined}\n aria-label={`${parameterLabel(field)} ${component.label}`}\n disabled={disabled || field.readOnly}\n onChange={(n) => onChange(Array.from({ length: size }, (_, j) => (j === i ? n : (value[j] ?? 0))))}\n />\n </label>\n );\n })}\n </div>\n );\n}\n\nexport interface ParameterImageProps extends ParameterControlProps<ImageParameterField, string> {\n /** Turns a picked file into a URL (upload it, or `URL.createObjectURL`). Without it there is no file button. */\n resolveFile?: (file: File) => string | Promise<string>;\n}\n\n/** An image picker: suggested thumbnails, a URL box, an optional file button and a clear button. */\nexport function ParameterImage({ field, value, onChange, disabled, id, resolveFile }: ParameterImageProps) {\n const off = disabled || field.readOnly;\n const name = parameterLabel(field);\n return (\n <div className=\"space-y-1.5\">\n <div className=\"flex items-center gap-2\">\n <div className=\"flex h-12 w-16 shrink-0 items-center justify-center overflow-hidden rounded-md border border-input bg-muted\">\n {value ? (\n <img src={value} alt={name} className=\"h-full w-full object-cover\" />\n ) : (\n <span className=\"text-[10px] text-muted-foreground\">None</span>\n )}\n </div>\n <div className=\"flex min-w-0 flex-1 flex-col gap-1\">\n <ParameterCommitInput\n id={id}\n aria-label={`${name} URL`}\n placeholder=\"Image URL\"\n value={value.startsWith('data:') ? '' : value}\n disabled={off}\n onCommit={(text) => onChange(text.trim())}\n />\n <div className=\"flex gap-1\">\n {resolveFile && (\n <label className={`${parameterButtonClass} cursor-pointer ${off ? 'pointer-events-none opacity-50' : ''}`}>\n Choose file…\n <input\n type=\"file\"\n className=\"sr-only\"\n accept={field.accept ?? 'image/*'}\n disabled={off}\n aria-label={`${name} file`}\n onChange={async (e) => {\n const file = e.target.files?.[0];\n e.target.value = '';\n if (file) onChange(await resolveFile(file));\n }}\n />\n </label>\n )}\n {value && (\n <button type=\"button\" className={parameterButtonClass} disabled={off} onClick={() => onChange('')} aria-label={`Clear ${name}`}>\n Clear\n </button>\n )}\n </div>\n </div>\n </div>\n {field.options && field.options.length > 0 && (\n <div className=\"flex flex-wrap gap-1\">\n {field.options.map((o) => (\n <button\n key={o.url}\n type=\"button\"\n title={o.label ?? o.url}\n aria-label={o.label ?? o.url}\n aria-pressed={o.url === value}\n disabled={off}\n onClick={() => onChange(o.url)}\n className=\"h-9 w-12 overflow-hidden rounded border border-input aria-pressed:ring-2 aria-pressed:ring-primary\"\n >\n <img src={o.url} alt=\"\" className=\"h-full w-full object-cover\" />\n </button>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/** A text box (or textarea with `multiline`) that commits on blur or Enter. */\nexport function ParameterText({ field, value, onChange, disabled, id }: ParameterControlProps<TextParameterField, string>) {\n return (\n <ParameterCommitInput\n id={id}\n aria-label={parameterLabel(field)}\n multiline={field.multiline}\n placeholder={field.placeholder}\n maxLength={field.maxLength}\n value={value}\n disabled={disabled || field.readOnly}\n onCommit={onChange}\n />\n );\n}\n\nexport interface KeyframeDiamondProps {\n state: ParameterKeyState;\n onToggle: () => void;\n /** The parameter's label (for the accessible name). */\n label: string;\n disabled?: boolean;\n className?: string;\n}\n\n/** A keyframe toggle: filled when a key sits at the playhead, tinted when the value is animated. */\nexport function KeyframeDiamond({ state, onToggle, label, disabled, className = '' }: KeyframeDiamondProps) {\n const keyed = state === 'keyed';\n return (\n <button\n type=\"button\"\n data-key-state={state}\n aria-pressed={keyed}\n aria-label={`${keyed ? 'Remove' : 'Add'} keyframe for ${label}`}\n title={keyed ? 'Remove keyframe here' : 'Add keyframe at the playhead'}\n disabled={disabled}\n onClick={onToggle}\n className={`inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary disabled:opacity-40 ${\n state === 'none' ? 'text-muted-foreground hover:text-foreground' : 'text-amber-500'\n } ${className}`}\n >\n <svg viewBox=\"0 0 10 10\" className=\"h-2.5 w-2.5\" aria-hidden=\"true\">\n <path\n d=\"M5 0.8 9.2 5 5 9.2 0.8 5Z\"\n fill={keyed ? 'currentColor' : 'none'}\n stroke=\"currentColor\"\n strokeWidth=\"1.3\"\n opacity={state === 'animated' ? 0.7 : 1}\n />\n </svg>\n </button>\n );\n}\n\nexport interface ParameterFieldControlProps extends ParameterControlProps<ParameterField, ParameterValue> {\n resolveFile?: ParameterImageProps['resolveFile'];\n}\n\n/** The control for any field type. */\nexport function ParameterFieldControl({ field, value, onChange, resolveFile, ...rest }: ParameterFieldControlProps) {\n const set = onChange as (value: any) => void;\n switch (field.type) {\n case 'number':\n case 'int':\n return <ParameterSlider field={field} value={value as number} onChange={set} {...rest} />;\n case 'boolean':\n return <ParameterToggle field={field} value={value as boolean} onChange={set} {...rest} />;\n case 'choice':\n return <ParameterSelect field={field} value={value as string | number} onChange={set} {...rest} />;\n case 'color':\n return <ParameterColor field={field} value={value as string} onChange={set} {...rest} />;\n case 'vector':\n return <ParameterVector field={field} value={value as number[]} onChange={set} {...rest} />;\n case 'image':\n return <ParameterImage field={field} value={value as string} onChange={set} resolveFile={resolveFile} {...rest} />;\n case 'text':\n return <ParameterText field={field} value={value as string} onChange={set} {...rest} />;\n }\n}\n\n"],"mappings":"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","names":["import_react","import_paint_editor","import_react","import_paint_editor","import_react","import_jsx_runtime","import_jsx_runtime","import_react","import_paint_editor","import_paint_editor","import_react","import_jsx_runtime","button","paintSourceCss","import_jsx_runtime","import_jsx_runtime","import_react","import_paint_editor","import_jsx_runtime","import_react","import_paint_editor","import_jsx_runtime","g","import_react","import_paint_editor","import_jsx_runtime","import_paint_editor","import_jsx_runtime","import_react","import_paint_editor","import_jsx_runtime","import_react","import_react","import_paint_editor","import_react","import_react","import_jsx_runtime","import_react","import_effects","import_jsx_runtime","import_react","import_effects","import_parameters","import_react","import_jsx_runtime","_","import_jsx_runtime","React","import_jsx_runtime","import_jsx_runtime"]}