@weasel-js/core 0.5.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 (74) hide show
  1. package/CHANGELOG.md +381 -0
  2. package/LICENSE +21 -0
  3. package/README.md +144 -0
  4. package/dist/DrawCommand-Dl0bXNfS.d.ts +500 -0
  5. package/dist/chunk-775XXAHR.js +216 -0
  6. package/dist/chunk-775XXAHR.js.map +1 -0
  7. package/dist/chunk-7V6JEOXE.js +27754 -0
  8. package/dist/chunk-7V6JEOXE.js.map +1 -0
  9. package/dist/chunk-AM6ARSPN.js +517 -0
  10. package/dist/chunk-AM6ARSPN.js.map +1 -0
  11. package/dist/chunk-BGGZ4CVF.js +248 -0
  12. package/dist/chunk-BGGZ4CVF.js.map +1 -0
  13. package/dist/chunk-BHVYVFGV.js +29 -0
  14. package/dist/chunk-BHVYVFGV.js.map +1 -0
  15. package/dist/chunk-CQNKCG34.js +831 -0
  16. package/dist/chunk-CQNKCG34.js.map +1 -0
  17. package/dist/chunk-GVCNT7UH.js +47 -0
  18. package/dist/chunk-GVCNT7UH.js.map +1 -0
  19. package/dist/chunk-PZ5AY32C.js +9 -0
  20. package/dist/chunk-PZ5AY32C.js.map +1 -0
  21. package/dist/chunk-UGFFCMQP.js +28 -0
  22. package/dist/chunk-UGFFCMQP.js.map +1 -0
  23. package/dist/chunk-VOVKONXA.js +103 -0
  24. package/dist/chunk-VOVKONXA.js.map +1 -0
  25. package/dist/chunk-Y52N27PF.js +39 -0
  26. package/dist/chunk-Y52N27PF.js.map +1 -0
  27. package/dist/clipboard.d.ts +91 -0
  28. package/dist/clipboard.js +6 -0
  29. package/dist/clipboard.js.map +1 -0
  30. package/dist/clone.d.ts +8 -0
  31. package/dist/clone.js +6 -0
  32. package/dist/clone.js.map +1 -0
  33. package/dist/fitViewToBounds-evGsnR8Q.d.ts +62 -0
  34. package/dist/grid-Cf87knjU.d.ts +153 -0
  35. package/dist/index-DZBYMsHI.d.ts +1555 -0
  36. package/dist/index.css +121 -0
  37. package/dist/index.css.map +1 -0
  38. package/dist/index.d.ts +10200 -0
  39. package/dist/index.js +13 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/insert.d.ts +33 -0
  42. package/dist/insert.js +81 -0
  43. package/dist/insert.js.map +1 -0
  44. package/dist/move.d.ts +69 -0
  45. package/dist/move.js +145 -0
  46. package/dist/move.js.map +1 -0
  47. package/dist/options-BPPBWMa7.d.ts +64 -0
  48. package/dist/patterns-builtin.d.ts +55 -0
  49. package/dist/patterns-builtin.js +100 -0
  50. package/dist/patterns-builtin.js.map +1 -0
  51. package/dist/pointSnapToGrid-D7s7QmOF.d.ts +185 -0
  52. package/dist/registerFont-CP-wCsrz.d.ts +109 -0
  53. package/dist/registerTexture-BzHTLhD9.d.ts +25 -0
  54. package/dist/renderer.css +121 -0
  55. package/dist/renderer.css.map +1 -0
  56. package/dist/renderer.d.ts +376 -0
  57. package/dist/renderer.js +13 -0
  58. package/dist/renderer.js.map +1 -0
  59. package/dist/resize.d.ts +78 -0
  60. package/dist/resize.js +5 -0
  61. package/dist/resize.js.map +1 -0
  62. package/dist/routing.css +35 -0
  63. package/dist/routing.css.map +1 -0
  64. package/dist/routing.d.ts +14 -0
  65. package/dist/routing.js +4 -0
  66. package/dist/routing.js.map +1 -0
  67. package/dist/types-B6MMiodD.d.ts +59 -0
  68. package/dist/types-BJ8_cyT7.d.ts +130 -0
  69. package/dist/types-B_-khFM0.d.ts +331 -0
  70. package/dist/types-BjUi2vA-.d.ts +355 -0
  71. package/dist/types-Cpb4hii1.d.ts +445 -0
  72. package/dist/types-D2tTKEU0.d.ts +18 -0
  73. package/dist/view-DSQgxBJB.d.ts +63 -0
  74. package/package.json +96 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/units.ts","../src/features/paths/types.ts","../src/features/paths/bounds.ts","../src/features/paths/flatten.ts","../src/features/paths/hitTest.ts","../src/features/paths/builder.ts","../src/features/paths/transformPath.ts","../src/features/paths/transform.ts","../src/interactions/actions/resize/geometry.ts","../src/features/paths/poseDescriptor.ts","../src/interactions/actions/resize/autoPoseDescriptor.ts","../src/interactions/gestures/shared/strategies/grid.ts","../src/core/viewport/meanScale.ts","../src/interactions/gestures/shared/strategies/guides.ts"],"names":["ex","ey","COORD_COUNT"],"mappings":"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","file":"chunk-CQNKCG34.js","sourcesContent":["/**\n * Units — a tiny customizable unit system for canvas-kit APIs.\n *\n * The kit stores all coordinates as bare numbers in a single base unit\n * chosen by the consumer app. To make API call sites self-documenting,\n * the public surface accepts `UnitValue` — either a bare number (interpreted\n * as base units) or a `{ value, unit }` tag that's resolved against a\n * `UnitSystem` at the API boundary. Internals never see units.\n *\n * Linear factors only. No per-axis units. No mixed-unit arithmetic.\n */\n\n/** A unit name (e.g. `'in'`, `'ft'`, `'mm'`). Looked up in a `UnitSystem`. */\nexport type Unit = string;\n\n/** Conversion table mapping unit names to factors against a base unit. */\nexport interface UnitSystem {\n /** Name of the base unit, e.g. 'in'. All conversions resolve to this. */\n base: Unit;\n /** Factor to multiply a value in `unit` by to get base units. base unit's factor is 1. */\n units: Record<Unit, number>;\n}\n\n/** Value at a unit-aware API boundary: bare number (in base units) or `{ value, unit }` tag. */\nexport type UnitValue = number | { value: number; unit: Unit };\n\n/**\n * Resolve a UnitValue to a number in base units.\n * - bare number: returned as-is (assumed base)\n * - tagged: looks up factor; throws if unit not in unit system\n */\nexport function resolveUnit(v: UnitValue, unitSystem?: UnitSystem): number {\n if (typeof v === 'number') return v;\n if (!unitSystem) {\n throw new Error(\n `resolveUnit: tagged value { value: ${v.value}, unit: '${v.unit}' } requires a UnitSystem`,\n );\n }\n const factor = unitSystem.units[v.unit];\n if (factor === undefined) {\n const known = Object.keys(unitSystem.units).join(', ') || '(none)';\n throw new Error(\n `resolveUnit: unknown unit '${v.unit}' (system base: '${unitSystem.base}', known units: ${known})`,\n );\n }\n return v.value * factor;\n}\n\n/**\n * Format a base-unit number as a string in the named display unit.\n * e.g. formatUnit(36, 'ft', IMPERIAL_INCHES) => '3ft'\n * Default precision: 2. Trailing zeros trimmed.\n */\nexport function formatUnit(\n baseValue: number,\n displayUnit: Unit,\n unitSystem: UnitSystem,\n opts?: { precision?: number; suffix?: boolean },\n): string {\n const factor = unitSystem.units[displayUnit];\n if (factor === undefined) {\n const known = Object.keys(unitSystem.units).join(', ') || '(none)';\n throw new Error(\n `formatUnit: unknown unit '${displayUnit}' (system base: '${unitSystem.base}', known units: ${known})`,\n );\n }\n const precision = opts?.precision ?? 2;\n const suffix = opts?.suffix ?? true;\n const display = baseValue / factor;\n // Trim trailing zeros (and a dangling decimal point) without losing precision.\n let s = display.toFixed(precision);\n if (s.includes('.')) {\n s = s.replace(/0+$/, '').replace(/\\.$/, '');\n }\n return suffix ? `${s}${displayUnit}` : s;\n}\n\n/** Imperial unit system with base 'in'. */\nexport const IMPERIAL_INCHES: UnitSystem = {\n base: 'in',\n units: { in: 1, ft: 12, yd: 36, mi: 63360 },\n};\n\n/** Metric unit system with base 'mm'. */\nexport const METRIC_MM: UnitSystem = {\n base: 'mm',\n units: { mm: 1, cm: 10, m: 1000, km: 1_000_000 },\n};\n\n/** Pixel unit system — sole unit is the base. */\nexport const PIXELS: UnitSystem = {\n base: 'px',\n units: { px: 1 },\n};\n","/**\n * Path data model. Vector-graphics primitive used kit-wide as the canonical\n * shape (replacing per-shape ad-hoc poses). SVG-style command stream so we\n * cover lines, polygons, beziers, and multi-contour shapes (think the inner\n * hole of an \"O\") under one type.\n *\n * Storage: command codes in a `Uint8Array`, parameters in a `Float32Array`.\n * Each command consumes a fixed number of float coords from the parameter\n * array; the parser walks both arrays in lockstep. This keeps interaction\n * hot loops monomorphic and keeps GC pressure low under heavy edits.\n *\n * Two path subtypes are distinguished at the type level so common-case\n * machinery (selection AABBs, area-select intersection, hit-testing rect\n * silhouettes) can short-circuit on `RectPath` without paying the polygon\n * kernel cost. Polymorphic kernels accept either via the `Path` union and\n * dispatch on `kind`.\n */\n\n/** Command code: moveTo. */\nexport const PATH_M = 0;\n/** Command code: lineTo. */\nexport const PATH_L = 1;\n/** Command code: cubic bezier (`bezierCurveTo`). */\nexport const PATH_C = 2;\n/** Command code: quadratic bezier (`quadraticCurveTo`). */\nexport const PATH_Q = 3;\n/** Command code: close subpath. */\nexport const PATH_Z = 4;\n\n/** Float coords consumed by each command, indexed by command code. */\nexport const PATH_CMD_LENGTHS: readonly number[] = [2, 2, 6, 4, 0];\n\n/** Fill rule used by polygon path hit-testing and `ctx.fill()`. */\nexport type PathFillRule = 'nonzero' | 'evenodd';\n\n/**\n * Polygon path with arbitrary contours and optional bezier segments.\n * Multi-contour: each `M` opens a new subpath; `Z` closes the current one.\n * Open subpaths (no `Z`) render as polylines and don't contribute to fills.\n */\nexport interface PolygonPath {\n kind: 'polygon';\n commands: Uint8Array;\n coords: Float32Array;\n fillRule: PathFillRule;\n}\n\n/**\n * Axis-aligned rectangle. Fast path for the (very common) case where the\n * shape is just a rect — preserves O(1) bounds and hit-test, avoids the\n * polygon kernel entirely. Promote to `PolygonPath` only when the shape\n * grows beyond what a rect can express.\n */\nexport interface RectPath {\n kind: 'rect';\n x: number;\n y: number;\n width: number;\n height: number;\n}\n\n/** Canonical path shape — either an axis-aligned rect (fast path) or a polygon command stream. */\nexport type Path = PolygonPath | RectPath;\n","/**\n * AABB bounds of a `Path`. Returned as `RectPath` for direct reuse with the\n * rect fast path machinery (selection AABB, area-select intersection).\n *\n * `RectPath` is its own bounds — O(1). For `PolygonPath`, walk segment by\n * segment, computing the tight bound per segment:\n *\n * - `M` / `L`: just the endpoint.\n * - `Q`: quadratic Bezier — endpoints plus axis-aligned extrema (one\n * possible inflection per axis).\n * - `C`: cubic Bezier — endpoints plus axis-aligned extrema (up to two\n * possible inflections per axis, found via the quadratic formula on\n * the derivative).\n *\n * Control points are NOT included directly; they're used only to compute\n * extrema that actually lie on the curve. This avoids the classic \"AABB\n * extends past where the curve visibly reaches\" bug for curved paths whose\n * control points poke outside the visible extent.\n *\n * Empty paths (no commands) return a zero-size rect anchored at the\n * origin — the convention used elsewhere in the kit for missing geometry.\n */\n\nimport { cubicBounds, elevateQuadraticToCubic } from '@weasel-js/geom';\nimport {\n PATH_C,\n PATH_L,\n PATH_M,\n PATH_Q,\n PATH_Z,\n type Path,\n type RectPath,\n} from './types';\n\n/** AABB of a `Path`, returned as a `RectPath` for direct reuse with rect-fast-path machinery. */\nexport function boundsOfPath(path: Path): RectPath {\n if (path.kind === 'rect') return path;\n\n const { commands, coords } = path;\n if (commands.length === 0) {\n return { kind: 'rect', x: 0, y: 0, width: 0, height: 0 };\n }\n\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n let ci = 0;\n let seen = false;\n // Pen position carried across segments — needed because curves are\n // defined relative to the previous endpoint, which is itself the start\n // of the next segment but not re-encoded in `coords`.\n let px = 0, py = 0;\n\n const include = (x: number, y: number) => {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n seen = true;\n };\n\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n switch (cmd) {\n case PATH_M:\n case PATH_L: {\n const x = coords[ci], y = coords[ci + 1];\n include(x, y);\n px = x; py = y;\n ci += 2;\n break;\n }\n case PATH_C: {\n const x1 = coords[ci], y1 = coords[ci + 1];\n const x2 = coords[ci + 2], y2 = coords[ci + 3];\n const x3 = coords[ci + 4], y3 = coords[ci + 5];\n const [bMinX, bMinY, bMaxX, bMaxY] = cubicBounds(px, py, x1, y1, x2, y2, x3, y3);\n include(bMinX, bMinY);\n include(bMaxX, bMaxY);\n px = x3; py = y3;\n ci += 6;\n break;\n }\n case PATH_Q: {\n const qx1 = coords[ci], qy1 = coords[ci + 1];\n const qx2 = coords[ci + 2], qy2 = coords[ci + 3];\n const [c1x, c1y, c2x, c2y] = elevateQuadraticToCubic(px, py, qx1, qy1, qx2, qy2);\n const [bMinX, bMinY, bMaxX, bMaxY] = cubicBounds(px, py, c1x, c1y, c2x, c2y, qx2, qy2);\n include(bMinX, bMinY);\n include(bMaxX, bMaxY);\n px = qx2; py = qy2;\n ci += 4;\n break;\n }\n case PATH_Z:\n break;\n default:\n throw new Error(`boundsOfPath: unknown command ${cmd}`);\n }\n }\n\n if (!seen) return { kind: 'rect', x: 0, y: 0, width: 0, height: 0 };\n return { kind: 'rect', x: minX, y: minY, width: maxX - minX, height: maxY - minY };\n}\n\n","/**\n * Bezier flattening — subdivide cubic and quadratic segments into polyline\n * approximations within a flatness tolerance. Used by hit-testing and\n * (eventually) any kernel that doesn't want to special-case curves.\n *\n * The flatness metric is the maximum perpendicular distance from any\n * control point to the chord between endpoints. When that distance falls\n * below `tolerance`, the segment is \"flat enough\" and emitted as a single\n * line segment.\n *\n * Tolerance is in world units. 0.5 is a sensible default for screen-rate\n * rendering at 1× zoom; consumers that zoom in heavily should pass a\n * tighter tolerance.\n */\n\nexport const DEFAULT_FLATTEN_TOLERANCE = 0.5;\n\n/** Distance from point P to line AB (perpendicular). */\nfunction distPointToLine(px: number, py: number, ax: number, ay: number, bx: number, by: number): number {\n const dx = bx - ax;\n const dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) {\n const ex = px - ax;\n const ey = py - ay;\n return Math.sqrt(ex * ex + ey * ey);\n }\n const cross = (px - ax) * dy - (py - ay) * dx;\n return Math.abs(cross) / Math.sqrt(len2);\n}\n\n/**\n * Recursively subdivide a cubic bezier (P0..P3) and append `lineTo`-style\n * vertices to `out` (interleaved x,y). The starting endpoint is *not*\n * appended — callers usually emitted it as the segment's previous vertex.\n */\nexport function flattenCubic(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n): void {\n const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);\n if (Math.max(d1, d2) <= tolerance) {\n out.push(x3, y3);\n return;\n }\n // De Casteljau split at t=0.5\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;\n const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;\n flattenCubic(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out);\n flattenCubic(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out);\n}\n\n/** Recursively subdivide a quadratic bezier (P0, P1, P2). */\nexport function flattenQuadratic(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n): void {\n const d = distPointToLine(x1, y1, x0, y0, x2, y2);\n if (d <= tolerance) {\n out.push(x2, y2);\n return;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n flattenQuadratic(x0, y0, x01, y01, x012, y012, tolerance, out);\n flattenQuadratic(x012, y012, x12, y12, x2, y2, tolerance, out);\n}\n\n/**\n * Like `flattenCubic` but also appends, for each new flattened point, its\n * arc-length fraction `t` (relative to the polyline distance accumulated so\n * far inside this curve) to `arcOut`. Caller then post-processes the segment's\n * `arcOut` range by dividing each by the segment's total flattened arc length\n * to yield t ∈ (0, 1].\n *\n * The returned values are *cumulative distance from the segment start*, not\n * normalized fractions. Two-pass design (accumulate, then divide) keeps the\n * recursive splitter simple — it doesn't need to know the total length up\n * front.\n */\nexport function flattenCubicWithArcLen(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n): number {\n return flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut, 0);\n}\n\nfunction flattenCubicArcRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n accum: number,\n): number {\n const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);\n if (Math.max(d1, d2) <= tolerance) {\n const lastX = out.length >= 2 ? out[out.length - 2] : x0;\n const lastY = out.length >= 2 ? out[out.length - 1] : y0;\n const seg = Math.hypot(x3 - lastX, y3 - lastY);\n accum += seg;\n out.push(x3, y3);\n arcOut.push(accum);\n return accum;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;\n const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;\n accum = flattenCubicArcRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out, arcOut, accum);\n accum = flattenCubicArcRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out, arcOut, accum);\n return accum;\n}\n\nexport function flattenQuadraticWithArcLen(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n): number {\n return flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut, 0);\n}\n\nfunction flattenQuadraticArcRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n accum: number,\n): number {\n const d = distPointToLine(x1, y1, x0, y0, x2, y2);\n if (d <= tolerance) {\n const lastX = out.length >= 2 ? out[out.length - 2] : x0;\n const lastY = out.length >= 2 ? out[out.length - 1] : y0;\n const seg = Math.hypot(x2 - lastX, y2 - lastY);\n accum += seg;\n out.push(x2, y2);\n arcOut.push(accum);\n return accum;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n accum = flattenQuadraticArcRec(x0, y0, x01, y01, x012, y012, tolerance, out, arcOut, accum);\n accum = flattenQuadraticArcRec(x012, y012, x12, y12, x2, y2, tolerance, out, arcOut, accum);\n return accum;\n}\n\n","/**\n * Point-in-path hit-testing. `RectPath` short-circuits to AABB compare\n * (O(1)). `PolygonPath` walks the command stream, flattening any bezier\n * segments to line segments, then runs ray-casting (even-odd) or\n * winding-number (non-zero) per the path's `fillRule`.\n *\n * Open subpaths (no `Z`) are skipped for filled hit-testing — they have\n * no enclosed area. For open polylines (strokes), use `strokeHitTest`\n * which computes point-to-segment distance against the flattened\n * polyline and returns true within a configurable threshold.\n */\n\nimport { flattenCubic, flattenQuadratic, DEFAULT_FLATTEN_TOLERANCE } from './flatten';\nimport {\n PATH_C,\n PATH_L,\n PATH_M,\n PATH_Q,\n PATH_Z,\n type Path,\n type PolygonPath,\n} from './types';\n\n/** Options for `pointInPath`. */\nexport interface PointInPathOptions {\n /** Bezier flattening tolerance in world units. Default 0.5. */\n tolerance?: number;\n}\n\n/** Filled-region hit-test for a `Path`. Rect short-circuits to AABB; polygons run ray-cast / winding per `fillRule`. */\nexport function pointInPath(\n path: Path,\n x: number,\n y: number,\n opts: PointInPathOptions = {},\n): boolean {\n if (path.kind === 'rect') {\n return x >= path.x && x <= path.x + path.width && y >= path.y && y <= path.y + path.height;\n }\n return pointInPolygonPath(path, x, y, opts.tolerance ?? DEFAULT_FLATTEN_TOLERANCE);\n}\n\nfunction pointInPolygonPath(path: PolygonPath, x: number, y: number, tolerance: number): boolean {\n const { commands, coords, fillRule } = path;\n if (commands.length === 0) return false;\n\n // Walk the command stream; flatten beziers into per-subpath vertex arrays.\n // For each closed subpath, accumulate winding/crossings against (x, y).\n let crossings = 0;\n let winding = 0;\n\n let subStartX = 0, subStartY = 0;\n let curX = 0, curY = 0;\n let subVerts: number[] = []; // flat [x, y, x, y, ...] for current subpath\n let subOpen = false;\n\n const flushSubpath = (closed: boolean) => {\n if (closed && subVerts.length >= 4) {\n // Close the subpath back to its start.\n subVerts.push(subStartX, subStartY);\n // Now subVerts is a closed polyline; tally crossings/winding.\n for (let i = 0; i < subVerts.length - 2; i += 2) {\n const ax = subVerts[i], ay = subVerts[i + 1];\n const bx = subVerts[i + 2], by = subVerts[i + 3];\n if (segmentCrossesRayRight(x, y, ax, ay, bx, by)) {\n crossings++;\n if (ay <= y && by > y) winding++;\n else if (by <= y && ay > y) winding--;\n }\n }\n }\n subVerts = [];\n subOpen = false;\n };\n\n let ci = 0;\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n switch (cmd) {\n case PATH_M: {\n if (subOpen) flushSubpath(false);\n subStartX = coords[ci]; subStartY = coords[ci + 1];\n curX = subStartX; curY = subStartY;\n subVerts.push(curX, curY);\n subOpen = true;\n ci += 2;\n break;\n }\n case PATH_L: {\n curX = coords[ci]; curY = coords[ci + 1];\n subVerts.push(curX, curY);\n ci += 2;\n break;\n }\n case PATH_C: {\n const x1 = coords[ci], y1 = coords[ci + 1];\n const x2 = coords[ci + 2], y2 = coords[ci + 3];\n const x3 = coords[ci + 4], y3 = coords[ci + 5];\n flattenCubic(curX, curY, x1, y1, x2, y2, x3, y3, tolerance, subVerts);\n curX = x3; curY = y3;\n ci += 6;\n break;\n }\n case PATH_Q: {\n const x1 = coords[ci], y1 = coords[ci + 1];\n const x2 = coords[ci + 2], y2 = coords[ci + 3];\n flattenQuadratic(curX, curY, x1, y1, x2, y2, tolerance, subVerts);\n curX = x2; curY = y2;\n ci += 4;\n break;\n }\n case PATH_Z: {\n flushSubpath(true);\n curX = subStartX; curY = subStartY;\n break;\n }\n default:\n throw new Error(`pointInPath: unknown command ${cmd}`);\n }\n }\n if (subOpen) flushSubpath(false);\n\n return fillRule === 'evenodd' ? (crossings & 1) === 1 : winding !== 0;\n}\n\n/**\n * Does the rightward horizontal ray from (x, y) cross segment (ax,ay)→(bx,by)?\n * Standard half-open rule (segments touching from above count, from below\n * don't) — avoids double-counting at shared vertices.\n */\nfunction segmentCrossesRayRight(\n x: number, y: number,\n ax: number, ay: number,\n bx: number, by: number,\n): boolean {\n if ((ay > y) === (by > y)) return false;\n const xCross = ax + ((y - ay) / (by - ay)) * (bx - ax);\n return x < xCross;\n}\n\n/** Options for {@link strokeHitTest}. */\nexport interface StrokeHitTestOptions {\n /** Bezier flattening tolerance in world units. Default 0.5. */\n tolerance?: number;\n}\n\n/**\n * Stroke-distance hit-test. Returns true when (x, y) lies within\n * `threshold` world units of the path's outline — i.e. when a stroke\n * of total width `2 * threshold` drawn along the path would cover the\n * point.\n *\n * Works for both closed and open subpaths — unlike {@link pointInPath},\n * which only tests filled regions. Use this for picking on open\n * polylines / curves and for adding stroke-clickability to closed\n * shapes (logical OR with `pointInPath` when both behaviors are\n * desired).\n *\n * `threshold` is typically the stroke's half-width plus a small slop\n * (e.g. `strokeWidth / 2 + 4`). Cap segments are approximated by the\n * threshold radius around each anchor — the test treats every flattened\n * segment as a capsule of width `2 * threshold`.\n */\nexport function strokeHitTest(\n path: Path,\n x: number,\n y: number,\n threshold: number,\n opts: StrokeHitTestOptions = {},\n): boolean {\n const t2 = threshold * threshold;\n if (path.kind === 'rect') {\n const { x: rx, y: ry, width: w, height: h } = path;\n return (\n pointSegmentDist2(x, y, rx, ry, rx + w, ry) <= t2\n || pointSegmentDist2(x, y, rx + w, ry, rx + w, ry + h) <= t2\n || pointSegmentDist2(x, y, rx + w, ry + h, rx, ry + h) <= t2\n || pointSegmentDist2(x, y, rx, ry + h, rx, ry) <= t2\n );\n }\n return polylineWithinThreshold(path, x, y, t2, opts.tolerance ?? DEFAULT_FLATTEN_TOLERANCE);\n}\n\nfunction polylineWithinThreshold(\n path: PolygonPath,\n px: number, py: number,\n t2: number,\n tolerance: number,\n): boolean {\n const { commands, coords } = path;\n if (commands.length === 0) return false;\n\n // Reuse pointInPath's command-stream + flatten walk; check distance from\n // (px, py) to each emitted segment instead of accumulating crossings.\n let subStartX = 0, subStartY = 0;\n let curX = 0, curY = 0;\n let subVerts: number[] = [];\n let subOpen = false;\n\n const checkSegments = (closed: boolean): boolean => {\n if (closed && subVerts.length >= 4) subVerts.push(subStartX, subStartY);\n for (let i = 0; i < subVerts.length - 2; i += 2) {\n if (pointSegmentDist2(px, py, subVerts[i], subVerts[i + 1], subVerts[i + 2], subVerts[i + 3]) <= t2) {\n return true;\n }\n }\n return false;\n };\n\n let ci = 0;\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n switch (cmd) {\n case PATH_M: {\n if (subOpen) {\n if (checkSegments(false)) return true;\n subVerts = [];\n }\n subStartX = coords[ci]; subStartY = coords[ci + 1];\n curX = subStartX; curY = subStartY;\n subVerts.push(curX, curY);\n subOpen = true;\n ci += 2;\n break;\n }\n case PATH_L: {\n curX = coords[ci]; curY = coords[ci + 1];\n subVerts.push(curX, curY);\n ci += 2;\n break;\n }\n case PATH_C: {\n const x1 = coords[ci], y1 = coords[ci + 1];\n const x2 = coords[ci + 2], y2 = coords[ci + 3];\n const x3 = coords[ci + 4], y3 = coords[ci + 5];\n flattenCubic(curX, curY, x1, y1, x2, y2, x3, y3, tolerance, subVerts);\n curX = x3; curY = y3;\n ci += 6;\n break;\n }\n case PATH_Q: {\n const x1 = coords[ci], y1 = coords[ci + 1];\n const x2 = coords[ci + 2], y2 = coords[ci + 3];\n flattenQuadratic(curX, curY, x1, y1, x2, y2, tolerance, subVerts);\n curX = x2; curY = y2;\n ci += 4;\n break;\n }\n case PATH_Z: {\n if (checkSegments(true)) return true;\n subVerts = [];\n subOpen = false;\n curX = subStartX; curY = subStartY;\n break;\n }\n default:\n throw new Error(`strokeHitTest: unknown command ${cmd}`);\n }\n }\n if (subOpen && checkSegments(false)) return true;\n return false;\n}\n\n/** Squared distance from (px, py) to the closest point on segment (ax,ay)→(bx,by). */\nfunction pointSegmentDist2(\n px: number, py: number,\n ax: number, ay: number,\n bx: number, by: number,\n): number {\n const dx = bx - ax;\n const dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) {\n const ex = px - ax, ey = py - ay;\n return ex * ex + ey * ey;\n }\n let t = ((px - ax) * dx + (py - ay) * dy) / len2;\n if (t < 0) t = 0; else if (t > 1) t = 1;\n const cx = ax + t * dx;\n const cy = ay + t * dy;\n const ex = px - cx, ey = py - cy;\n return ex * ex + ey * ey;\n}\n","/**\n * Fluent builder for `PolygonPath`. Hides the `Uint8Array` / `Float32Array`\n * encoding behind move/line/curve/close calls and a final `build()`. Use\n * this to construct paths in tests and demos; production callers that need\n * to mutate large paths in place should reach for the raw arrays directly.\n *\n * Numeric capacity grows by doubling — typical for amortized O(1) push.\n *\n * Also exposes `rectPath` / `polygonFromPoints` shortcuts for the common\n * cases. `rectPath` returns the lighter `RectPath` subtype, not a polygon.\n */\n\nimport {\n PATH_C,\n PATH_L,\n PATH_M,\n PATH_Q,\n PATH_Z,\n type PathFillRule,\n type PolygonPath,\n type RectPath,\n} from './types';\n\n/** Fluent builder for `PolygonPath`; hides the `Uint8Array`/`Float32Array` encoding behind move/line/curve/close calls. */\nexport class PathBuilder {\n private cmds: number[] = [];\n private xs: number[] = [];\n private fillRule: PathFillRule = 'nonzero';\n\n /** Seed a builder with an existing `PolygonPath`. Useful for extending\n * an in-flight path with another segment (e.g. appending a cubic to\n * the end of a curve in response to a user action) without hand-\n * reaching into the `commands` / `coords` typed arrays.\n *\n * ```ts\n * const next = PathBuilder.fromPath(current).curveTo(...).build();\n * ```\n */\n static fromPath(path: PolygonPath): PathBuilder {\n const b = new PathBuilder();\n b.cmds = Array.from(path.commands);\n b.xs = Array.from(path.coords);\n b.fillRule = path.fillRule;\n return b;\n }\n\n setFillRule(rule: PathFillRule): this {\n this.fillRule = rule;\n return this;\n }\n\n moveTo(x: number, y: number): this {\n this.cmds.push(PATH_M);\n this.xs.push(x, y);\n return this;\n }\n\n lineTo(x: number, y: number): this {\n this.cmds.push(PATH_L);\n this.xs.push(x, y);\n return this;\n }\n\n /** Cubic bezier to (x, y) with control points (x1, y1) and (x2, y2). */\n curveTo(x1: number, y1: number, x2: number, y2: number, x: number, y: number): this {\n this.cmds.push(PATH_C);\n this.xs.push(x1, y1, x2, y2, x, y);\n return this;\n }\n\n /** Quadratic bezier to (x, y) with control point (x1, y1). */\n quadTo(x1: number, y1: number, x: number, y: number): this {\n this.cmds.push(PATH_Q);\n this.xs.push(x1, y1, x, y);\n return this;\n }\n\n close(): this {\n this.cmds.push(PATH_Z);\n return this;\n }\n\n build(): PolygonPath {\n return {\n kind: 'polygon',\n commands: new Uint8Array(this.cmds),\n coords: new Float32Array(this.xs),\n fillRule: this.fillRule,\n };\n }\n}\n\n/** Construct a `RectPath` (the fast-path subtype). */\nexport function rectPath(x: number, y: number, width: number, height: number): RectPath {\n return { kind: 'rect', x, y, width, height };\n}\n\n/** Build a closed polygon from a flat list of points. */\nexport function polygonFromPoints(\n points: readonly { x: number; y: number }[],\n opts: { fillRule?: PathFillRule } = {},\n): PolygonPath {\n if (points.length === 0) {\n return {\n kind: 'polygon',\n commands: new Uint8Array(),\n coords: new Float32Array(),\n fillRule: opts.fillRule ?? 'nonzero',\n };\n }\n const b = new PathBuilder();\n if (opts.fillRule) b.setFillRule(opts.fillRule);\n b.moveTo(points[0].x, points[0].y);\n for (let i = 1; i < points.length; i++) b.lineTo(points[i].x, points[i].y);\n b.close();\n return b.build();\n}\n\n/** Cubic-Bezier kappa for circular-quadrant approximation (<1% max error). */\nconst ELLIPSE_KAPPA = 0.5522847498307936;\n\n/** Closed ellipse inscribed in `bounds`, as a 4-cubic-Bezier `PolygonPath`.\n * Matches the geometry `useEllipseTool`'s overlay paints. */\nexport function ellipsePath(\n bounds: { x: number; y: number; width: number; height: number },\n): PolygonPath {\n const cx = bounds.x + bounds.width / 2;\n const cy = bounds.y + bounds.height / 2;\n const rx = bounds.width / 2;\n const ry = bounds.height / 2;\n const ox = rx * ELLIPSE_KAPPA;\n const oy = ry * ELLIPSE_KAPPA;\n const b = new PathBuilder();\n b.moveTo(cx + rx, cy);\n b.curveTo(cx + rx, cy + oy, cx + ox, cy + ry, cx, cy + ry);\n b.curveTo(cx - ox, cy + ry, cx - rx, cy + oy, cx - rx, cy);\n b.curveTo(cx - rx, cy - oy, cx - ox, cy - ry, cx, cy - ry);\n b.curveTo(cx + ox, cy - ry, cx + rx, cy - oy, cx + rx, cy);\n b.close();\n return b.build();\n}\n\n/** Closed regular n-gon centered at `center`, circumscribed by `radius`.\n * `rotation` is in radians; default 0 puts the first vertex on the +x axis. */\nexport function regularPolygonPath(\n center: { x: number; y: number },\n radius: number,\n sides: number,\n rotation = 0,\n): PolygonPath {\n const b = new PathBuilder();\n for (let i = 0; i < sides; i++) {\n const a = rotation + (i / sides) * Math.PI * 2;\n const x = center.x + radius * Math.cos(a);\n const y = center.y + radius * Math.sin(a);\n if (i === 0) b.moveTo(x, y); else b.lineTo(x, y);\n }\n b.close();\n return b.build();\n}\n\n/** Closed n-pointed star centered at `center`, alternating `outerRadius` and\n * `innerRadius` (default `outerRadius / 2`). `rotation` is in radians. */\nexport function starPath(\n center: { x: number; y: number },\n outerRadius: number,\n points = 5,\n innerRadius: number = outerRadius / 2,\n rotation = 0,\n): PolygonPath {\n const b = new PathBuilder();\n const n = points * 2;\n for (let i = 0; i < n; i++) {\n const a = rotation + (i / n) * Math.PI * 2;\n const r = i % 2 === 0 ? outerRadius : innerRadius;\n const x = center.x + r * Math.cos(a);\n const y = center.y + r * Math.sin(a);\n if (i === 0) b.moveTo(x, y); else b.lineTo(x, y);\n }\n b.close();\n return b.build();\n}\n\n/** Open 2-vertex polyline from `a` to `b` — strokeable, not fillable. */\nexport function linePath(\n a: { x: number; y: number },\n b: { x: number; y: number },\n): PolygonPath {\n const pb = new PathBuilder();\n pb.moveTo(a.x, a.y);\n pb.lineTo(b.x, b.y);\n return pb.build();\n}\n","import { type Mat3, transformCoords } from '@weasel-js/geom';\nimport { PathBuilder } from './builder';\nimport { type Path, type PolygonPath } from './types';\n\n/** Apply an affine `Mat3` to a path's geometry.\n *\n * Axis-aligned maps (no rotation/shear, i.e. `m[1] === 0 && m[2] === 0`) keep a\n * `RectPath` a rect — the four corners stay axis-aligned, so we transform the\n * two diagonal corners and normalize negative extent (mirror). Rotation or\n * shear promotes the rect's four corners to a `PolygonPath`. Polygon paths map\n * every coord via the kernel's `transformCoords`, preserving the command stream\n * and `fillRule`. Never mutates the input.\n *\n * `Mat3` here is the 6-tuple `number[]` from `@weasel-js/geom` (DOMMatrix order:\n * `[a, b, c, d, e, f]` where `x' = a·x + c·y + e`, `y' = b·x + d·y + f`),\n * not the renderer's 9-element `Float32Array`. */\nexport function transformPath(path: Path, m: Mat3): Path {\n const [a, b, c, d, e, f] = m;\n if (path.kind === 'rect') {\n if (b === 0 && c === 0) {\n // Pure scale + translate — corners remain axis-aligned.\n const x0 = a * path.x + e;\n const y0 = d * path.y + f;\n const x1 = a * (path.x + path.width) + e;\n const y1 = d * (path.y + path.height) + f;\n return {\n kind: 'rect',\n x: Math.min(x0, x1),\n y: Math.min(y0, y1),\n width: Math.abs(x1 - x0),\n height: Math.abs(y1 - y0),\n };\n }\n // Rotation / shear — promote to polygon with the four rect corners.\n const poly = new PathBuilder()\n .moveTo(path.x, path.y)\n .lineTo(path.x + path.width, path.y)\n .lineTo(path.x + path.width, path.y + path.height)\n .lineTo(path.x, path.y + path.height)\n .close()\n .build();\n return transformPolygon(poly, m);\n }\n return transformPolygon(path, m);\n}\n\nfunction transformPolygon(path: PolygonPath, m: Mat3): PolygonPath {\n // transformCoords returns Float64Array; PolygonPath.coords is Float32Array.\n const mapped = transformCoords(path.coords, m);\n return { ...path, coords: Float32Array.from(mapped) };\n}\n","/**\n * In-place and copy-out path transforms. Translation is the most common —\n * called every pointermove during a drag — so the polygon variant mutates\n * the float buffer directly to keep allocation pressure off the GC.\n *\n * `scalePathToBounds` is for the resize interaction: given the path's\n * current AABB and the desired new AABB, scales every coordinate\n * proportionally. Degenerate source bounds (zero width/height) collapse\n * the corresponding axis to the new origin — preferable to dividing by\n * zero or refusing to resize.\n */\n\nimport { boxToBox } from '@weasel-js/geom';\nimport { boundsOfPath } from './bounds';\nimport { transformPath } from './transformPath';\nimport { PATH_C, PATH_L, PATH_M, PATH_Q, PATH_Z, type Path, type PolygonPath, type RectPath } from './types';\n\n/**\n * Translate a path by (dx, dy). Returns a new instance — the kit's pose\n * model treats poses as immutable to keep React state-update semantics\n * predictable. Polygon coords are copied into a fresh `Float32Array`.\n */\nexport function translatePath(path: Path, dx: number, dy: number): Path {\n if (path.kind === 'rect') {\n return { kind: 'rect', x: path.x + dx, y: path.y + dy, width: path.width, height: path.height };\n }\n return translatePolygonCopy(path, dx, dy);\n}\n\nfunction translatePolygonCopy(path: PolygonPath, dx: number, dy: number): PolygonPath {\n const next = new Float32Array(path.coords.length);\n const { commands, coords } = path;\n let ci = 0;\n for (let i = 0; i < commands.length; i++) {\n const len = COORD_COUNT[commands[i]];\n for (let k = 0; k < len; k += 2) {\n next[ci + k] = coords[ci + k] + dx;\n next[ci + k + 1] = coords[ci + k + 1] + dy;\n }\n ci += len;\n }\n return { kind: 'polygon', commands: path.commands, coords: next, fillRule: path.fillRule };\n}\n\n/**\n * Translate a polygon path's coords *in place*. Returns the same\n * `PolygonPath` reference. Use only for transient overlay buffers — never\n * for committed scene state, which must remain immutable for React.\n */\nexport function translatePolygonInPlace(path: PolygonPath, dx: number, dy: number): PolygonPath {\n const { commands, coords } = path;\n let ci = 0;\n for (let i = 0; i < commands.length; i++) {\n const len = COORD_COUNT[commands[i]];\n for (let k = 0; k < len; k += 2) {\n coords[ci + k] += dx;\n coords[ci + k + 1] += dy;\n }\n ci += len;\n }\n return path;\n}\n\n/**\n * Scale a path's coords so its current AABB maps to `target`. Resize\n * interactions use this to make a polygon follow a corner-handle drag.\n *\n * Degenerate source axes (width or height == 0) collapse to `target.x` /\n * `target.y` — every coord on that axis becomes the new origin. Avoids\n * division by zero without throwing.\n */\nexport function scalePathToBounds(path: Path, target: RectPath): Path {\n if (path.kind === 'rect') {\n return { kind: 'rect', x: target.x, y: target.y, width: target.width, height: target.height };\n }\n const src = boundsOfPath(path);\n return scalePolygon(path, src, target);\n}\n\nfunction scalePolygon(path: PolygonPath, src: RectPath, dst: RectPath): PolygonPath {\n const m = boxToBox(src.x, src.y, src.width, src.height, dst.x, dst.y, dst.width, dst.height);\n // src/dst are axis-aligned, so the polygon stays a polygon after this pure scale+translate.\n return transformPath(path, m) as PolygonPath;\n}\n\nconst COORD_COUNT: Readonly<Record<number, number>> = {\n [PATH_M]: 2,\n [PATH_L]: 2,\n [PATH_C]: 6,\n [PATH_Q]: 4,\n [PATH_Z]: 0,\n};\n","import type { ResizePose, RotatedPose } from '../../gestures/types';\n\n/**\n * Bridges arbitrary `TPose` shapes into the resize hook's bounds-driven math.\n * The hook reads bounds via `getBounds`, runs anchor-relative math on those\n * bounds, then asks `remapBounds` to project the result back into TPose.\n *\n * `remapBounds(pose, src, dst)` is a single operation that subsumes both\n * \"set my own AABB to dst\" (single-leaf resize) and \"scale me as a leaf\n * inside parent's src→dst rect\" (group resize) — they're the same affine\n * map. For rect-shaped poses the default geometry interprets the pose as\n * its own bounds; for Path or polygon poses the consumer supplies a\n * projection that knows how to read and rewrite the underlying geometry.\n */\nexport interface PoseProjection<TPose> {\n getBounds(pose: TPose): ResizePose;\n remapBounds(pose: TPose, src: ResizePose, dst: ResizePose): TPose;\n /** Translate the pose by (dx, dy). Optional — when omitted, callers fall\n * back to a translation derived from `remapBounds` (origin shifted, no\n * scale). Path-shaped poses should provide this for performance. */\n translate?(pose: TPose, dx: number, dy: number): TPose;\n /** True iff any portion of the pose's geometry intersects `rect`. Optional\n * — when omitted, area-select and similar callers test against `getBounds`\n * AABB (looser, but correct for axis-aligned rect poses). */\n intersectsRect?(pose: TPose, rect: ResizePose): boolean;\n /** Interpolate between two poses. Optional — animation helpers fall back to\n * rect-shape lerp when omitted (which fails for non-rect poses). */\n lerp?(a: TPose, b: TPose, t: number): TPose;\n /** Read the pose's rotation in radians. Pivot is the AABB center\n * (`getBounds(pose)` center). Default 0 when omitted — descriptor\n * declares \"this pose has no rotation.\" When supplied and non-zero,\n * `useResize` projects the drag delta into the leaf's local frame,\n * runs anchor math there, and translates the resulting pose so the\n * diagonally opposite world-space corner is pinned. */\n getRotation?(pose: TPose): number;\n /** True iff this pose shape can carry a rotation. Consulted by the\n * rotation affordance to decide whether to render the rotate cursor /\n * drag-band over a selection. When omitted, the kit assumes `true` for\n * back-compat — descriptors whose poses lack `x/y/width/height/rotation`\n * fields (e.g. polygon Paths) should return `false` so the affordance\n * hides instead of exposing a non-functional rotate cursor. */\n supportsRotation?(pose: TPose): boolean;\n}\n\n/** AABB-vs-AABB overlap. Exported for callers building a default\n * `intersectsRect` from `getBounds`. */\nexport function aabbIntersectsRect(b: ResizePose, r: ResizePose): boolean {\n return b.x < r.x + r.width && b.x + b.width > r.x && b.y < r.y + r.height && b.y + b.height > r.y;\n}\n\n/** Identity geometry for `TPose extends ResizePose`. Treats the pose as its\n * own bounds and remaps via affine scale against `src`/`dst`. */\nexport const RECT_POSE_DESCRIPTOR: PoseProjection<ResizePose> = {\n getBounds: (p) => p,\n remapBounds: (p, src, dst) => {\n const sx = src.width === 0 ? 1 : dst.width / src.width;\n const sy = src.height === 0 ? 1 : dst.height / src.height;\n return {\n ...p,\n x: dst.x + (p.x - src.x) * sx,\n y: dst.y + (p.y - src.y) * sy,\n width: p.width * sx,\n height: p.height * sy,\n };\n },\n translate: (p, dx, dy) => ({ ...p, x: p.x + dx, y: p.y + dy }),\n intersectsRect: (p, r) => aabbIntersectsRect(p, r),\n lerp: (a, b, t) => ({\n ...a,\n x: a.x + (b.x - a.x) * t,\n y: a.y + (b.y - a.y) * t,\n width: a.width + (b.width - a.width) * t,\n height: a.height + (b.height - a.height) * t,\n }),\n};\n\n/** Identity geometry for `RotatedPose`. Inherits rect-shape projection\n * from `RECT_POSE_DESCRIPTOR` (the `RotatedPose extends ResizePose`\n * subtype lets the rect descriptor's methods apply directly; `remapBounds`\n * preserves the `rotation` field via `...p` spread). Adds `getRotation` so\n * `useResize` knows to take the rotation-aware math path. */\nexport const ROTATED_POSE_DESCRIPTOR: PoseProjection<RotatedPose> = {\n getBounds: RECT_POSE_DESCRIPTOR.getBounds as PoseProjection<RotatedPose>['getBounds'],\n remapBounds: RECT_POSE_DESCRIPTOR.remapBounds as PoseProjection<RotatedPose>['remapBounds'],\n translate: RECT_POSE_DESCRIPTOR.translate as PoseProjection<RotatedPose>['translate'],\n intersectsRect: RECT_POSE_DESCRIPTOR.intersectsRect as PoseProjection<RotatedPose>['intersectsRect'],\n lerp: RECT_POSE_DESCRIPTOR.lerp as PoseProjection<RotatedPose>['lerp'],\n getRotation: (p) => p.rotation,\n};\n","import { boundsOfPath } from './bounds';\nimport { pointInPath } from './hitTest';\nimport { translatePath } from './transform';\nimport { PATH_C, PATH_L, PATH_M, PATH_Q, PATH_Z, type Path, type PolygonPath } from './types';\nimport { aabbIntersectsRect, type PoseProjection } from 'interactions/actions/resize/geometry';\nimport type { ResizePose } from 'interactions/gestures/types';\n\n/**\n * `PoseProjection` for `Path` poses — wires `useResize` to operate\n * on `Path` directly. `getBounds` defers to the same `boundsOfPath` kernel\n * the rest of the kit uses; `remapBounds` does an affine scale of every\n * coord against `src`/`dst`. Degenerate axes (zero src extent) collapse to\n * the new origin so resize from a flat edge doesn't produce NaN.\n *\n * Mirrors `scalePathToBounds` but takes `src` explicitly: the resize hook\n * knows the group's origin AABB and uses it for every leaf, instead of\n * each leaf scaling against its own AABB (which would ignore group context).\n */\nexport const pathPoseDescriptor: PoseProjection<Path> = {\n getBounds: (path) => boundsOfPath(path),\n remapBounds: (path, src, dst) => {\n const sx = src.width === 0 ? 0 : dst.width / src.width;\n const sy = src.height === 0 ? 0 : dst.height / src.height;\n if (path.kind === 'rect') {\n return {\n kind: 'rect',\n x: dst.x + (path.x - src.x) * sx,\n y: dst.y + (path.y - src.y) * sy,\n width: path.width * sx,\n height: path.height * sy,\n };\n }\n return remapPolygon(path, src, dst, sx, sy);\n },\n translate: (path, dx, dy) => translatePath(path, dx, dy),\n // WHY: AABB pre-test is cheap; only fall through to per-corner pointInPath\n // when the rect is fully inside the AABB (silhouette test).\n intersectsRect: (path, rect) => {\n const b = boundsOfPath(path);\n if (!aabbIntersectsRect(b, rect)) return false;\n if (path.kind === 'rect') return true;\n // Sample the rect's four corners; any inside the polygon ⇒ overlap.\n if (\n pointInPath(path, rect.x, rect.y) ||\n pointInPath(path, rect.x + rect.width, rect.y) ||\n pointInPath(path, rect.x, rect.y + rect.height) ||\n pointInPath(path, rect.x + rect.width, rect.y + rect.height)\n ) return true;\n // Conservative fallback: AABB overlap counts. Tighter edge-vs-edge test\n // would be the next step; defer until a demo demands it.\n return true;\n },\n lerp: (a, b, t) => {\n if (a.kind === 'rect' && b.kind === 'rect') {\n return {\n kind: 'rect',\n x: a.x + (b.x - a.x) * t,\n y: a.y + (b.y - a.y) * t,\n width: a.width + (b.width - a.width) * t,\n height: a.height + (b.height - a.height) * t,\n };\n }\n if (a.kind === 'polygon' && b.kind === 'polygon' && a.coords.length === b.coords.length) {\n const next = new Float32Array(a.coords.length);\n for (let i = 0; i < a.coords.length; i++) {\n next[i] = a.coords[i] + (b.coords[i] - a.coords[i]) * t;\n }\n return { kind: 'polygon', commands: a.commands, coords: next, fillRule: a.fillRule };\n }\n throw new Error('pathPoseDescriptor.lerp: incompatible path shapes');\n },\n // Path poses carry no x/y/width/height/rotation fields — the kit's\n // `wrapWithPoseRotation` helper has nothing to bind a rotation to, and\n // `remapBounds` would drop a synthetic rotation field on every commit.\n // Returning false here hides the rotation affordance for Path consumers\n // so the rotate cursor doesn't appear without a working interaction.\n supportsRotation: () => false,\n};\n\nfunction remapPolygon(path: PolygonPath, src: ResizePose, dst: ResizePose, sx: number, sy: number): PolygonPath {\n const next = new Float32Array(path.coords.length);\n const { commands, coords } = path;\n let ci = 0;\n for (let i = 0; i < commands.length; i++) {\n const len = COORD_COUNT[commands[i]];\n for (let k = 0; k < len; k += 2) {\n next[ci + k] = dst.x + (coords[ci + k] - src.x) * sx;\n next[ci + k + 1] = dst.y + (coords[ci + k + 1] - src.y) * sy;\n }\n ci += len;\n }\n return { kind: 'polygon', commands: path.commands, coords: next, fillRule: path.fillRule };\n}\n\nconst COORD_COUNT: Readonly<Record<number, number>> = {\n [PATH_M]: 2,\n [PATH_L]: 2,\n [PATH_C]: 6,\n [PATH_Q]: 4,\n [PATH_Z]: 0,\n};\n","import type { Path } from 'features/paths/types';\nimport { pathPoseDescriptor } from 'features/paths/poseDescriptor';\nimport { RECT_POSE_DESCRIPTOR, type PoseProjection } from './geometry';\n\n/** True for Path-shaped poses (`{kind: 'polygon' | 'rect'}`). Useful for\n * callers that need to fork between `pathPoseDescriptor` and\n * `RECT_POSE_DESCRIPTOR` without forcing the consumer to wire `geometry`\n * explicitly. */\nexport function isPathLike(p: unknown): p is Path {\n return !!p && typeof p === 'object' && 'kind' in p\n && ((p as { kind: unknown }).kind === 'polygon' || (p as { kind: unknown }).kind === 'rect');\n}\n\n/** Per-call dispatch: if the pose looks like a Path, route to\n * `pathPoseDescriptor`; otherwise treat as a plain rect pose. Avoids forcing\n * demos with Path TPose to wire `geometry={pathPoseDescriptor}` explicitly.\n * `getRotation` surfaces a `pose.rotation` field on non-Path poses so demos\n * using rect-with-rotation shapes (e.g. `RotatedPose`) don't have to wire\n * `geometry={ROTATED_POSE_DESCRIPTOR}` just to get rotated selection chrome\n * and rotation-aware corner hit-tests. */\nexport const AUTO_POSE_DESCRIPTOR: PoseProjection<unknown> = {\n getBounds: (p) => isPathLike(p)\n ? pathPoseDescriptor.getBounds(p)\n : RECT_POSE_DESCRIPTOR.getBounds(p as { x: number; y: number; width: number; height: number }),\n remapBounds: (p, src, dst) => isPathLike(p)\n ? pathPoseDescriptor.remapBounds(p, src, dst)\n : RECT_POSE_DESCRIPTOR.remapBounds(p as { x: number; y: number; width: number; height: number }, src, dst),\n translate: (p, dx, dy) => isPathLike(p)\n ? pathPoseDescriptor.translate!(p, dx, dy)\n : RECT_POSE_DESCRIPTOR.translate!(p as { x: number; y: number; width: number; height: number }, dx, dy),\n intersectsRect: (p, rect) => isPathLike(p)\n ? pathPoseDescriptor.intersectsRect!(p, rect)\n : RECT_POSE_DESCRIPTOR.intersectsRect!(p as { x: number; y: number; width: number; height: number }, rect),\n getRotation: (p) => {\n if (isPathLike(p)) return 0;\n const r = (p as { rotation?: unknown }).rotation;\n return typeof r === 'number' ? r : 0;\n },\n // Path-shaped poses can't carry rotation (see `pathPoseDescriptor`).\n // Everything else flows through `wrapWithPoseRotation`'s x/y/w/h gate at\n // paint time, so report `true` and let the wrapper no-op for poses\n // missing AABB fields.\n supportsRotation: (p) => !isPathLike(p),\n};\n","import type { SnapStrategy } from '../../types';\nimport { resolveUnit, type UnitSystem, type UnitValue } from 'core/units';\nimport type { DebugSink } from '../../../../debug/types';\nimport { isPathLike } from 'interactions/actions/resize/autoPoseDescriptor';\nimport { boundsOfPath } from 'features/paths/bounds';\nimport { translatePath } from 'features/paths/transform';\nimport type { Path } from 'features/paths/types';\n\n/**\n * Projection used by `gridSnapStrategy` when `TPose` doesn't expose `{x,y}`\n * directly (Path, polygon, etc.). The strategy reads the snap point via\n * `getOrigin`, rounds it to the grid, then asks `translate` to move the\n * pose by the resulting delta.\n */\nexport interface OriginProjection<TPose> {\n getOrigin(pose: TPose): { x: number; y: number };\n translate(pose: TPose, dx: number, dy: number): TPose;\n}\n\n/** Identity projection for `TPose extends { x; y }`. */\nexport const RECT_ORIGIN_PROJECTION: OriginProjection<{ x: number; y: number }> = {\n getOrigin: (p) => ({ x: p.x, y: p.y }),\n translate: (p, dx, dy) => ({ ...p, x: p.x + dx, y: p.y + dy }),\n};\n\n/** Per-call dispatch: routes Path-shaped poses to the path origin/translate\n * helpers and everything else to `RECT_ORIGIN_PROJECTION`. Default for\n * `gridSnapStrategy` so consumers with Path TPose don't have to thread\n * `pathOriginProjection` explicitly. */\nexport const AUTO_ORIGIN_PROJECTION: OriginProjection<unknown> = {\n getOrigin: (p) => {\n if (isPathLike(p)) {\n const b = boundsOfPath(p as Path);\n return { x: b.x, y: b.y };\n }\n const r = p as { x: number; y: number };\n return { x: r.x, y: r.y };\n },\n translate: (p, dx, dy) => {\n if (isPathLike(p)) return translatePath(p as Path, dx, dy);\n const r = p as { x: number; y: number };\n return { ...r, x: r.x + dx, y: r.y + dy };\n },\n};\n\n/** Snap-strategy that rounds the pose's origin to the nearest multiple of\n * `spacing` (resolved through `unitSystem`). For non-rect TPose pass an\n * `OriginProjection` so the strategy knows how to read/write the origin. */\nexport function gridSnapStrategy<TPose>(\n spacing: UnitValue,\n unitSystem?: UnitSystem,\n): SnapStrategy<TPose>;\nexport function gridSnapStrategy<TPose>(\n spacing: UnitValue,\n opts: { unitSystem?: UnitSystem; debug?: DebugSink },\n): SnapStrategy<TPose>;\nexport function gridSnapStrategy<TPose>(\n spacing: UnitValue,\n opts: { unitSystem?: UnitSystem; origin: OriginProjection<TPose>; debug?: DebugSink },\n): SnapStrategy<TPose>;\n/** Snap-strategy that rounds the pose's origin to the nearest multiple of\n * `spacing` (resolved through `unitSystem`). For non-rect TPose pass an\n * `OriginProjection` so the strategy knows how to read/write the origin. */\nexport function gridSnapStrategy<TPose>(\n spacing: UnitValue,\n arg?: UnitSystem | { unitSystem?: UnitSystem; origin?: OriginProjection<TPose>; debug?: DebugSink },\n): SnapStrategy<TPose> {\n const isOpts =\n typeof arg === 'object' &&\n arg !== null &&\n ('origin' in arg || 'debug' in arg || 'unitSystem' in arg) &&\n !('base' in arg);\n const optsArg = isOpts\n ? (arg as { unitSystem?: UnitSystem; origin?: OriginProjection<TPose>; debug?: DebugSink })\n : null;\n const unitSystem = optsArg ? optsArg.unitSystem : (arg as UnitSystem | undefined);\n const proj: OriginProjection<TPose> = optsArg && optsArg.origin\n ? optsArg.origin\n : (AUTO_ORIGIN_PROJECTION as unknown as OriginProjection<TPose>);\n const debug: DebugSink | undefined = optsArg ? optsArg.debug : undefined;\n const c = resolveUnit(spacing, unitSystem);\n return {\n snap(pose) {\n const o = proj.getOrigin(pose);\n const sx = Math.round(o.x / c) * c;\n const sy = Math.round(o.y / c) * c;\n debug?.recordSnapCandidate({ x: sx, y: sy }, true);\n return proj.translate(pose, sx - o.x, sy - o.y);\n },\n };\n}\n\n/**\n * Compute the integer cell `{col, row}` that contains `point`, given a grid\n * `spacing` and optional `origin` and `unitSystem`. Pair with\n * `createCellHighlightLayer` (its `getCell` callback) to draw a snap-target\n * preview that uses the same spacing as `gridSnapStrategy` — so the visual\n * and behavioral grids stay in lockstep:\n *\n * const SPACING = 20;\n * const snap = gridSnapStrategy(SPACING);\n * // visual grid:\n * createGridLayer({ spacing: SPACING, bounds: () => ... });\n * // hover-preview overlay:\n * createCellHighlightLayer({\n * spacing: SPACING,\n * getCell: () => hoverPoint && pointToGridCell(hoverPoint, SPACING),\n * });\n */\nexport function pointToGridCell(\n point: { x: number; y: number },\n spacing: UnitValue,\n unitSystem?: UnitSystem,\n origin: { x: number; y: number } = { x: 0, y: 0 },\n): { col: number; row: number } {\n const s = resolveUnit(spacing, unitSystem);\n return {\n col: Math.floor((point.x - origin.x) / s),\n row: Math.floor((point.y - origin.y) / s),\n };\n}\n","/**\n * Geometric mean of a per-axis scale. Used as a scalar fallback for chrome\n * hit-test radii and hairline stroke widths under non-uniform zoom.\n * Degenerates to `s.x` (or `s.y`) when the two axes are equal; otherwise\n * sits between them.\n *\n * Under non-uniform zoom a circular screen-pixel hit region projects to\n * an ellipse in world space (and vice versa). The geometric-mean\n * approximation is intentionally a v1 fallback — proper axis-aware\n * elliptical hit shapes are a future follow-up.\n */\nexport function meanScale(s: { x: number; y: number }): number {\n return Math.sqrt(s.x * s.y);\n}\n","import type { SnapStrategy } from '../../types';\nimport type { Guide } from 'features/guides/types';\nimport type { View } from 'core/viewport/view';\nimport { meanScale } from 'core/viewport/meanScale';\nimport type { OriginProjection } from './grid';\nimport { RECT_ORIGIN_PROJECTION } from './grid';\n\n/** Default snap tolerance (screen pixels). */\nexport const DEFAULT_GUIDE_TOLERANCE_PX = 6;\n\n/** Options for `guideSnapStrategy`. */\nexport interface GuideSnapOptions<TPose> {\n /**\n * Tolerance, in screen pixels (CSS px) when `getView` is provided, or in\n * world units otherwise. Defaults to `DEFAULT_GUIDE_TOLERANCE_PX`.\n */\n tolerance?: number;\n /**\n * Read the active view transform. When supplied, `tolerance` is interpreted\n * in screen pixels and divided by `view.scale` so the trigger zone stays\n * the same on screen as the user zooms in/out. Without it, `tolerance`\n * is treated as world units.\n */\n getView?: () => View;\n /**\n * Projection used when `TPose` doesn't expose `{x, y}` directly (Path,\n * polygon, etc.) — same contract as `gridSnapStrategy`. Defaults to the\n * rect-pose identity projection.\n */\n origin?: OriginProjection<TPose>;\n}\n\n/**\n * Snap-strategy that snaps the pose's origin to the nearest guide line on\n * each axis when within tolerance. Each axis is considered independently:\n * a vertical guide (`axis: 'x'`) constrains X, a horizontal guide\n * (`axis: 'y'`) constrains Y. When multiple guides are within range on the\n * same axis, the closest wins.\n *\n * Pair with `useGuides` for storage and `createGuidesLayer` for rendering.\n *\n * **Composition:** combining with `gridSnapStrategy` is left to the\n * consumer in v1 — typically by picking one based on a modifier key, or\n * by stacking two move/resize/insert behaviors in priority order.\n */\nexport function guideSnapStrategy<TPose extends { x: number; y: number }>(\n getGuides: () => readonly Guide[],\n options?: Omit<GuideSnapOptions<TPose>, 'origin'>,\n): SnapStrategy<TPose>;\nexport function guideSnapStrategy<TPose>(\n getGuides: () => readonly Guide[],\n options: GuideSnapOptions<TPose> & { origin: OriginProjection<TPose> },\n): SnapStrategy<TPose>;\nexport function guideSnapStrategy<TPose>(\n getGuides: () => readonly Guide[],\n options: GuideSnapOptions<TPose> = {},\n): SnapStrategy<TPose> {\n const tolerance = options.tolerance ?? DEFAULT_GUIDE_TOLERANCE_PX;\n const getView = options.getView;\n const proj: OriginProjection<TPose> =\n options.origin ?? (RECT_ORIGIN_PROJECTION as unknown as OriginProjection<TPose>);\n\n return {\n snap(pose) {\n const guides = getGuides();\n if (guides.length === 0) return null;\n\n // Convert tolerance to world units. With no view, treat tolerance as\n // already-world. With a view, divide by scale (px / (px/world) = world).\n const worldTolerance = getView\n ? tolerance / Math.max(1e-9, meanScale(getView().scale))\n : tolerance;\n\n const o = proj.getOrigin(pose);\n\n let bestDx = 0;\n let bestAbsDx = Infinity;\n let bestDy = 0;\n let bestAbsDy = Infinity;\n\n for (const g of guides) {\n if (g.axis === 'x') {\n const d = g.offset - o.x;\n const ad = Math.abs(d);\n if (ad <= worldTolerance && ad < bestAbsDx) {\n bestAbsDx = ad;\n bestDx = d;\n }\n } else {\n const d = g.offset - o.y;\n const ad = Math.abs(d);\n if (ad <= worldTolerance && ad < bestAbsDy) {\n bestAbsDy = ad;\n bestDy = d;\n }\n }\n }\n\n if (bestAbsDx === Infinity && bestAbsDy === Infinity) return null;\n const dx = bestAbsDx === Infinity ? 0 : bestDx;\n const dy = bestAbsDy === Infinity ? 0 : bestDy;\n if (dx === 0 && dy === 0) return null;\n return proj.translate(pose, dx, dy);\n },\n };\n}\n"]}
@@ -0,0 +1,47 @@
1
+ // src/core/ops/registry.ts
2
+ var FACTORIES = /* @__PURE__ */ new Map();
3
+ function registerOpFactory(name, build) {
4
+ FACTORIES.set(name, build);
5
+ }
6
+ function rebuildOp(name, args) {
7
+ const f = FACTORIES.get(name);
8
+ return f ? f(args) : null;
9
+ }
10
+
11
+ // src/core/ops/create.ts
12
+ function createInsertOp(args) {
13
+ const { node, label, index } = args;
14
+ return {
15
+ name: "insert",
16
+ args: { node, label, index },
17
+ label,
18
+ apply(adapter) {
19
+ adapter.insertNode(node, index);
20
+ },
21
+ invert() {
22
+ return createDeleteOp({ node, label, index: index ?? -1 });
23
+ }
24
+ };
25
+ }
26
+ registerOpFactory("insert", (args) => createInsertOp(args));
27
+
28
+ // src/core/ops/delete.ts
29
+ function createDeleteOp(args) {
30
+ const { node, label, index } = args;
31
+ return {
32
+ name: "delete",
33
+ args: { node, label, index },
34
+ label,
35
+ apply(adapter) {
36
+ adapter.removeNode(node.id);
37
+ },
38
+ invert() {
39
+ return createInsertOp({ node, label, index });
40
+ }
41
+ };
42
+ }
43
+ registerOpFactory("delete", (args) => createDeleteOp(args));
44
+
45
+ export { createDeleteOp, createInsertOp, rebuildOp, registerOpFactory };
46
+ //# sourceMappingURL=chunk-GVCNT7UH.js.map
47
+ //# sourceMappingURL=chunk-GVCNT7UH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/ops/registry.ts","../src/core/ops/create.ts","../src/core/ops/delete.ts"],"names":[],"mappings":";AAeA,IAAM,SAAA,uBAAgB,GAAA,EAAqB;AAQpC,SAAS,iBAAA,CAAqB,MAAc,KAAA,EAA8B;AAC/E,EAAA,SAAA,CAAU,GAAA,CAAI,MAAM,KAAgB,CAAA;AACtC;AAKO,SAAS,SAAA,CAAU,MAAc,IAAA,EAA0B;AAChE,EAAA,MAAM,CAAA,GAAI,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA;AAC5B,EAAA,OAAO,CAAA,GAAI,CAAA,CAAE,IAAI,CAAA,GAAI,IAAA;AACvB;;;ACNO,SAAS,eAA6C,IAAA,EAAmC;AAC9F,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAM,GAAI,IAAA;AAC/B,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,QAAA;AAAA,IACN,IAAA,EAAM,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAM;AAAA,IAC3B,KAAA;AAAA,IACA,MAAM,OAAA,EAAS;AACb,MAAC,OAAA,CAAiC,UAAA,CAAW,IAAA,EAAM,KAAK,CAAA;AAAA,IAC1D,CAAA;AAAA,IACA,MAAA,GAAS;AAMP,MAAA,OAAO,eAAe,EAAE,IAAA,EAAM,OAAO,KAAA,EAAO,KAAA,IAAS,IAAI,CAAA;AAAA,IAC3D;AAAA,GACF;AACF;AAEA,iBAAA,CAA8C,QAAA,EAAU,CAAC,IAAA,KAAS,cAAA,CAAe,IAAI,CAAC,CAAA;;;ACzB/E,SAAS,eAA6C,IAAA,EAA6B;AACxF,EAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAM,GAAI,IAAA;AAC/B,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,QAAA;AAAA,IACN,IAAA,EAAM,EAAE,IAAA,EAAM,KAAA,EAAO,KAAA,EAAM;AAAA,IAC3B,KAAA;AAAA,IACA,MAAM,OAAA,EAAS;AACb,MAAC,OAAA,CAA0B,UAAA,CAAW,IAAA,CAAK,EAAE,CAAA;AAAA,IAC/C,CAAA;AAAA,IACA,MAAA,GAAS;AACP,MAAA,OAAO,cAAA,CAAe,EAAE,IAAA,EAAM,KAAA,EAAO,OAAO,CAAA;AAAA,IAC9C;AAAA,GACF;AACF;AAEA,iBAAA,CAA8C,QAAA,EAAU,CAAC,IAAA,KAAS,cAAA,CAAe,IAAI,CAAC,CAAA","file":"chunk-GVCNT7UH.js","sourcesContent":["// Op-factory registry — pairs a stable `name` (stamped onto each op by its\n// factory) with a `(args) => Op` rebuilder so a `{ name, args }` snapshot\n// can be reconstituted into a live `Op` whose `apply`/`invert` closures\n// behave identically to the original.\n//\n// The kit calls `registerOpFactory` at module-init time for every built-in\n// factory (see `./create.ts`, `./delete.ts`, `./transform.ts`, etc.).\n// Consumers wanting their custom ops to survive `History.serialize()` /\n// `History.restore()` register their factories at app bootstrap, before\n// `createHistory` is called.\n\nimport type { Op } from './types';\n\ntype Builder = (args: unknown) => Op;\n\nconst FACTORIES = new Map<string, Builder>();\n\n/** Register an op-factory builder under a stable name. The builder receives\n * the serialized `args` and must return an `Op` equivalent to one freshly\n * constructed at the original call site (`apply` and `invert` behave the\n * same). Idempotent on the same `(name, build)` pair; a second registration\n * with a different builder silently overwrites — kit modules import each\n * factory exactly once at init, so this never races in practice. */\nexport function registerOpFactory<A>(name: string, build: (args: A) => Op): void {\n FACTORIES.set(name, build as Builder);\n}\n\n/** Rebuild an op from its serialized `(name, args)`. Returns `null` when\n * `name` isn't registered — callers handle this (typically by substituting\n * a no-op placeholder so stack ordering survives across kit version skew). */\nexport function rebuildOp(name: string, args: unknown): Op | null {\n const f = FACTORIES.get(name);\n return f ? f(args) : null;\n}\n\n/** Test-only: drop all registrations. Not exported from the kit barrel — the\n * built-in factories self-register at module init, so production code never\n * needs to clear the table. Exposed for unit tests that want to assert the\n * unknown-name fallback path. */\nexport function _clearOpFactoriesForTest(): void {\n FACTORIES.clear();\n}\n\n/** Test-only: read-only snapshot of currently-registered names. */\nexport function _registeredOpNamesForTest(): string[] {\n return [...FACTORIES.keys()];\n}\n","import type { Op } from './types';\nimport { createDeleteOp } from './delete';\nimport { registerOpFactory } from './registry';\n\ninterface InsertAdapter<TNode> {\n /** When `index` is supplied, insert at that position; adapters that ignore\n * the second arg (or don't expose it) fall back to their default\n * placement (typically append-to-end). */\n insertNode(node: TNode, index?: number): void;\n}\n\n/** Type alias for ops produced by `createInsertOp`. Carries no extra type info today;\n * exists so consumers can name the op type when needed. */\nexport type InsertOp = Op;\n\n/** @internal */\ninterface InsertArgs<TNode extends { id: string }> {\n node: TNode;\n label?: string;\n /** Original z-index in the host array. Forwarded to\n * `adapter.insertNode(node, index)` when present so undo of a multi-delete\n * batch restores paint order instead of reversing it. Optional — adapters\n * that don't honor it still work. */\n index?: number;\n}\n\n/** Op: insert `node` into the scene; inverts to a delete of the same id. */\nexport function createInsertOp<TNode extends { id: string }>(args: InsertArgs<TNode>): InsertOp {\n const { node, label, index } = args;\n return {\n name: 'insert',\n args: { node, label, index },\n label,\n apply(adapter) {\n (adapter as InsertAdapter<TNode>).insertNode(node, index);\n },\n invert() {\n // Insert's `index` is optional (fresh-insert callsites have no\n // meaningful original position); the inverted Delete needs *some*\n // index. Default to -1 — the symmetry only matters when the Insert\n // itself was a re-insert from a prior Delete, in which case the\n // index round-trips correctly.\n return createDeleteOp({ node, label, index: index ?? -1 });\n },\n };\n}\n\nregisterOpFactory<InsertArgs<{ id: string }>>('insert', (args) => createInsertOp(args));\n","import type { Op } from './types';\nimport { createInsertOp } from './create';\nimport { registerOpFactory } from './registry';\n\ninterface DeleteAdapter {\n removeNode(id: string): void;\n}\n\n/** @internal */\ninterface DeleteArgs<TNode extends { id: string }> {\n node: TNode;\n label?: string;\n /** Z-index the node occupies in its host array at the moment of delete.\n * Forwarded through `invert()` to the re-insert so undo restores paint\n * order — without this, undo of a multi-delete batch fully reverses\n * the stack. Required: every delete callsite knows where the node sits\n * (it has to, to remove it), so there's no good reason to drop the\n * data on the floor. */\n index: number;\n}\n\n/** Op: remove `node` from the scene; inverts to a re-insert of the captured node. */\nexport function createDeleteOp<TNode extends { id: string }>(args: DeleteArgs<TNode>): Op {\n const { node, label, index } = args;\n return {\n name: 'delete',\n args: { node, label, index },\n label,\n apply(adapter) {\n (adapter as DeleteAdapter).removeNode(node.id);\n },\n invert() {\n return createInsertOp({ node, label, index });\n },\n };\n}\n\nregisterOpFactory<DeleteArgs<{ id: string }>>('delete', (args) => createDeleteOp(args));\n"]}
@@ -0,0 +1,9 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, { get: all[name], enumerable: true });
5
+ };
6
+
7
+ export { __export };
8
+ //# sourceMappingURL=chunk-PZ5AY32C.js.map
9
+ //# sourceMappingURL=chunk-PZ5AY32C.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-PZ5AY32C.js"}
@@ -0,0 +1,28 @@
1
+ import { createSetSelectionOp } from './chunk-BHVYVFGV.js';
2
+ import { createInsertOp } from './chunk-GVCNT7UH.js';
3
+
4
+ // src/interactions/actions/clone/behaviors/cloneByAltDrag.ts
5
+ function cloneByAltDrag() {
6
+ return {
7
+ id: "cloneByAltDrag",
8
+ activates: (mods) => mods.alt === true,
9
+ onEnd(pose, ctx) {
10
+ if (!ctx.adapter.snapshotSelection || !ctx.adapter.commitPaste) return [];
11
+ const snap = ctx.adapter.snapshotSelection(pose.ids);
12
+ const created = ctx.adapter.commitPaste(snap, pose.offset, {
13
+ dropPoint: { worldX: pose.worldX, worldY: pose.worldY }
14
+ });
15
+ if (created.length === 0) return [];
16
+ const newIds = created.map((o) => o.id);
17
+ const from = ctx.adapter.getSelection?.() ?? [];
18
+ return [
19
+ ...created.map((o) => createInsertOp({ node: o })),
20
+ createSetSelectionOp({ from, to: newIds })
21
+ ];
22
+ }
23
+ };
24
+ }
25
+
26
+ export { cloneByAltDrag };
27
+ //# sourceMappingURL=chunk-UGFFCMQP.js.map
28
+ //# sourceMappingURL=chunk-UGFFCMQP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/interactions/actions/clone/behaviors/cloneByAltDrag.ts"],"names":[],"mappings":";;;;AAMO,SAAS,cAAA,GAAgC;AAC9C,EAAA,OAAO;AAAA,IACL,EAAA,EAAI,gBAAA;AAAA,IACJ,SAAA,EAAW,CAAC,IAAA,KAAS,IAAA,CAAK,GAAA,KAAQ,IAAA;AAAA,IAClC,KAAA,CAAM,MAAM,GAAA,EAAK;AACf,MAAA,IAAI,CAAC,IAAI,OAAA,CAAQ,iBAAA,IAAqB,CAAC,GAAA,CAAI,OAAA,CAAQ,WAAA,EAAa,OAAO,EAAC;AACxE,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,OAAA,CAAQ,iBAAA,CAAkB,KAAK,GAAG,CAAA;AACnD,MAAA,MAAM,UAAU,GAAA,CAAI,OAAA,CAAQ,WAAA,CAAY,IAAA,EAAM,KAAK,MAAA,EAAQ;AAAA,QACzD,WAAW,EAAE,MAAA,EAAQ,KAAK,MAAA,EAAQ,MAAA,EAAQ,KAAK,MAAA;AAAO,OACvD,CAAA;AACD,MAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,EAAC;AAClC,MAAA,MAAM,SAAS,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAsB,EAAE,EAAE,CAAA;AACtD,MAAA,MAAM,IAAA,GAAO,GAAA,CAAI,OAAA,CAAQ,YAAA,QAAoB,EAAC;AAC9C,MAAA,OAAO;AAAA,QACL,GAAG,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,eAAe,EAAE,IAAA,EAAM,CAAA,EAAG,CAAC,CAAA;AAAA,QACjD,oBAAA,CAAqB,EAAE,IAAA,EAAwB,EAAA,EAAI,QAAoB;AAAA,OACzE;AAAA,IACF;AAAA,GACF;AACF","file":"chunk-UGFFCMQP.js","sourcesContent":["import { createInsertOp } from 'core/ops/create';\nimport { createSetSelectionOp } from 'core/ops/select';\nimport type { NodeId } from 'core/scene/types';\nimport type { CloneBehavior } from '../../../gestures/types';\n\n/** Clone-on-alt-drag behavior for `useClone`; activates when Alt/Option is held at drag start. */\nexport function cloneByAltDrag(): CloneBehavior {\n return {\n id: 'cloneByAltDrag',\n activates: (mods) => mods.alt === true,\n onEnd(pose, ctx) {\n if (!ctx.adapter.snapshotSelection || !ctx.adapter.commitPaste) return [];\n const snap = ctx.adapter.snapshotSelection(pose.ids);\n const created = ctx.adapter.commitPaste(snap, pose.offset, {\n dropPoint: { worldX: pose.worldX, worldY: pose.worldY },\n });\n if (created.length === 0) return [];\n const newIds = created.map((o: { id: string }) => o.id);\n const from = ctx.adapter.getSelection?.() ?? [];\n return [\n ...created.map((o) => createInsertOp({ node: o })),\n createSetSelectionOp({ from: from as NodeId[], to: newIds as NodeId[] }),\n ];\n },\n };\n}\n"]}
@@ -0,0 +1,103 @@
1
+ import { RECT_ORIGIN_PROJECTION } from './chunk-CQNKCG34.js';
2
+ import { registerOpFactory } from './chunk-GVCNT7UH.js';
3
+
4
+ // src/core/ops/transform.ts
5
+ function createTransformOp(args) {
6
+ const { id, from, to, label, coalesceKey = `transform:${id}` } = args;
7
+ return {
8
+ name: "transform",
9
+ args: { id, from, to, label, coalesceKey },
10
+ label,
11
+ coalesceKey,
12
+ apply(adapter) {
13
+ adapter.setPose(id, to);
14
+ if (poseShallowEqual(from, to)) return false;
15
+ return void 0;
16
+ },
17
+ invert() {
18
+ return createTransformOp({ id, from: to, to: from, label, coalesceKey });
19
+ }
20
+ };
21
+ }
22
+ registerOpFactory("transform", (args) => createTransformOp(args));
23
+ function poseShallowEqual(a, b) {
24
+ if (a === b) return true;
25
+ if (a === null || b === null || typeof a !== "object" || typeof b !== "object") return false;
26
+ const ka = Object.keys(a);
27
+ const kb = Object.keys(b);
28
+ if (ka.length !== kb.length) return false;
29
+ for (const k of ka) {
30
+ if (a[k] !== b[k]) return false;
31
+ }
32
+ return true;
33
+ }
34
+
35
+ // src/core/ops/reparent.ts
36
+ function createReparentOp(args) {
37
+ const { id, fromParentId, toParentId, label = "Reparent", coalesceKey = `reparent:${id}` } = args;
38
+ return {
39
+ name: "reparent",
40
+ args: { id, fromParentId, toParentId, label, coalesceKey },
41
+ label,
42
+ coalesceKey,
43
+ apply(adapter) {
44
+ adapter.setParent(id, toParentId);
45
+ },
46
+ invert() {
47
+ return createReparentOp({
48
+ id,
49
+ fromParentId: toParentId,
50
+ toParentId: fromParentId,
51
+ label,
52
+ coalesceKey
53
+ });
54
+ }
55
+ };
56
+ }
57
+ registerOpFactory("reparent", (args) => createReparentOp(args));
58
+
59
+ // src/interactions/scratchKey.ts
60
+ function scratchKey(name) {
61
+ return { name };
62
+ }
63
+ function getScratch(store, key) {
64
+ return store[key.name];
65
+ }
66
+ function setScratch(store, key, value) {
67
+ store[key.name] = value;
68
+ }
69
+ function deleteScratch(store, key) {
70
+ if (Object.prototype.hasOwnProperty.call(store, key.name)) {
71
+ delete store[key.name];
72
+ return true;
73
+ }
74
+ return false;
75
+ }
76
+
77
+ // src/interactions/gestures/shared/snap.ts
78
+ function snap(strategy, opts = {}) {
79
+ const { bypassKey } = opts;
80
+ const proj = opts.origin ?? RECT_ORIGIN_PROJECTION;
81
+ return {
82
+ onMove(ctx, transform) {
83
+ if (bypassKey && ctx.modifiers[bypassKey]) return;
84
+ if (transform.kind !== "translate") return;
85
+ const primaryId = ctx.draggedIds[0];
86
+ if (primaryId === void 0) return;
87
+ const originPose = ctx.origin.get(primaryId);
88
+ if (originPose === void 0) return;
89
+ const proposed = proj.translate(originPose, transform.dx, transform.dy);
90
+ const snapped = strategy.snap(proposed, ctx);
91
+ if (snapped === null) return;
92
+ const o0 = proj.getOrigin(originPose);
93
+ const o1 = proj.getOrigin(snapped);
94
+ return {
95
+ transform: { kind: "translate", dx: o1.x - o0.x, dy: o1.y - o0.y }
96
+ };
97
+ }
98
+ };
99
+ }
100
+
101
+ export { createReparentOp, createTransformOp, deleteScratch, getScratch, scratchKey, setScratch, snap };
102
+ //# sourceMappingURL=chunk-VOVKONXA.js.map
103
+ //# sourceMappingURL=chunk-VOVKONXA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/ops/transform.ts","../src/core/ops/reparent.ts","../src/interactions/scratchKey.ts","../src/interactions/gestures/shared/snap.ts"],"names":[],"mappings":"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","file":"chunk-VOVKONXA.js","sourcesContent":["import type { Op } from './types';\nimport { registerOpFactory } from './registry';\n\ninterface TransformAdapter<TPose> {\n setPose(id: string, pose: TPose): void;\n}\n\n/** @internal */\ninterface TransformArgs<TPose> {\n id: string;\n from: TPose;\n to: TPose;\n label?: string;\n coalesceKey?: string;\n}\n\n/** Op: set an object's pose, inverting back to `from`. `coalesceKey` defaults to\n * `transform:${id}` so successive pose writes to the same node (drag-move,\n * resize, repeated nudges) merge into one undo entry within the history's\n * coalesce window. Pass an explicit key (or a unique one) to opt out. */\nexport function createTransformOp<TPose>(args: TransformArgs<TPose>): Op {\n const { id, from, to, label, coalesceKey = `transform:${id}` } = args;\n return {\n name: 'transform',\n args: { id, from, to, label, coalesceKey },\n label,\n coalesceKey,\n apply(adapter) {\n // Always call setPose so consumers that inspect op behavior (tests,\n // overlays) see a consistent \"this op writes (id, to)\" signal. When\n // from and to are structurally identical, additionally report a\n // no-op to history so the entry can be skipped from the undo stack.\n // setPose(id, to) is idempotent in this branch — adapters write the\n // same pose they already had.\n (adapter as TransformAdapter<TPose>).setPose(id, to);\n if (poseShallowEqual(from, to)) return false;\n return undefined;\n },\n invert() {\n return createTransformOp<TPose>({ id, from: to, to: from, label, coalesceKey });\n },\n };\n}\n\nregisterOpFactory<TransformArgs<unknown>>('transform', (args) => createTransformOp(args));\n\nfunction poseShallowEqual<TPose>(a: TPose, b: TPose): boolean {\n if (a === b) return true;\n if (a === null || b === null || typeof a !== 'object' || typeof b !== 'object') return false;\n const ka = Object.keys(a as object);\n const kb = Object.keys(b as object);\n if (ka.length !== kb.length) return false;\n for (const k of ka) {\n if ((a as Record<string, unknown>)[k] !== (b as Record<string, unknown>)[k]) return false;\n }\n return true;\n}\n","import type { Op } from './types';\nimport { registerOpFactory } from './registry';\n\ninterface ReparentAdapter {\n setParent(id: string, parentId: string | null): void;\n}\n\n/** @internal */\ninterface ReparentArgs {\n id: string;\n fromParentId: string | null;\n toParentId: string | null;\n label?: string;\n coalesceKey?: string;\n}\n\n/**\n * Op: change `id`'s parent, inverting back to the prior parent.\n *\n * `coalesceKey` defaults to `reparent:${id}` so successive reparents of the\n * same id batch-merge cleanly.\n */\nexport function createReparentOp(args: ReparentArgs): Op {\n const { id, fromParentId, toParentId, label = 'Reparent', coalesceKey = `reparent:${id}` } = args;\n return {\n name: 'reparent',\n args: { id, fromParentId, toParentId, label, coalesceKey },\n label,\n coalesceKey,\n apply(adapter) {\n (adapter as ReparentAdapter).setParent(id, toParentId);\n },\n invert() {\n return createReparentOp({\n id,\n fromParentId: toParentId,\n toParentId: fromParentId,\n label,\n coalesceKey,\n });\n },\n };\n}\n\nregisterOpFactory<ReparentArgs>('reparent', (args) => createReparentOp(args));\n","/**\n * Typed keys for the gesture/behavior scratch store.\n *\n * Gestures expose `ctx.scratch: Record<string, unknown>` as a per-gesture\n * mutable bag that behaviors use to stash state across `onDown` / `onMove`\n * / `onEnd` calls. The store is `unknown`-valued because behaviors are\n * tool-agnostic — a single behavior may run under different tools with\n * different scratch shapes. Without a typing convention every read site\n * has to `(ctx.scratch as <some shape>)[KEY]`, and a writer changing the\n * shape can silently break readers with no compile-time signal.\n *\n * `ScratchKey<T>` is a phantom-typed string that carries its payload type\n * via a branded interface. `getScratch` and `setScratch` use the brand to\n * narrow / constrain at the typing layer; at runtime the key is just its\n * underlying string and the store remains a plain `Record`.\n *\n * @example\n * ```ts\n * // Module-level (or behavior-level) constant, shared by writer + reader:\n * const LASSO_VERTICES = scratchKey<readonly { x: number; y: number }[]>('lasso.vertices');\n *\n * // Writer (a tool's onMove):\n * setScratch(ctx.scratch, LASSO_VERTICES, vertices);\n *\n * // Reader (a behavior's onEnd):\n * const vertices = getScratch(ctx.scratch, LASSO_VERTICES) ?? [];\n * // ^? readonly { x: number; y: number }[] | undefined\n * ```\n */\n\n/** Phantom-typed key for a scratch slot. The `__scratchKeyPayload` phantom\n * field carries the value type without occupying any runtime memory. */\nexport interface ScratchKey<T> {\n readonly name: string;\n /** Phantom — never read at runtime. Only present so TypeScript can\n * recover `T` at use sites. */\n readonly __scratchKeyPayload?: (_: T) => T;\n}\n\n/** Compatible scratch store shape. The kit's gesture context's `scratch`\n * field already satisfies this; consumers don't need to construct one. */\nexport type ScratchStore = Record<string, unknown>;\n\n/**\n * Make a typed scratch key. Use module-level constants so the same key\n * is shared by writer and reader.\n *\n * Namespace the name by behavior or feature to avoid collisions\n * (`'behavior.field'` is a good convention). Two keys with the same\n * `name` refer to the same slot at runtime — the type parameter is a\n * compile-time contract, not a uniqueness guarantee.\n */\nexport function scratchKey<T>(name: string): ScratchKey<T> {\n return { name };\n}\n\n/** Read a typed slot from the scratch store. Returns `undefined` if\n * nothing has been written under the key. */\nexport function getScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n): T | undefined {\n return store[key.name] as T | undefined;\n}\n\n/** Write a value to a typed slot. Overwrites whatever was there. */\nexport function setScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n value: T,\n): void {\n store[key.name] = value;\n}\n\n/** Remove a slot from the scratch store. Returns `true` if it was set,\n * `false` if it wasn't. */\nexport function deleteScratch<T>(\n store: ScratchStore,\n key: ScratchKey<T>,\n): boolean {\n if (Object.prototype.hasOwnProperty.call(store, key.name)) {\n delete store[key.name];\n return true;\n }\n return false;\n}\n","import type { MoveBehavior, ModifierState, SnapStrategy } from '../types';\nimport {\n RECT_ORIGIN_PROJECTION,\n type OriginProjection,\n} from './strategies/grid';\n\ntype ModKey = keyof ModifierState;\n\n/**\n * Generic snap behavior factory: wraps a `SnapStrategy` and returns a\n * `MoveBehavior` whose `onMove` returns a uniform `GroupTransform`.\n *\n * Implementation:\n * 1. Compute the primary's proposed pose by applying the gesture's\n * `transform` (translate) to `origin.get(primaryId)`.\n * 2. Call `strategy.snap(proposed)`. If null, no-op.\n * 3. Derive the snapped delta via the `OriginProjection`:\n * dx = origin(snapped).x - origin(originPose).x\n * ...so the gesture applies the same delta to every dragged id.\n *\n * The pose-shape-aware delta extraction lives here — gestures stay pose-shape\n * agnostic. Default projection is `{x, y}`-bearing (rect / path / polygon).\n * Pass `origin` for exotic poses.\n */\nexport function snap<TPose>(\n strategy: SnapStrategy<TPose>,\n opts: { bypassKey?: ModKey; origin?: OriginProjection<TPose> } = {},\n): MoveBehavior<TPose> {\n const { bypassKey } = opts;\n const proj: OriginProjection<TPose> = opts.origin\n ?? (RECT_ORIGIN_PROJECTION as unknown as OriginProjection<TPose>);\n return {\n onMove(ctx, transform) {\n if (bypassKey && ctx.modifiers[bypassKey]) return;\n // The new contract: behaviors see a GroupTransform, not a pose. But\n // strategies still operate on poses. Reconstruct the proposed pose\n // by applying the (translate) transform to the primary's origin.\n if (transform.kind !== 'translate') return;\n const primaryId = ctx.draggedIds[0];\n if (primaryId === undefined) return;\n const originPose = ctx.origin.get(primaryId);\n if (originPose === undefined) return;\n const proposed = proj.translate(originPose, transform.dx, transform.dy);\n const snapped = strategy.snap(proposed, ctx);\n if (snapped === null) return;\n const o0 = proj.getOrigin(originPose);\n const o1 = proj.getOrigin(snapped);\n return {\n transform: { kind: 'translate', dx: o1.x - o0.x, dy: o1.y - o0.y },\n };\n },\n };\n}\n"]}
@@ -0,0 +1,39 @@
1
+ // src/renderer/textures/registerTexture.ts
2
+ var counter = 0;
3
+ var registry = /* @__PURE__ */ new Map();
4
+ function getTexture(id) {
5
+ return registry.get(id) ?? null;
6
+ }
7
+ function registerTexture(image) {
8
+ const id = `tex_${++counter}`;
9
+ registry.set(id, { source: image });
10
+ return { id };
11
+ }
12
+
13
+ // src/features/patterns/index.ts
14
+ function createTilePattern(opts) {
15
+ let off;
16
+ try {
17
+ off = new OffscreenCanvas(opts.size, opts.size);
18
+ } catch {
19
+ if (typeof document === "undefined") return null;
20
+ const c = document.createElement("canvas");
21
+ c.width = opts.size;
22
+ c.height = opts.size;
23
+ off = c;
24
+ }
25
+ const oc = off.getContext("2d");
26
+ if (!oc) return null;
27
+ opts.draw(oc, opts.size);
28
+ let bitmap;
29
+ if (typeof off.transferToImageBitmap === "function") {
30
+ bitmap = off.transferToImageBitmap();
31
+ } else {
32
+ return null;
33
+ }
34
+ return registerTexture(bitmap);
35
+ }
36
+
37
+ export { createTilePattern, getTexture, registerTexture };
38
+ //# sourceMappingURL=chunk-Y52N27PF.js.map
39
+ //# sourceMappingURL=chunk-Y52N27PF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/renderer/textures/registerTexture.ts","../src/features/patterns/index.ts"],"names":[],"mappings":";AAmBA,IAAI,OAAA,GAAU,CAAA;AACd,IAAI,QAAA,uBAAe,GAAA,EAA0B;AAQtC,SAAS,WAAW,EAAA,EAAiC;AAC1D,EAAA,OAAO,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA,IAAK,IAAA;AAC7B;AAWO,SAAS,gBACd,KAAA,EACe;AACf,EAAA,MAAM,EAAA,GAAK,CAAA,IAAA,EAAO,EAAE,OAAO,CAAA,CAAA;AAC3B,EAAA,QAAA,CAAS,GAAA,CAAI,EAAA,EAAI,EAAE,MAAA,EAAQ,OAAO,CAAA;AAClC,EAAA,OAAO,EAAE,EAAA,EAAG;AACd;;;ACfO,SAAS,kBAAkB,IAAA,EAA6C;AAG7E,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI;AACF,IAAA,GAAA,GAAM,IAAI,eAAA,CAAgB,IAAA,CAAK,IAAA,EAAM,KAAK,IAAI,CAAA;AAAA,EAChD,CAAA,CAAA,MAAQ;AACN,IAAA,IAAI,OAAO,QAAA,KAAa,WAAA,EAAa,OAAO,IAAA;AAC5C,IAAA,MAAM,CAAA,GAAI,QAAA,CAAS,aAAA,CAAc,QAAQ,CAAA;AACzC,IAAA,CAAA,CAAE,QAAQ,IAAA,CAAK,IAAA;AACf,IAAA,CAAA,CAAE,SAAS,IAAA,CAAK,IAAA;AAChB,IAAA,GAAA,GAAM,CAAA;AAAA,EACR;AACA,EAAA,MAAM,EAAA,GAAK,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA;AAC9B,EAAA,IAAI,CAAC,IAAI,OAAO,IAAA;AAChB,EAAA,IAAA,CAAK,IAAA,CAAK,EAAA,EAAI,IAAA,CAAK,IAAI,CAAA;AAMvB,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,OAAQ,GAAA,CAAwB,qBAAA,KAA0B,UAAA,EAAY;AACxE,IAAA,MAAA,GAAU,IAAwB,qBAAA,EAAsB;AAAA,EAC1D,CAAA,MAAO;AACL,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,gBAAgB,MAAM,CAAA;AAC/B","file":"chunk-Y52N27PF.js","sourcesContent":["/**\n * registerTexture — accepts an image source, assigns an opaque id, stores in\n * a module-level registry. Actual GL upload happens lazily at draw time in\n * drawShader() via GLTextureCache.upload (which is idempotent).\n *\n * Lifecycle: textures live for the renderer's lifetime. No unregister in v1.\n *\n * Convention §9: this registry stores image data only — no per-renderer state.\n * Each WeaselRenderer's GLTextureCache does its own dedup via has(id).\n */\n\nexport interface TextureHandle {\n readonly id: string;\n}\n\nexport interface TextureEntry {\n source: HTMLImageElement | ImageBitmap;\n}\n\nlet counter = 0;\nlet registry = new Map<string, TextureEntry>();\n\n/** @internal Test helper — do not call from product code. */\nexport function _resetTextureRegistryForTests(): void {\n registry = new Map();\n counter = 0;\n}\n\nexport function getTexture(id: string): TextureEntry | null {\n return registry.get(id) ?? null;\n}\n\n/**\n * Register an image for use as a shader texture uniform.\n *\n * Returns a TextureHandle whose `id` can be passed as a ShaderUniform value.\n * The handle is valid for the lifetime of the renderer it will be used with.\n *\n * @param image The image to register. HTMLImageElement must be fully loaded.\n * @returns Opaque TextureHandle.\n */\nexport function registerTexture(\n image: HTMLImageElement | ImageBitmap,\n): TextureHandle {\n const id = `tex_${++counter}`;\n registry.set(id, { source: image });\n return { id };\n}\n","/**\n * Tile-pattern primitive — a small helper for building repeating texture\n * tiles from a draw callback. The result plugs into a `FillStyle` of\n * `{ fill: 'pattern', pattern }` (see `../../core/paint-types.ts`).\n *\n * GL-backed: the tile is rendered to an `OffscreenCanvas` (with a 2D fallback\n * to a regular `<canvas>` for environments without `OffscreenCanvas`),\n * converted to an `ImageBitmap`, and registered with `registerTexture()`.\n * The returned `TextureHandle` is what `FillStyle.pattern` accepts.\n *\n * For ready-to-use named patterns (hatch, crosshatch, dots, chunks),\n * see the `@weasel-js/core/patterns-builtin` subpath.\n */\n\nimport { registerTexture } from '../../renderer/textures/registerTexture';\nimport type { TextureHandle } from '../../renderer/textures/registerTexture';\n\n/** Options for `createTilePattern`. */\nexport interface TilePatternOpts {\n /** Edge length (in pixels) of the square offscreen tile. */\n size: number;\n /** FillStyle one tile at integer-pixel coordinates `(0, 0) .. (size, size)`. */\n draw: (oc: CanvasRenderingContext2D, size: number) => void;\n}\n\n/**\n * Render a single tile to an offscreen canvas and register it as a GL\n * texture, returning a `TextureHandle` you can wrap in a `FillStyle` of\n * `{ fill: 'pattern', pattern }`. Returns `null` only when an\n * `OffscreenCanvas`/2D context can't be acquired (very rare; same fallback\n * semantics as the prior `CanvasPattern`-based implementation).\n */\nexport function createTilePattern(opts: TilePatternOpts): TextureHandle | null {\n // Prefer OffscreenCanvas; fall back to <canvas> for environments without it\n // (tests in jsdom may need that fallback — try OffscreenCanvas first).\n let off: OffscreenCanvas | HTMLCanvasElement;\n try {\n off = new OffscreenCanvas(opts.size, opts.size);\n } catch {\n if (typeof document === 'undefined') return null;\n const c = document.createElement('canvas');\n c.width = opts.size;\n c.height = opts.size;\n off = c;\n }\n const oc = off.getContext('2d') as CanvasRenderingContext2D | null;\n if (!oc) return null;\n opts.draw(oc, opts.size);\n\n // Convert to ImageBitmap so registerTexture can store it.\n // OffscreenCanvas.transferToImageBitmap() is the fast path; the\n // synchronous path requires OffscreenCanvas. If we got here without it,\n // the env doesn't support OffscreenCanvas — fail gracefully.\n let bitmap: ImageBitmap;\n if (typeof (off as OffscreenCanvas).transferToImageBitmap === 'function') {\n bitmap = (off as OffscreenCanvas).transferToImageBitmap();\n } else {\n return null;\n }\n return registerTexture(bitmap);\n}\n"]}