@sarmal/core 0.9.10 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auto-init.cjs +80 -17
- package/dist/auto-init.cjs.map +1 -1
- package/dist/auto-init.js +80 -17
- package/dist/auto-init.js.map +1 -1
- package/dist/curves/artemis2.d.cts +1 -1
- package/dist/curves/artemis2.d.ts +1 -1
- package/dist/curves/astroid.d.cts +1 -1
- package/dist/curves/astroid.d.ts +1 -1
- package/dist/curves/deltoid.d.cts +1 -1
- package/dist/curves/deltoid.d.ts +1 -1
- package/dist/curves/epicycloid3.d.cts +1 -1
- package/dist/curves/epicycloid3.d.ts +1 -1
- package/dist/curves/epitrochoid7.d.cts +1 -1
- package/dist/curves/epitrochoid7.d.ts +1 -1
- package/dist/curves/index.cjs.map +1 -1
- package/dist/curves/index.d.cts +15 -3
- package/dist/curves/index.d.ts +15 -3
- package/dist/curves/index.js.map +1 -1
- package/dist/curves/lame.d.cts +1 -1
- package/dist/curves/lame.d.ts +1 -1
- package/dist/curves/lissajous32.d.cts +1 -1
- package/dist/curves/lissajous32.d.ts +1 -1
- package/dist/curves/lissajous43.d.cts +1 -1
- package/dist/curves/lissajous43.d.ts +1 -1
- package/dist/curves/rose3.d.cts +1 -1
- package/dist/curves/rose3.d.ts +1 -1
- package/dist/curves/rose5.d.cts +1 -1
- package/dist/curves/rose5.d.ts +1 -1
- package/dist/index.cjs +87 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +87 -27
- package/dist/index.js.map +1 -1
- package/dist/{types-cR2xOewv.d.cts → types-BzgdhxE0.d.cts} +72 -35
- package/dist/{types-cR2xOewv.d.ts → types-BzgdhxE0.d.ts} +72 -35
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/engine.ts","../src/renderer-shared.ts","../src/renderer.ts","../src/renderer-svg.ts","../src/curves/artemis2.ts","../src/curves/astroid.ts","../src/curves/deltoid.ts","../src/curves/epicycloid3.ts","../src/curves/epitrochoid7.ts","../src/curves/lissajous32.ts","../src/curves/lissajous43.ts","../src/curves/lame.ts","../src/curves/rose3.ts","../src/curves/rose5.ts","../src/curves/index.ts","../src/index.ts"],"names":["dx","dy","len","options","EMPTY_PARAMS","skeleton","TWO_PI"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n CurveDef,\n Engine,\n MorpStrategy,\n Point,\n SeekOptions,\n SeekWithTrailOptions,\n} from \"./types\";\n\nconst TWO_PI = Math.PI * 2;\nconst POINTS_PER_PERIOD_UNIT = 50;\n\n/** Linearly interpolate from start to end by factor t (0→1) */\nfunction lerp(start: number, end: number, t: number): number {\n return start + (end - start) * t;\n}\n\n/** Reused across all curve fn calls — params is never populated, allocation is wasteful */\nconst EMPTY_PARAMS: Record<string, number> = {};\n\n/**\n * A fixed-size list of points with first in, last out method\n * The oldest entry is automatically discarded when the list is at capacity\n *\n * Note: `result.length` is *never* changed,\n * so callers use the separate `count` getter to know valid size\n */\nclass CircularBuffer {\n private data: Array<Point>;\n private result: Array<Point>;\n private capacity: number;\n private head: number = 0;\n private count: number = 0;\n\n constructor(capacity: number) {\n this.capacity = capacity;\n this.data = Array.from({ length: capacity }, () => ({ x: 0, y: 0 }));\n this.result = Array.from({ length: capacity }, () => ({ x: 0, y: 0 }));\n }\n\n /** Mutates in-place */\n push(x: number, y: number): void {\n const slot = this.data[this.head]!;\n\n slot.x = x;\n slot.y = y;\n this.head = (this.head + 1) % this.capacity;\n\n if (this.count < this.capacity) {\n this.count++;\n }\n }\n\n /**\n * Copies ordered points into the pre-allocated result buffer and returns it\n * Note: The *same* array reference is returned every call,\n * so `result.length` is also always `capacity`\n */\n toArray(): Array<Point> {\n const start = this.count < this.capacity ? 0 : this.head;\n\n for (let i = 0; i < this.count; i++) {\n const src = this.data[(start + i) % this.capacity]!;\n const dst = this.result[i]!;\n dst.x = src.x;\n dst.y = src.y;\n }\n\n return this.result;\n }\n\n clear(): void {\n this.head = 0;\n this.count = 0;\n }\n\n get length() {\n return this.count;\n }\n}\n\n/**\n * Creates the core simulation engine for a sarmal\n *\n * it runs a clock (time `t`), asks the curve for the current Point position at that time,\n * and remembers the last N positions so the renderer can draw the trail\n *\n * The engine is only responsible for math coordinates,\n * so it is not responsible for drawing or colors\n *\n * @param curveDef A curve definition\n * @param trailLength default: `120`\n */\n/** Normalised resolution of a CurveDef, with required fields filled in */\ntype ResolvedCurve = {\n name: string;\n fn: CurveDef[\"fn\"];\n period: number;\n speed: number;\n skeleton?: CurveDef[\"skeleton\"];\n skeletonFn?: CurveDef[\"skeletonFn\"];\n};\n\nfunction resolveCurve(curveDef: CurveDef): ResolvedCurve {\n const period = curveDef.period ?? TWO_PI;\n\n if (!Number.isFinite(period) || period <= 0) {\n throw new RangeError(`[sarmal] period must be a positive finite number, got ${period}`);\n }\n\n const speed = curveDef.speed ?? 1;\n\n if (!Number.isFinite(speed)) {\n throw new RangeError(`[sarmal] speed must be a finite number, got ${speed}`);\n }\n\n return {\n name: curveDef.name,\n fn: curveDef.fn,\n period,\n speed,\n skeleton: curveDef.skeleton,\n skeletonFn: curveDef.skeletonFn,\n };\n}\n\nexport function createEngine(curveDef: CurveDef, trailLength: number = 120): Engine {\n if (!Number.isFinite(trailLength) || trailLength <= 0) {\n throw new RangeError(\n `[sarmal] trailLength must be a positive finite number, got ${trailLength}`,\n );\n }\n\n let curve = resolveCurve(curveDef);\n const trail = new CircularBuffer(trailLength);\n let t = 0;\n let actualTime = 0;\n\n // Morph state which is `null` when not morphing\n let morphCurveB: ResolvedCurve | null = null;\n let _morphAlpha: number | null = null;\n let _morphStrategy: MorpStrategy = \"normalized\";\n\n /** Samples a resolved curve's skeleton at position `sampleT` */\n function sampleSkeleton(c: ResolvedCurve, sampleT: number): Point {\n if (c.skeletonFn) {\n return c.skeletonFn(sampleT);\n }\n if (c.skeleton === \"live\") {\n return c.fn(sampleT, actualTime, EMPTY_PARAMS);\n }\n return c.fn(sampleT, 0, EMPTY_PARAMS);\n }\n\n return {\n tick(deltaTime: number): Array<Point> {\n let effectiveSpeed = curve.speed;\n if (morphCurveB !== null && _morphAlpha !== null) {\n effectiveSpeed = lerp(curve.speed, morphCurveB.speed, _morphAlpha);\n }\n t = (t + effectiveSpeed * deltaTime) % curve.period;\n actualTime += deltaTime;\n\n if (morphCurveB !== null && _morphAlpha !== null) {\n const a = curve.fn(t, actualTime, EMPTY_PARAMS);\n const tB = _morphStrategy === \"normalized\" ? (t / curve.period) * morphCurveB.period : t;\n const b = morphCurveB.fn(tB, actualTime, EMPTY_PARAMS);\n trail.push(a.x + (b.x - a.x) * _morphAlpha, a.y + (b.y - a.y) * _morphAlpha);\n } else {\n const point = curve.fn(t, actualTime, EMPTY_PARAMS);\n trail.push(point.x, point.y);\n }\n\n return trail.toArray();\n },\n\n get trailCount() {\n return trail.length;\n },\n\n get isLiveSkeleton() {\n return curve.skeleton === \"live\";\n },\n\n get morphAlpha() {\n return _morphAlpha;\n },\n\n reset() {\n t = 0;\n actualTime = 0;\n trail.clear();\n },\n\n seek(newT: number, { clearTrail = false }: SeekOptions = {}) {\n t = ((newT % curve.period) + curve.period) % curve.period;\n if (clearTrail) {\n trail.clear();\n }\n },\n\n seekWithTrail(\n targetT: number,\n { wrap = false, step = curve.period / trailLength }: SeekWithTrailOptions = {},\n ) {\n const advance = curve.speed * step;\n const target = ((targetT % curve.period) + curve.period) % curve.period;\n const targetTime = target / curve.speed;\n\n t = target;\n actualTime = targetTime;\n trail.clear();\n\n const pointsFromStart = Math.floor(target / advance) + 1;\n const count = wrap ? trailLength : Math.min(trailLength, pointsFromStart);\n\n for (let i = count - 1; i >= 0; i--) {\n const sampleT = target - i * advance;\n const wrappedT = ((sampleT % curve.period) + curve.period) % curve.period;\n const time = targetTime - i * step;\n const point = curve.fn(wrappedT, time, EMPTY_PARAMS);\n\n trail.push(point.x, point.y);\n }\n },\n\n startMorph(target: CurveDef, strategy: MorpStrategy = \"normalized\") {\n const resolvedTarget = resolveCurve(target);\n\n if (morphCurveB !== null && _morphAlpha !== null) {\n const frozenAlpha = _morphAlpha;\n const frozenA = curve;\n const frozenB = morphCurveB;\n const frozenStrategy = _morphStrategy;\n\n curve = {\n ...frozenB,\n fn: (sampleT: number, time: number, params: Record<string, number>) => {\n const a = frozenA.fn(sampleT, time, params);\n const tB =\n frozenStrategy === \"normalized\"\n ? (sampleT / frozenA.period) * frozenB.period\n : sampleT;\n const b = frozenB.fn(tB, time, params);\n return {\n x: a.x + (b.x - a.x) * frozenAlpha,\n y: a.y + (b.y - a.y) * frozenAlpha,\n };\n },\n };\n }\n\n _morphStrategy = strategy;\n morphCurveB = resolvedTarget;\n _morphAlpha = 0;\n },\n\n setMorphAlpha(alpha: number) {\n _morphAlpha = alpha;\n },\n\n completeMorph() {\n if (morphCurveB !== null) {\n // Normalized strategy drives `curveB` at `tB` = `(t / periodA) * periodB`\n // Remap `t` so the trail continues from the same position on `curveB`,\n // not from a raw `t` value that belongs to `curveA`'s smaller range.\n if (_morphStrategy === \"normalized\" && curve.period !== morphCurveB.period) {\n t = (t / curve.period) * morphCurveB.period;\n }\n curve = morphCurveB;\n }\n morphCurveB = null;\n _morphAlpha = null;\n },\n\n getSarmalSkeleton(): Array<Point> {\n const steps = Math.ceil(curve.period * POINTS_PER_PERIOD_UNIT);\n // oxlint-disable-next-line unicorn/no-new-array -- array is pre-allocated, filled immediately below\n const points: Array<Point> = new Array(steps);\n\n if (morphCurveB !== null && _morphAlpha !== null) {\n for (let i = 0; i < steps; i++) {\n const sampleT = (i / (steps - 1)) * curve.period;\n const a = sampleSkeleton(curve, sampleT);\n const tB =\n _morphStrategy === \"normalized\"\n ? (sampleT / curve.period) * morphCurveB.period\n : sampleT;\n const b = sampleSkeleton(morphCurveB, tB);\n\n points[i] = {\n x: a.x + (b.x - a.x) * _morphAlpha,\n y: a.y + (b.y - a.y) * _morphAlpha,\n };\n }\n return points;\n }\n\n for (let i = 0; i < steps; i++) {\n const sampleT = (i / (steps - 1)) * curve.period;\n points[i] = sampleSkeleton(curve, sampleT);\n }\n\n return points;\n },\n };\n}\n","import type { Point } from \"./types\";\n\nexport const DEFAULT_MORPH_DURATION_MS = 300;\nexport const DEFAULT_SKELETON_OPACITY = 0.15;\n/** Fraction of the bounding box added as padding when fitting the curve to the viewport */\nexport const FIT_PADDING = 0.1;\n/** Higher values = sharper fade near the tail, more of the trail appears faint */\nexport const TRAIL_FADE_CURVE = 1.5;\nexport const TRAIL_MAX_OPACITY = 0.88;\n/** Stroke/line width at the tail */\nexport const TRAIL_MIN_WIDTH = 0.5;\n/** Stroke/line width at the head */\nexport const TRAIL_MAX_WIDTH = 2.5;\n\nexport interface TrailPoint {\n x: number;\n y: number;\n}\n\n/**\n * Computes the unit tangent vector at a point on the trail.\n * - Interior points: central difference (previous -> next)\n * - Endpoints: forward/backward difference\n */\nexport function computeTangent(trail: TrailPoint[], i: number): TrailPoint {\n const count = trail.length;\n if (count < 2) {\n return { x: 1, y: 0 };\n }\n\n if (i === 0) {\n const dx = trail[1]!.x - trail[0]!.x;\n const dy = trail[1]!.y - trail[0]!.y;\n const len = Math.sqrt(dx * dx + dy * dy) || 1;\n return { x: dx / len, y: dy / len };\n }\n\n if (i === count - 1) {\n const dx = trail[count - 1]!.x - trail[count - 2]!.x;\n const dy = trail[count - 1]!.y - trail[count - 2]!.y;\n const len = Math.sqrt(dx * dx + dy * dy) || 1;\n return { x: dx / len, y: dy / len };\n }\n\n const dx = trail[i + 1]!.x - trail[i - 1]!.x;\n const dy = trail[i + 1]!.y - trail[i - 1]!.y;\n const len = Math.sqrt(dx * dx + dy * dy) || 1;\n return { x: dx / len, y: dy / len };\n}\n\n/**\n * Computes the unit normal vector at a point on the trail.\n * The normal is perpendicular to the tangent, rotated 90° counter-clockwise\n */\nexport function computeNormal(trail: TrailPoint[], i: number): TrailPoint {\n const tangent = computeTangent(trail, i);\n return { x: -tangent.y, y: tangent.x };\n}\n\n/** The four pixel-space corners and per-segment style values for one ribbon quad */\nexport interface TrailQuad {\n /** Left corner at the tail end of this segment */\n l0x: number;\n l0y: number;\n /** Right corner at the tail end of this segment */\n r0x: number;\n r0y: number;\n /** Left corner at the head end of this segment */\n l1x: number;\n l1y: number;\n /** Right corner at the head end of this segment */\n r1x: number;\n r1y: number;\n /** Fill opacity for this segment (0–1) */\n opacity: number;\n /** Position along the trail (0 = tail, 1 = head) */\n progress: number;\n}\n\n/**\n * Computes the pixel-space quad corners and style for one ribbon segment.\n *\n * @param trail Full trail array\n * @param i Segment index (draws from point i to point i+1)\n * @param trailCount Number of active trail points\n * @param toX Convert a trail point to its pixel X coordinate\n * @param toY Convert a trail point to its pixel Y coordinate\n *\n * @see https://mattdesl.svbtle.com/drawing-lines-is-hard\n * DesLauriers: \"Triangulated Lines\" — expand points outward by half\n * the thickness on either side using normals to create thick lines.\n */\nexport function computeTrailQuad(\n trail: TrailPoint[],\n i: number,\n trailCount: number,\n toX: (p: TrailPoint) => number,\n toY: (p: TrailPoint) => number,\n): TrailQuad {\n const progress = i / (trailCount - 1);\n const nextProgress = (i + 1) / (trailCount - 1);\n const opacity = Math.pow(progress, TRAIL_FADE_CURVE) * TRAIL_MAX_OPACITY;\n const w0 = (TRAIL_MIN_WIDTH + progress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH)) / 2;\n const w1 = (TRAIL_MIN_WIDTH + nextProgress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH)) / 2;\n\n const curr = trail[i]!;\n const next = trail[i + 1]!;\n const n0 = computeNormal(trail, i);\n const n1 = computeNormal(trail, i + 1);\n\n const cx = toX(curr);\n const cy = toY(curr);\n const nx = toX(next);\n const ny = toY(next);\n\n return {\n l0x: cx + n0.x * w0,\n l0y: cy + n0.y * w0,\n r0x: cx - n0.x * w0,\n r0y: cy - n0.y * w0,\n l1x: nx + n1.x * w1,\n l1y: ny + n1.y * w1,\n r1x: nx - n1.x * w1,\n r1y: ny - n1.y * w1,\n opacity,\n progress,\n };\n}\n\nexport interface BoundaryResult {\n scale: number;\n offsetX: number;\n offsetY: number;\n}\n\n/**\n * Computes how to map engine coordinates into a viewport of the given logical size.\n * ! Returns `null` if `pts` is empty\n * ! Throws if all points are identical\n *\n * Steps: find bounding box -> compute uniform scale that fits with padding -> center offsets\n */\nexport function computeBoundaries(\n pts: Point[],\n logicalWidth: number,\n logicalHeight: number,\n): BoundaryResult | null {\n if (pts.length === 0) return null;\n\n const first = pts[0]!;\n let minX = first.x,\n maxX = first.x,\n minY = first.y,\n maxY = first.y;\n\n for (const p of pts) {\n if (p.x < minX) {\n minX = p.x;\n }\n if (p.x > maxX) {\n maxX = p.x;\n }\n if (p.y < minY) {\n minY = p.y;\n }\n if (p.y > maxY) {\n maxY = p.y;\n }\n }\n\n const w = maxX - minX;\n const h = maxY - minY;\n\n if (w === 0 && h === 0) {\n throw new Error(\n \"[sarmal] Degenerate curve: all skeleton points are identical. \" +\n \"Check that your curve fn returns distinct points for different values of t.\",\n );\n }\n\n const scaleX = logicalWidth / (w * (1 + FIT_PADDING * 2));\n const scaleY = logicalHeight / (h * (1 + FIT_PADDING * 2));\n const scale = Math.min(scaleX, scaleY);\n\n return {\n scale,\n offsetX: (logicalWidth - w * scale) / 2 - minX * scale,\n offsetY: (logicalHeight - h * scale) / 2 - minY * scale,\n };\n}\n","import type {\n CurveDef,\n MorphOptions,\n PalettePreset,\n Point,\n RendererOptions,\n SarmalInstance,\n TrailStyle,\n} from \"./types\";\nimport {\n DEFAULT_MORPH_DURATION_MS,\n DEFAULT_SKELETON_OPACITY,\n computeBoundaries,\n computeNormal,\n computeTrailQuad,\n} from \"./renderer-shared\";\n\n// Re-exported so existing test imports (renderer.test.ts) keep working\nexport { computeTangent, computeNormal, TrailPoint } from \"./renderer-shared\";\n\nconst DEFAULT_HEAD_RADIUS = 4;\nconst DEFAULT_SKELETON_COLOR = \"#ffffff\";\n\nconst GRADIENT = {\n bard: [\"#a855f7\", \"#3b82f6\", \"#14b8a6\", \"#ec4899\"],\n sunset: [\"#f97316\", \"#dc2626\", \"#9333ea\", \"#f472b6\"],\n ocean: [\"#1e3a8a\", \"#06b6d4\", \"#22d3ee\", \"#e0f2fe\"],\n ice: [\"#1e3a8a\", \"#67e8f9\"],\n fire: [\"#7f1d1d\", \"#fbbf24\"],\n forest: [\"#14532d\", \"#86efac\"],\n};\n\nconst PRESETS: Record<PalettePreset, string[]> = {\n bard: GRADIENT.bard,\n sunset: GRADIENT.sunset,\n ocean: GRADIENT.ocean,\n ice: GRADIENT.ice,\n fire: GRADIENT.fire,\n forest: GRADIENT.forest,\n};\n\n// ? exported for testing\nexport interface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\n// ? exported for testing\nexport function hexToRgb(hex: string): Rgb {\n const n = parseInt(hex.slice(1), 16);\n return { r: n >> 16, g: (n >> 8) & 255, b: n & 255 };\n}\n\n// ? exported for testing\nexport const lerpRgb = (a: Rgb, b: Rgb, t: number) => ({\n r: Math.round(a.r + (b.r - a.r) * t),\n g: Math.round(a.g + (b.g - a.g) * t),\n b: Math.round(a.b + (b.b - a.b) * t),\n});\n\n/**\n * Gets a color from a palette based on position (0-1) with optional time-based cycling\n * ? Exported for testing.\n */\nexport function getPaletteColor(palette: string[], position: number, timeOffset: number = 0): Rgb {\n if (palette.length === 0) return { r: 255, g: 255, b: 255 };\n if (palette.length === 1) return hexToRgb(palette[0]!);\n\n const cyclePos = (position + timeOffset) % 1;\n const scaled = cyclePos * palette.length;\n const idx = Math.floor(scaled);\n const t = scaled - idx;\n\n const c1 = hexToRgb(palette[idx % palette.length]!);\n const c2 = hexToRgb(palette[(idx + 1) % palette.length]!);\n\n return lerpRgb(c1, c2, t);\n}\n\n// ? exported for testing\nexport function resolvePalette(\n palette: PalettePreset | string[] | undefined,\n trailStyle: TrailStyle,\n): string[] {\n if (Array.isArray(palette)) return palette;\n if (palette && palette in PRESETS) return PRESETS[palette as PalettePreset]!;\n return trailStyle === \"gradient-animated\" ? GRADIENT.bard : GRADIENT.ice;\n}\n\n// TODO: accept rgb(a)\nexport function hexToRgbComponents(hex: string): string {\n const n = parseInt(hex.slice(1), 16);\n return `${n >> 16},${(n >> 8) & 255},${n & 255}`;\n}\n\n/**\n * ! Exported purely so `applyDprSizing` can be unit-tested without a DOM\n */\nexport interface DprSizingTarget {\n width: number;\n height: number;\n style: { width: string; height: string };\n}\n\n/**\n * Applies DPR sizing to a target\n *\n * ! DO NOT REMOVE THE `style.width` and `style.height` ASSIGNMENTS\n *\n * A canvas with only `width`/`height` HTML attributes and no CSS derives\n * its displayed size from those attributes.\n * If we set `canvas.width = logicalWidth * dpr` to scale the drawing buffer for \"crispness\",\n * the element ALSO visually grows by the DPR factor\n * ! The bug is silent and sneaky. It just resulsts in a broken render without any obvious reasons\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas\n * MDN: \"If you don't set the CSS attributes, the intrinsic size of the canvas will be used as its display size\"\n *\n * @see https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html\n * \"Every canvas has 2 sizes: the drawingbuffer (pixels) and the display\n * size (CSS). If no CSS affects display size, it equals drawingbuffer.\"\n *\n * @see https://stackoverflow.com/questions/4938346/canvas-width-and-height-in-html5\n * Phrogz: \"If you don't set the CSS attributes, the intrinsic size of\n * the canvas will be used as its display size.\"\n *\n * The regression test for this lives in **renderer.test.ts**\n */\nexport function applyDprSizing(\n target: DprSizingTarget,\n logicalWidth: number,\n logicalHeight: number,\n dpr: number,\n): void {\n // Pin the CSS display size FIRST so changing the attributes below\n // cannot resize the element.\n target.style.width = `${logicalWidth}px`;\n target.style.height = `${logicalHeight}px`;\n\n target.width = logicalWidth * dpr;\n target.height = logicalHeight * dpr;\n}\n\n/**\n * Creates a Canvas 2D renderer for sarmal animations\n * Renders the skeleton and the trail\n */\nexport function createRenderer(options: RendererOptions): SarmalInstance {\n const canvas = options.canvas;\n if (!canvas.getContext(\"2d\")) {\n throw new Error(\"Could not get 2d context from canvas\");\n }\n const ctx = canvas.getContext(\"2d\")!;\n\n const engine = options.engine;\n const opts = {\n skeletonColor: options.skeletonColor ?? DEFAULT_SKELETON_COLOR,\n trailColor: options.trailColor ?? \"#ffffff\",\n headColor: options.headColor ?? \"#ffffff\",\n headRadius: options.headRadius ?? DEFAULT_HEAD_RADIUS,\n };\n\n const trailStyle: TrailStyle = options.trailStyle ?? \"default\";\n const palette = resolvePalette(options.palette, trailStyle);\n const trailRgb = hexToRgbComponents(opts.trailColor);\n\n /**\n * Device pixel ratio for high-DPI displays.\n * We scale the canvas buffer size by DPR and apply a transform scale\n */\n const dpr = typeof window !== \"undefined\" ? window.devicePixelRatio || 1 : 1;\n\n /**\n * Sets up the canvas for DPR scaling\n */\n function setupCanvas() {\n // TODO: attach a ResizeObserver so this function can be called again for the right scale of canvas\n const rect = canvas.getBoundingClientRect();\n const lw = rect.width || 200;\n const lh = rect.height || 200;\n applyDprSizing(canvas, lw, lh, dpr);\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n\n setupCanvas();\n\n // Store logical dimensions for boundary calculations\n let logicalWidth = canvas.width / dpr;\n let logicalHeight = canvas.height / dpr;\n\n let skeleton: Array<Point> = [];\n let skeletonCanvas: OffscreenCanvas | null = null;\n let trail: Array<Point> = [];\n let trailCount = 0;\n let head: Point | null = null;\n let scale = 1;\n let offsetX = 0;\n let offsetY = 0;\n let animationId: number | null = null;\n let lastTime = 0;\n\n let morphResolve: (() => void) | null = null;\n let morphDurationMs = DEFAULT_MORPH_DURATION_MS;\n let morphAlpha = 0;\n\n /** Accumulated time for \"gradient-animated\" trail style */\n let gradientAnimTime = 0;\n\n function calculateBoundaries() {\n const b = computeBoundaries(skeleton, logicalWidth, logicalHeight);\n if (b) {\n scale = b.scale;\n offsetX = b.offsetX;\n offsetY = b.offsetY;\n }\n }\n\n /**\n * Draws the skeleton once into an OffscreenCanvas so that every frame\n * only needs a single ctx.drawImage() instead of rebuilding the full path.\n */\n function buildSkeletonCanvas() {\n if (skeleton.length < 2) return;\n\n skeletonCanvas = new OffscreenCanvas(canvas.width, canvas.height);\n const skeletonCtx = skeletonCanvas.getContext(\"2d\")!;\n\n // Apply DPR scale to draw in logical coordinates\n skeletonCtx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n skeletonCtx.strokeStyle = `rgba(${hexToRgbComponents(opts.skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;\n skeletonCtx.lineWidth = 1.5;\n skeletonCtx.beginPath();\n\n const first = skeleton[0]!;\n skeletonCtx.moveTo(first.x * scale + offsetX, first.y * scale + offsetY);\n\n for (let i = 1; i < skeleton.length; i++) {\n const p = skeleton[i]!;\n skeletonCtx.lineTo(p.x * scale + offsetX, p.y * scale + offsetY);\n }\n\n skeletonCtx.stroke();\n }\n\n function drawSkeletonPath(pts: Array<Point>, opacity: number) {\n if (pts.length < 2) return;\n ctx.strokeStyle = `rgba(${hexToRgbComponents(opts.skeletonColor)},${opacity})`;\n ctx.lineWidth = 1.5;\n ctx.beginPath();\n ctx.moveTo(pts[0]!.x * scale + offsetX, pts[0]!.y * scale + offsetY);\n for (let i = 1; i < pts.length; i++) {\n ctx.lineTo(pts[i]!.x * scale + offsetX, pts[i]!.y * scale + offsetY);\n }\n ctx.stroke();\n }\n\n function drawSkeleton() {\n if (opts.skeletonColor === \"transparent\") {\n return;\n }\n\n if (engine.morphAlpha !== null) {\n // Draw the live lerped skeleton every frame so it always matches the current\n // scale/offset and correctly tracks live curves that change with actualTime\n drawSkeletonPath(engine.getSarmalSkeleton(), DEFAULT_SKELETON_OPACITY);\n return;\n }\n\n if (engine.isLiveSkeleton) {\n if (skeleton.length < 2) {\n return;\n }\n\n ctx.strokeStyle = `rgba(${hexToRgbComponents(opts.skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;\n ctx.lineWidth = 1.5;\n ctx.beginPath();\n\n const first = skeleton[0]!;\n ctx.moveTo(first.x * scale + offsetX, first.y * scale + offsetY);\n\n for (let i = 1; i < skeleton.length; i++) {\n const p = skeleton[i]!;\n ctx.lineTo(p.x * scale + offsetX, p.y * scale + offsetY);\n }\n\n ctx.stroke();\n } else if (skeletonCanvas) {\n /**\n * ! The offscreen buffer is *already* DPR-scaled, but the main ctx also has a DPR transform applied,\n * ! so passing natural pixel size would **double-scale** it.\n */\n ctx.drawImage(skeletonCanvas, 0, 0, logicalWidth, logicalHeight);\n }\n }\n\n function drawTrail() {\n if (trailCount < 2) {\n return;\n }\n\n /**\n * Ribbon approach: draw the trail as a sequence of filled quads.\n * Each quad connects two consecutive trail points with left/right offsets\n * based on the width at that position. Quads are drawn from tail to head\n * so later quads naturally overlay earlier ones.\n *\n * @see https://cesium.com/blog/2013/04/22/robust-polyline-rendering-with-webgl\n * Cesium: \"draw a screen-aligned quad for each segment... extrude them\n * in screen space in the direction normal to the line.\"\n */\n const toX = (p: { x: number }) => p.x * scale + offsetX;\n const toY = (p: { y: number }) => p.y * scale + offsetY;\n for (let i = 0; i < trailCount - 1; i++) {\n const { l0x, l0y, r0x, r0y, l1x, l1y, r1x, r1y, opacity, progress } = computeTrailQuad(\n trail,\n i,\n trailCount,\n toX,\n toY,\n );\n\n // Determine fill color based on trail style\n if (trailStyle === \"default\") {\n ctx.fillStyle = `rgba(${trailRgb},${opacity})`;\n } else {\n const timeOffset = trailStyle === \"gradient-animated\" ? gradientAnimTime * 0.0005 : 0;\n const color = getPaletteColor(palette, progress, timeOffset);\n ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${opacity})`;\n }\n\n ctx.beginPath();\n ctx.moveTo(l0x, l0y);\n ctx.lineTo(l1x, l1y);\n ctx.lineTo(r1x, r1y);\n ctx.lineTo(r0x, r0y);\n ctx.closePath();\n ctx.fill();\n }\n }\n\n function drawHead() {\n if (!head) {\n return;\n }\n\n const x = head.x * scale + offsetX;\n const y = head.y * scale + offsetY;\n\n ctx.fillStyle = opts.headColor;\n ctx.beginPath();\n ctx.arc(x, y, opts.headRadius, 0, Math.PI * 2);\n ctx.fill();\n }\n\n function render() {\n const now = performance.now();\n const deltaTime = Math.min((now - lastTime) / 1000, 1 / 30);\n lastTime = now;\n\n // Update gradient animation time for animated trail style\n if (trailStyle === \"gradient-animated\") {\n gradientAnimTime += deltaTime * 1000; // Convert to ms for consistent speed\n }\n\n if (engine.morphAlpha !== null) {\n morphAlpha = Math.min(1, morphAlpha + deltaTime / (morphDurationMs / 1000));\n engine.setMorphAlpha(morphAlpha);\n\n /**\n * Compute bounds from the actual interpolated skeleton during morph\n * ! This ensures the curve stays properly centered and scaled\n */\n const interpolatedSkeleton = engine.getSarmalSkeleton();\n const bounds = computeBoundaries(interpolatedSkeleton, logicalWidth, logicalHeight);\n\n if (bounds) {\n scale = bounds.scale;\n offsetX = bounds.offsetX;\n offsetY = bounds.offsetY;\n }\n\n if (morphAlpha >= 1) {\n engine.completeMorph();\n morphResolve?.();\n morphResolve = null;\n morphAlpha = 0;\n\n skeleton = engine.getSarmalSkeleton();\n if (!engine.isLiveSkeleton) {\n buildSkeletonCanvas();\n }\n }\n }\n\n trail = engine.tick(deltaTime);\n trailCount = engine.trailCount;\n head = trailCount > 0 ? trail[trailCount - 1]! : null;\n\n ctx.clearRect(0, 0, logicalWidth, logicalHeight);\n\n if (engine.isLiveSkeleton && engine.morphAlpha === null) {\n skeleton = engine.getSarmalSkeleton();\n calculateBoundaries();\n }\n\n drawSkeleton();\n drawTrail();\n drawHead();\n\n animationId = requestAnimationFrame(render);\n }\n\n // Initialize skeleton and offscreen canvas on creation\n skeleton = engine.getSarmalSkeleton();\n calculateBoundaries();\n\n if (!engine.isLiveSkeleton) {\n buildSkeletonCanvas();\n }\n\n return {\n start() {\n if (animationId !== null) {\n return;\n }\n\n lastTime = performance.now();\n render();\n },\n\n stop() {\n if (animationId === null) {\n return;\n }\n\n cancelAnimationFrame(animationId);\n animationId = null;\n },\n\n reset() {\n engine.reset();\n trail = [];\n head = null;\n },\n\n destroy() {\n if (animationId !== null) {\n cancelAnimationFrame(animationId);\n animationId = null;\n }\n },\n\n seek(t, options) {\n engine.seek(t, options);\n },\n\n seekWithTrail(t) {\n engine.seekWithTrail(t);\n },\n\n morphTo(target: CurveDef, options?: MorphOptions): Promise<void> {\n if (morphResolve !== null) {\n engine.completeMorph();\n morphResolve();\n morphResolve = null;\n morphAlpha = 0;\n }\n\n morphDurationMs = options?.duration ?? DEFAULT_MORPH_DURATION_MS;\n morphAlpha = 0;\n\n engine.startMorph(target, options?.morphStrategy);\n\n return new Promise<void>((resolve) => {\n morphResolve = resolve;\n });\n },\n };\n}\n","import type { CurveDef, Engine, MorphOptions, Point, SarmalInstance } from \"./types\";\nimport {\n DEFAULT_MORPH_DURATION_MS,\n DEFAULT_SKELETON_OPACITY,\n computeBoundaries,\n computeTrailQuad,\n} from \"./renderer-shared\";\nimport { createEngine } from \"./engine\";\n\nexport interface SVGRendererOptions {\n /** Container element that will contain the SVG */\n container: Element;\n engine: Engine;\n /** @default '#ffffff' */\n skeletonColor?: string;\n /** @default '#ffffff' */\n trailColor?: string;\n /** @default '#ffffff' */\n headColor?: string;\n /** @default 4 */\n headRadius?: number;\n /** @default 'Loading' */\n ariaLabel?: string;\n}\n\nexport interface SVGSarmalOptions extends Omit<SVGRendererOptions, \"container\" | \"engine\"> {\n /** @default 120 */\n trailLength?: number;\n}\n/** Maximum number of trail segment paths pre-created for the ribbon */\nconst MAX_TRAIL_SEGMENTS = 200;\n\nconst EMPTY_PARAMS: Record<string, number> = {};\n\nfunction pointsToPathString(pts: Point[], scale: number, offsetX: number, offsetY: number): string {\n if (pts.length < 2) return \"\";\n const px = (p: Point) => (p.x * scale + offsetX).toFixed(2);\n const py = (p: Point) => (p.y * scale + offsetY).toFixed(2);\n let d = `M${px(pts[0]!)} ${py(pts[0]!)}`;\n for (let i = 1; i < pts.length; i++) {\n d += ` L${px(pts[i]!)} ${py(pts[i]!)}`;\n }\n return d + \" Z\";\n}\n\nfunction sampleCurveSkeleton(curveDef: CurveDef): Point[] {\n const period = curveDef.period ?? Math.PI * 2;\n const samples = Math.ceil(period * 50); // match engine's POINTS_PER_PERIOD_UNIT\n const pts: Point[] = Array.from({ length: samples });\n for (let i = 0; i < samples; i++) {\n const t = (i / (samples - 1)) * period;\n pts[i] = curveDef.skeletonFn ? curveDef.skeletonFn(t) : curveDef.fn(t, 0, EMPTY_PARAMS);\n }\n return pts;\n}\n\nfunction el(tag: string): SVGElement {\n return document.createElementNS(\"http://www.w3.org/2000/svg\", tag);\n}\n\n/**\n * Creates a live SVG renderer for sarmal animations\n * The SVG is appended into `container` and updated each frame via **requestAnimationFrame**\n */\nexport function createSVGRenderer(options: SVGRendererOptions): SarmalInstance {\n const { container, engine } = options;\n const opts = {\n skeletonColor: options.skeletonColor ?? \"#ffffff\",\n trailColor: options.trailColor ?? \"#ffffff\",\n headColor: options.headColor ?? \"#ffffff\",\n headRadius: options.headRadius ?? 4,\n ariaLabel: options.ariaLabel ?? \"Loading\",\n };\n\n const rect = container.getBoundingClientRect();\n const width = rect.width || 200;\n const height = rect.height || 200;\n\n const svg = el(\"svg\") as SVGSVGElement;\n svg.setAttribute(\"width\", String(width));\n svg.setAttribute(\"height\", String(height));\n svg.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n svg.setAttribute(\"role\", \"img\");\n svg.setAttribute(\"aria-label\", opts.ariaLabel);\n\n const titleEl = el(\"title\");\n titleEl.textContent = opts.ariaLabel;\n svg.appendChild(titleEl);\n\n const skeletonPath = el(\"path\") as SVGPathElement;\n skeletonPath.setAttribute(\"fill\", \"none\");\n skeletonPath.setAttribute(\"stroke\", opts.skeletonColor);\n skeletonPath.setAttribute(\"stroke-opacity\", String(DEFAULT_SKELETON_OPACITY));\n skeletonPath.setAttribute(\"stroke-width\", \"1.5\");\n svg.appendChild(skeletonPath);\n\n const skeletonPathA = el(\"path\") as SVGPathElement;\n skeletonPathA.setAttribute(\"fill\", \"none\");\n skeletonPathA.setAttribute(\"stroke\", opts.skeletonColor);\n skeletonPathA.setAttribute(\"stroke-width\", \"1.5\");\n skeletonPathA.setAttribute(\"visibility\", \"hidden\");\n svg.appendChild(skeletonPathA);\n\n const skeletonPathB = el(\"path\") as SVGPathElement;\n skeletonPathB.setAttribute(\"fill\", \"none\");\n skeletonPathB.setAttribute(\"stroke\", opts.skeletonColor);\n skeletonPathB.setAttribute(\"stroke-width\", \"1.5\");\n skeletonPathB.setAttribute(\"visibility\", \"hidden\");\n svg.appendChild(skeletonPathB);\n\n let morphPathABuilt = \"\";\n let morphPathBBuilt = \"\";\n\n const trailPaths: SVGPathElement[] = [];\n for (let i = 0; i < MAX_TRAIL_SEGMENTS; i++) {\n const path = el(\"path\") as SVGPathElement;\n path.setAttribute(\"fill\", opts.trailColor);\n svg.appendChild(path);\n trailPaths.push(path);\n }\n\n const headCircle = el(\"circle\") as SVGCircleElement;\n headCircle.setAttribute(\"fill\", opts.headColor);\n headCircle.setAttribute(\"r\", String(opts.headRadius));\n svg.appendChild(headCircle);\n\n container.appendChild(svg);\n\n let scale = 1;\n let offsetX = 0;\n let offsetY = 0;\n\n function applyBoundaries(skeleton: Point[]) {\n const b = computeBoundaries(skeleton, width, height);\n if (b) {\n scale = b.scale;\n offsetX = b.offsetX;\n offsetY = b.offsetY;\n }\n }\n\n // Coordinate transform helpers: numeric (for math)\n function px(p: Point): number {\n return p.x * scale + offsetX;\n }\n function py(p: Point): number {\n return p.y * scale + offsetY;\n }\n\n function updateSkeleton(skeleton: Point[]) {\n skeletonPath.setAttribute(\"d\", pointsToPathString(skeleton, scale, offsetX, offsetY));\n }\n\n const skeleton = engine.getSarmalSkeleton();\n applyBoundaries(skeleton);\n\n if (!engine.isLiveSkeleton) {\n updateSkeleton(skeleton);\n }\n\n function updateTrail(trail: Point[], trailCount: number) {\n if (trailCount < 2) {\n for (const p of trailPaths) {\n p.setAttribute(\"d\", \"\");\n }\n return;\n }\n\n /**\n * Ribbon approach: each segment is a filled quad with its own opacity.\n * Quads are drawn from tail to head, with later quads overlaying earlier ones.\n */\n for (let i = 0; i < trailCount - 1; i++) {\n const { l0x, l0y, r0x, r0y, l1x, l1y, r1x, r1y, opacity } = computeTrailQuad(\n trail,\n i,\n trailCount,\n px,\n py,\n );\n\n const d = `M${l0x.toFixed(2)} ${l0y.toFixed(2)} L${l1x.toFixed(2)} ${l1y.toFixed(2)} L${r1x.toFixed(2)} ${r1y.toFixed(2)} L${r0x.toFixed(2)} ${r0y.toFixed(2)} Z`;\n\n trailPaths[i]!.setAttribute(\"d\", d);\n trailPaths[i]!.setAttribute(\"fill-opacity\", opacity.toFixed(3));\n }\n\n // Hide unused paths\n for (let i = trailCount - 1; i < trailPaths.length; i++) {\n trailPaths[i]!.setAttribute(\"d\", \"\");\n }\n }\n\n function updateHead(trail: Point[], trailCount: number) {\n if (trailCount === 0) {\n return;\n }\n\n const head = trail[trailCount - 1]!;\n const x = px(head);\n const y = py(head);\n\n headCircle.setAttribute(\"cx\", String(x));\n headCircle.setAttribute(\"cy\", String(y));\n }\n\n let animationId: number | null = null;\n let lastTime = 0;\n const prefersReducedMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n let morphResolve: (() => void) | null = null;\n let morphDurationMs = DEFAULT_MORPH_DURATION_MS;\n let morphTarget: CurveDef | null = null;\n let morphAlpha = 0;\n\n function renderFrame() {\n const now = performance.now();\n const dt = Math.min((now - lastTime) / 1000, 1 / 30);\n lastTime = now;\n\n if (engine.morphAlpha !== null) {\n morphAlpha = Math.min(1, morphAlpha + dt / (morphDurationMs / 1000));\n engine.setMorphAlpha(morphAlpha);\n\n if (morphPathABuilt) {\n skeletonPathA.setAttribute(\"d\", morphPathABuilt);\n skeletonPathA.setAttribute(\"visibility\", \"visible\");\n skeletonPathA.setAttribute(\n \"stroke-opacity\",\n String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY),\n );\n }\n\n if (morphPathBBuilt) {\n skeletonPathB.setAttribute(\"d\", morphPathBBuilt);\n skeletonPathB.setAttribute(\"visibility\", \"visible\");\n skeletonPathB.setAttribute(\"stroke-opacity\", String(morphAlpha * DEFAULT_SKELETON_OPACITY));\n }\n\n if (morphAlpha >= 1) {\n engine.completeMorph();\n morphResolve?.();\n morphResolve = null;\n morphTarget = null;\n morphAlpha = 0;\n morphPathABuilt = \"\";\n morphPathBBuilt = \"\";\n skeletonPathA.setAttribute(\"visibility\", \"hidden\");\n skeletonPathB.setAttribute(\"visibility\", \"hidden\");\n // Snap coordinate space to `curveB` and update skeleton path\n const newSkeleton = engine.getSarmalSkeleton();\n applyBoundaries(newSkeleton);\n updateSkeleton(newSkeleton);\n }\n }\n\n const trail = engine.tick(dt);\n const trailCount = engine.trailCount;\n\n if (engine.isLiveSkeleton && engine.morphAlpha === null) {\n const liveSkeleton = engine.getSarmalSkeleton();\n applyBoundaries(liveSkeleton);\n updateSkeleton(liveSkeleton);\n }\n\n updateTrail(trail, trailCount);\n updateHead(trail, trailCount);\n\n if (!prefersReducedMotion) {\n animationId = requestAnimationFrame(renderFrame);\n }\n }\n\n return {\n start() {\n if (animationId !== null) {\n return;\n }\n lastTime = performance.now();\n renderFrame();\n },\n\n stop() {\n if (animationId === null) {\n return;\n }\n cancelAnimationFrame(animationId);\n animationId = null;\n },\n\n reset() {\n engine.reset();\n },\n\n destroy() {\n if (animationId !== null) {\n cancelAnimationFrame(animationId);\n animationId = null;\n }\n svg.remove();\n },\n\n seek(t, options) {\n engine.seek(t, options);\n },\n\n seekWithTrail(t) {\n engine.seekWithTrail(t);\n },\n\n morphTo(target: CurveDef, options?: MorphOptions): Promise<void> {\n if (morphResolve !== null) {\n engine.completeMorph();\n morphResolve();\n morphResolve = null;\n morphAlpha = 0;\n skeletonPathA.setAttribute(\"visibility\", \"hidden\");\n skeletonPathB.setAttribute(\"visibility\", \"hidden\");\n }\n\n morphDurationMs = options?.duration ?? DEFAULT_MORPH_DURATION_MS;\n morphTarget = target;\n morphAlpha = 0;\n\n const currentSkeleton = engine.getSarmalSkeleton();\n morphPathABuilt = pointsToPathString(currentSkeleton, scale, offsetX, offsetY);\n\n engine.startMorph(target, options?.morphStrategy);\n\n if (morphTarget) {\n const targetSkeleton = sampleCurveSkeleton(target);\n morphPathBBuilt = pointsToPathString(targetSkeleton, scale, offsetX, offsetY);\n }\n\n return new Promise<void>((resolve) => {\n morphResolve = resolve;\n });\n },\n };\n}\n\n/**\n * Creates a sarmal animation inside a container element using an SVG renderer\n * The SVG is appended to the container and animated via requestAnimationFrame\n *\n * @example\n * ```ts\n * import { createSarmalSVG, curves } from '@sarmal/core'\n * const sarmal = createSarmalSVG(document.getElementById('spinner'), curves.epitrochoid7)\n * sarmal.start()\n * ```\n */\nexport function createSarmalSVG(\n container: Element,\n curveDef: CurveDef,\n options?: SVGSarmalOptions,\n): SarmalInstance {\n const { trailLength, ...rendererOpts } = options ?? {};\n const engine = createEngine(curveDef, trailLength);\n return createSVGRenderer({ container, engine, ...rendererOpts });\n}\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\n/**\n * Artemis II free-return lunar trajectory\n * @see https://www.nasa.gov/wp-content/uploads/2025/09/artemis-ii-map-508.pdf\n * a = x-axis asymmetry (widens one lobe),\n * b = y-axis asymmetry,\n * ox = horizontal offset to visually center the shape\n */\nfunction artemis2Fn(t: number, _time: number, _params: Record<string, number>) {\n const a = 0.35,\n b = 0.15,\n ox = 0.175;\n const s = Math.sin(t),\n c = Math.cos(t);\n const denom = 1 + s * s;\n return {\n x: (c * (1 + a * c)) / denom - ox,\n y: (s * c * (1 + b * c)) / denom,\n };\n}\n\n/**\n * Artemis II free-return lunar trajectory curve\n * Traces the path of the Orion spacecraft during the Artemis II mission\n */\nexport const artemis2: CurveDef = {\n name: \"Artemis II\",\n fn: artemis2Fn,\n period: TWO_PI,\n speed: 0.7,\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction astroidFn(t: number, _time: number, _params: Record<string, number>) {\n const c = Math.cos(t);\n const s = Math.sin(t);\n return {\n x: c * c * c,\n y: s * s * s,\n };\n}\n\n/**\n * Astroid curve - a 4-cusped hypocycloid\n * Creates a star-like shape with four sharp corners\n */\nexport const astroid: CurveDef = {\n name: \"Astroid\",\n fn: astroidFn,\n period: TWO_PI,\n speed: 1.1,\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction deltoidFn(t: number, _time: number, _params: Record<string, number>) {\n return {\n x: 2 * Math.cos(t) + Math.cos(2 * t),\n y: 2 * Math.sin(t) - Math.sin(2 * t),\n };\n}\n\n/**\n * Deltoid curve - a 3-cusped hypocycloid\n * Creates a triangular shape with curved sides\n */\nexport const deltoid: CurveDef = {\n name: \"Deltoid\",\n fn: deltoidFn,\n period: TWO_PI,\n speed: 0.9,\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction epicycloid3Fn(t: number, _time: number, _params: Record<string, number>) {\n return {\n x: 4 * Math.cos(t) - Math.cos(4 * t),\n y: 4 * Math.sin(t) - Math.sin(4 * t),\n };\n}\n\n/**\n * Epicycloid with 3 cusps\n * Creates a three-pointed star shape\n */\nexport const epicycloid3: CurveDef = {\n name: \"Epicycloid (n=3)\",\n fn: epicycloid3Fn,\n period: TWO_PI,\n speed: 0.75,\n};\n","import type { CurveDef, Point } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction epitrochoid7Fn(t: number, _time: number, _params: Record<string, number>) {\n const d = 1.0 + 0.55 * Math.sin(t * 0.5);\n return {\n x: 7 * Math.cos(t) - d * Math.cos(7 * t),\n y: 7 * Math.sin(t) - d * Math.sin(7 * t),\n };\n}\n\nfunction epitrochoid7SkeletonFn(t: number): Point {\n // average of the oscillating range for a stable base shape\n const d = 1.275;\n return {\n x: 7 * Math.cos(t) - d * Math.cos(7 * t),\n y: 7 * Math.sin(t) - d * Math.sin(7 * t),\n };\n}\n\n/**\n * Epitrochoid with 7 lobes and dynamic variation\n * Creates a flower-like pattern with undulating petals\n */\nexport const epitrochoid7: CurveDef = {\n name: \"Epitrochoid\",\n fn: epitrochoid7Fn,\n period: TWO_PI,\n speed: 1.4,\n skeletonFn: epitrochoid7SkeletonFn,\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction lissajous32Fn(t: number, time: number, _params: Record<string, number>) {\n const phi = time * 0.45;\n return {\n x: Math.sin(3 * t + phi),\n y: Math.sin(2 * t),\n };\n}\n\n/**\n * Lissajous curve with frequency ratio 3:2\n * Creates a figure-eight-like pattern with live skeleton\n */\nexport const lissajous32: CurveDef = {\n name: \"Lissajous 3:2\",\n fn: lissajous32Fn,\n period: TWO_PI,\n speed: 2.0,\n skeleton: \"live\",\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction lissajous43Fn(t: number, time: number, _params: Record<string, number>) {\n const phi = time * 0.38;\n return {\n x: Math.sin(4 * t + phi),\n y: Math.sin(3 * t),\n };\n}\n\n/**\n * Lissajous curve with frequency ratio 4:3\n * Creates a complex interweaving pattern with live skeleton\n */\nexport const lissajous43: CurveDef = {\n name: \"Lissajous 4:3\",\n fn: lissajous43Fn,\n period: TWO_PI,\n speed: 1.8,\n skeleton: \"live\",\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction lameFn(t: number, time: number, _params: Record<string, number>) {\n const p = 1.75 + 1.25 * Math.sin(time * 0.48);\n const c = Math.cos(t),\n s = Math.sin(t);\n return {\n x: Math.sign(c) * Math.pow(Math.abs(c), p),\n y: Math.sign(s) * Math.pow(Math.abs(s), p),\n };\n}\n\n/**\n * Lamé curve (superellipse) with time-varying exponent\n * Creates a squircle-like shape that morphs over time\n */\nexport const lame: CurveDef = {\n name: \"Lamé Curve\",\n fn: lameFn,\n period: TWO_PI,\n speed: 1.0,\n skeleton: \"live\",\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction rose3Fn(t: number, _time: number, _params: Record<string, number>) {\n const r = Math.cos(3 * t);\n return {\n x: r * Math.cos(t),\n y: r * Math.sin(t),\n };\n}\n\n/**\n * Rose curve with 3 petals\n * Creates a three-petaled flower pattern\n */\nexport const rose3: CurveDef = {\n name: \"Rose (n=3)\",\n fn: rose3Fn,\n period: TWO_PI,\n speed: 1.15,\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction rose5Fn(t: number, _time: number, _params: Record<string, number>) {\n const r = Math.cos(5 * t);\n return {\n x: r * Math.cos(t),\n y: r * Math.sin(t),\n };\n}\n\n/**\n * Rose curve with 5 petals\n * Creates a five-petaled flower pattern\n */\nexport const rose5: CurveDef = {\n name: \"Rose (n=5)\",\n fn: rose5Fn,\n period: TWO_PI,\n speed: 1.0,\n};\n","// Individual curve exports for tree-shaking\nexport { artemis2 } from \"./artemis2\";\nexport { astroid } from \"./astroid\";\nexport { deltoid } from \"./deltoid\";\nexport { epicycloid3 } from \"./epicycloid3\";\nexport { epitrochoid7 } from \"./epitrochoid7\";\nexport { lissajous32 } from \"./lissajous32\";\nexport { lissajous43 } from \"./lissajous43\";\nexport { lame } from \"./lame\";\nexport { rose3 } from \"./rose3\";\nexport { rose5 } from \"./rose5\";\n\n// Bulk export for convenience\nimport type { CurveDef } from \"../types\";\nimport { artemis2 } from \"./artemis2\";\nimport { astroid } from \"./astroid\";\nimport { deltoid } from \"./deltoid\";\nimport { epicycloid3 } from \"./epicycloid3\";\nimport { epitrochoid7 } from \"./epitrochoid7\";\nimport { lissajous32 } from \"./lissajous32\";\nimport { lissajous43 } from \"./lissajous43\";\nimport { lame } from \"./lame\";\nimport { rose3 } from \"./rose3\";\nimport { rose5 } from \"./rose5\";\n\n/**\n * Collection of all built-in sarmal curves\n * Import individual curves for better tree-shaking\n */\nexport const curves: Record<string, CurveDef> = {\n artemis2,\n epitrochoid7,\n astroid,\n deltoid,\n rose5,\n rose3,\n lissajous32,\n lissajous43,\n epicycloid3,\n lame,\n};\n","export type { SVGRendererOptions, SVGSarmalOptions } from \"./renderer-svg\";\nexport type {\n Point,\n CurveDef,\n Engine,\n SarmalInstance,\n SeekOptions,\n SeekWithTrailOptions,\n RendererOptions,\n SarmalOptions,\n TrailStyle,\n PalettePreset,\n} from \"./types\";\n\nexport { createEngine } from \"./engine\";\nexport { createRenderer } from \"./renderer\";\nexport { createSVGRenderer, createSarmalSVG } from \"./renderer-svg\";\nexport { curves } from \"./curves\";\nexport {\n artemis2,\n epitrochoid7,\n astroid,\n deltoid,\n rose5,\n rose3,\n lissajous32,\n lissajous43,\n epicycloid3,\n lame,\n} from \"./curves\";\n\nimport type { CurveDef, SarmalInstance, SarmalOptions } from \"./types\";\nimport { createEngine } from \"./engine\";\nimport { createRenderer } from \"./renderer\";\n\n/**\n * Creates a sarmal animation on a canvas element\n *\n * @example\n * ```ts\n * import { createSarmal, curves } from '@sarmal/core'\n * const sarmal = createSarmal(canvas, curves.artemis2)\n * sarmal.start()\n * ```\n */\nexport function createSarmal(\n canvas: HTMLCanvasElement,\n curveDef: CurveDef,\n options?: SarmalOptions,\n): SarmalInstance {\n const { trailLength, ...rendererOpts } = options ?? {};\n const engine = createEngine(curveDef, trailLength);\n\n return createRenderer({ canvas, engine, ...rendererOpts });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/engine.ts","../src/renderer-shared.ts","../src/renderer.ts","../src/renderer-svg.ts","../src/curves/artemis2.ts","../src/curves/astroid.ts","../src/curves/deltoid.ts","../src/curves/epicycloid3.ts","../src/curves/epitrochoid7.ts","../src/curves/lissajous32.ts","../src/curves/lissajous43.ts","../src/curves/lame.ts","../src/curves/rose3.ts","../src/curves/rose5.ts","../src/curves/index.ts","../src/index.ts"],"names":["dx","dy","len","options","EMPTY_PARAMS","skeleton","TWO_PI"],"mappings":";AAEA,IAAM,MAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AACzB,IAAM,sBAAA,GAAyB,EAAA;AAY/B,SAAS,IAAA,CAAK,KAAA,EAAe,GAAA,EAAa,CAAA,EAAmB;AAC3D,EAAA,OAAO,KAAA,GAAA,CAAS,MAAM,KAAA,IAAS,CAAA;AACjC;AAGA,IAAM,eAAuC,EAAC;AAS9C,IAAM,iBAAN,MAAqB;AAAA,EAOnB,YAAY,QAAA,EAAkB;AAH9B,IAAA,IAAA,CAAQ,IAAA,GAAe,CAAA;AACvB,IAAA,IAAA,CAAQ,KAAA,GAAgB,CAAA;AAGtB,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,IAAA,IAAA,CAAK,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,QAAA,EAAS,EAAG,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,GAAE,CAAE,CAAA;AACnE,IAAA,IAAA,CAAK,MAAA,GAAS,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,QAAA,EAAS,EAAG,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,GAAE,CAAE,CAAA;AAAA,EACvE;AAAA;AAAA,EAGA,IAAA,CAAK,GAAW,CAAA,EAAiB;AAC/B,IAAA,MAAM,IAAA,GAAO,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,IAAI,CAAA;AAEhC,IAAA,IAAA,CAAK,CAAA,GAAI,CAAA;AACT,IAAA,IAAA,CAAK,CAAA,GAAI,CAAA;AACT,IAAA,IAAA,CAAK,IAAA,GAAA,CAAQ,IAAA,CAAK,IAAA,GAAO,CAAA,IAAK,IAAA,CAAK,QAAA;AAEnC,IAAA,IAAI,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,QAAA,EAAU;AAC9B,MAAA,IAAA,CAAK,KAAA,EAAA;AAAA,IACP;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAA,GAAwB;AACtB,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,GAAQ,IAAA,CAAK,QAAA,GAAW,IAAI,IAAA,CAAK,IAAA;AAEpD,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,OAAO,CAAA,EAAA,EAAK;AACnC,MAAA,MAAM,MAAM,IAAA,CAAK,IAAA,CAAA,CAAM,KAAA,GAAQ,CAAA,IAAK,KAAK,QAAQ,CAAA;AACjD,MAAA,MAAM,GAAA,GAAM,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AACzB,MAAA,GAAA,CAAI,IAAI,GAAA,CAAI,CAAA;AACZ,MAAA,GAAA,CAAI,IAAI,GAAA,CAAI,CAAA;AAAA,IACd;AAEA,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA,EAEA,KAAA,GAAc;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,CAAA;AACZ,IAAA,IAAA,CAAK,KAAA,GAAQ,CAAA;AAAA,EACf;AAAA,EAEA,IAAI,MAAA,GAAS;AACX,IAAA,OAAO,IAAA,CAAK,KAAA;AAAA,EACd;AACF,CAAA;AAwBA,SAAS,aAAa,QAAA,EAAmC;AACvD,EAAA,MAAM,MAAA,GAAS,SAAS,MAAA,IAAU,MAAA;AAElC,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,MAAM,CAAA,IAAK,UAAU,CAAA,EAAG;AAC3C,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,sDAAA,EAAyD,MAAM,CAAA,CAAE,CAAA;AAAA,EACxF;AAEA,EAAA,MAAM,KAAA,GAAQ,SAAS,KAAA,IAAS,CAAA;AAEhC,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAC3B,IAAA,MAAM,IAAI,UAAA,CAAW,CAAA,4CAAA,EAA+C,KAAK,CAAA,CAAE,CAAA;AAAA,EAC7E;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,QAAA,CAAS,IAAA;AAAA,IACf,IAAI,QAAA,CAAS,EAAA;AAAA,IACb,MAAA;AAAA,IACA,KAAA;AAAA,IACA,UAAU,QAAA,CAAS,QAAA;AAAA,IACnB,YAAY,QAAA,CAAS;AAAA,GACvB;AACF;AAEO,SAAS,YAAA,CAAa,QAAA,EAAoB,WAAA,GAAsB,GAAA,EAAa;AAClF,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,WAAW,CAAA,IAAK,eAAe,CAAA,EAAG;AACrD,IAAA,MAAM,IAAI,UAAA;AAAA,MACR,8DAA8D,WAAW,CAAA;AAAA,KAC3E;AAAA,EACF;AAEA,EAAA,IAAI,KAAA,GAAQ,aAAa,QAAQ,CAAA;AACjC,EAAA,MAAM,KAAA,GAAQ,IAAI,cAAA,CAAe,WAAW,CAAA;AAC5C,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,iBAAA,GAAmC,IAAA;AAGvC,EAAA,IAAI,WAAA,GAAoC,IAAA;AACxC,EAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,EAAA,IAAI,cAAA,GAA+B,YAAA;AAGnC,EAAA,IAAI,gBAAA,GAA2C,IAAA;AAG/C,EAAA,SAAS,cAAA,CAAe,GAAkB,OAAA,EAAwB;AAChE,IAAA,IAAI,EAAE,UAAA,EAAY;AAChB,MAAA,OAAO,CAAA,CAAE,WAAW,OAAO,CAAA;AAAA,IAC7B;AACA,IAAA,IAAI,CAAA,CAAE,aAAa,MAAA,EAAQ;AACzB,MAAA,OAAO,CAAA,CAAE,EAAA,CAAG,OAAA,EAAS,UAAA,EAAY,YAAY,CAAA;AAAA,IAC/C;AACA,IAAA,OAAO,CAAA,CAAE,EAAA,CAAG,OAAA,EAAS,CAAA,EAAG,YAAY,CAAA;AAAA,EACtC;AAEA,EAAA,OAAO;AAAA,IACL,KAAK,SAAA,EAAiC;AACpC,MAAA,IAAI,qBAAqB,IAAA,EAAM;AAG7B,QAAA,gBAAA,CAAiB,WAAW,SAAA,GAAY,GAAA;AACxC,QAAA,MAAM,QAAQ,IAAA,CAAK,GAAA,CAAI,iBAAiB,OAAA,GAAU,gBAAA,CAAiB,UAAU,CAAC,CAAA;AAC9E,QAAA,iBAAA,GAAoB,IAAA,CAAK,gBAAA,CAAiB,IAAA,EAAM,gBAAA,CAAiB,IAAI,KAAK,CAAA;AAC1E,QAAA,IAAI,SAAS,CAAA,EAAG;AACd,UAAA,iBAAA,GAAoB,gBAAA,CAAiB,EAAA;AACrC,UAAA,gBAAA,CAAiB,OAAA,EAAQ;AACzB,UAAA,gBAAA,GAAmB,IAAA;AAAA,QACrB;AAAA,MACF;AAEA,MAAA,IAAI,cAAA,GAAiB,qBAAqB,KAAA,CAAM,KAAA;AAChD,MAAA,IAAI,WAAA,KAAgB,IAAA,IAAQ,WAAA,KAAgB,IAAA,EAAM;AAChD,QAAA,cAAA,GAAiB,IAAA,CAAK,cAAA,EAAgB,WAAA,CAAY,KAAA,EAAO,WAAW,CAAA;AAAA,MACtE;AACA,MAAA,CAAA,GAAA,CAAK,CAAA,GAAI,cAAA,GAAiB,SAAA,IAAa,KAAA,CAAM,MAAA;AAC7C,MAAA,UAAA,IAAc,SAAA;AAEd,MAAA,IAAI,WAAA,KAAgB,IAAA,IAAQ,WAAA,KAAgB,IAAA,EAAM;AAChD,QAAA,MAAM,CAAA,GAAI,KAAA,CAAM,EAAA,CAAG,CAAA,EAAG,YAAY,YAAY,CAAA;AAC9C,QAAA,MAAM,KAAK,cAAA,KAAmB,YAAA,GAAgB,IAAI,KAAA,CAAM,MAAA,GAAU,YAAY,MAAA,GAAS,CAAA;AACvF,QAAA,MAAM,CAAA,GAAI,WAAA,CAAY,EAAA,CAAG,EAAA,EAAI,YAAY,YAAY,CAAA;AACrD,QAAA,KAAA,CAAM,IAAA,CAAK,CAAA,CAAE,CAAA,GAAA,CAAK,CAAA,CAAE,IAAI,CAAA,CAAE,CAAA,IAAK,WAAA,EAAa,CAAA,CAAE,CAAA,GAAA,CAAK,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,KAAK,WAAW,CAAA;AAAA,MAC7E,CAAA,MAAO;AACL,QAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,EAAA,CAAG,CAAA,EAAG,YAAY,YAAY,CAAA;AAClD,QAAA,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,KAAA,CAAM,CAAC,CAAA;AAAA,MAC7B;AAEA,MAAA,OAAO,MAAM,OAAA,EAAQ;AAAA,IACvB,CAAA;AAAA,IAEA,IAAI,UAAA,GAAa;AACf,MAAA,OAAO,KAAA,CAAM,MAAA;AAAA,IACf,CAAA;AAAA,IAEA,IAAI,cAAA,GAAiB;AACnB,MAAA,OAAO,MAAM,QAAA,KAAa,MAAA;AAAA,IAC5B,CAAA;AAAA,IAEA,IAAI,UAAA,GAAa;AACf,MAAA,OAAO,WAAA;AAAA,IACT,CAAA;AAAA,IAEA,KAAA,GAAQ;AACN,MAAA,CAAA,GAAI,CAAA;AACJ,MAAA,UAAA,GAAa,CAAA;AACb,MAAA,KAAA,CAAM,KAAA,EAAM;AAAA,IACd,CAAA;AAAA,IAEA,KAAK,IAAA,EAAc,EAAE,aAAa,KAAA,EAAM,GAAiB,EAAC,EAAG;AAC3D,MAAA,CAAA,GAAA,CAAM,IAAA,GAAO,KAAA,CAAM,MAAA,GAAU,KAAA,CAAM,UAAU,KAAA,CAAM,MAAA;AACnD,MAAA,IAAI,UAAA,EAAY;AACd,QAAA,KAAA,CAAM,KAAA,EAAM;AAAA,MACd;AAAA,IACF,CAAA;AAAA,IAEA,IAAA,CAAK,OAAA,EAAiB,EAAE,IAAA,GAAO,KAAA,EAAO,IAAA,GAAO,KAAA,CAAM,MAAA,GAAS,WAAA,EAAY,GAAiB,EAAC,EAAG;AAC3F,MAAA,MAAM,OAAA,GAAU,MAAM,KAAA,GAAQ,IAAA;AAC9B,MAAA,MAAM,UAAW,OAAA,GAAU,KAAA,CAAM,MAAA,GAAU,KAAA,CAAM,UAAU,KAAA,CAAM,MAAA;AACjE,MAAA,MAAM,UAAA,GAAa,SAAS,KAAA,CAAM,KAAA;AAElC,MAAA,CAAA,GAAI,MAAA;AACJ,MAAA,UAAA,GAAa,UAAA;AACb,MAAA,KAAA,CAAM,KAAA,EAAM;AAEZ,MAAA,MAAM,eAAA,GAAkB,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,OAAO,CAAA,GAAI,CAAA;AACvD,MAAA,MAAM,QAAQ,IAAA,GAAO,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,aAAa,eAAe,CAAA;AAExE,MAAA,KAAA,IAAS,CAAA,GAAI,KAAA,GAAQ,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AACnC,QAAA,MAAM,OAAA,GAAU,SAAS,CAAA,GAAI,OAAA;AAC7B,QAAA,MAAM,YAAa,OAAA,GAAU,KAAA,CAAM,MAAA,GAAU,KAAA,CAAM,UAAU,KAAA,CAAM,MAAA;AACnE,QAAA,MAAM,IAAA,GAAO,aAAa,CAAA,GAAI,IAAA;AAC9B,QAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,EAAA,CAAG,QAAA,EAAU,MAAM,YAAY,CAAA;AAEnD,QAAA,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,KAAA,CAAM,CAAC,CAAA;AAAA,MAC7B;AAAA,IACF,CAAA;AAAA,IAEA,UAAA,CAAW,MAAA,EAAkB,QAAA,GAAyB,YAAA,EAAc;AAClE,MAAA,MAAM,cAAA,GAAiB,aAAa,MAAM,CAAA;AAE1C,MAAA,IAAI,WAAA,KAAgB,IAAA,IAAQ,WAAA,KAAgB,IAAA,EAAM;AAChD,QAAA,MAAM,WAAA,GAAc,WAAA;AACpB,QAAA,MAAM,OAAA,GAAU,KAAA;AAChB,QAAA,MAAM,OAAA,GAAU,WAAA;AAChB,QAAA,MAAM,cAAA,GAAiB,cAAA;AAEvB,QAAA,KAAA,GAAQ;AAAA,UACN,GAAG,OAAA;AAAA,UACH,EAAA,EAAI,CAAC,OAAA,EAAiB,IAAA,EAAc,MAAA,KAAmC;AACrE,YAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,EAAA,CAAG,OAAA,EAAS,MAAM,MAAM,CAAA;AAC1C,YAAA,MAAM,KACJ,cAAA,KAAmB,YAAA,GACd,UAAU,OAAA,CAAQ,MAAA,GAAU,QAAQ,MAAA,GACrC,OAAA;AACN,YAAA,MAAM,CAAA,GAAI,OAAA,CAAQ,EAAA,CAAG,EAAA,EAAI,MAAM,MAAM,CAAA;AACrC,YAAA,OAAO;AAAA,cACL,GAAG,CAAA,CAAE,CAAA,GAAA,CAAK,CAAA,CAAE,CAAA,GAAI,EAAE,CAAA,IAAK,WAAA;AAAA,cACvB,GAAG,CAAA,CAAE,CAAA,GAAA,CAAK,CAAA,CAAE,CAAA,GAAI,EAAE,CAAA,IAAK;AAAA,aACzB;AAAA,UACF;AAAA,SACF;AAAA,MACF;AAEA,MAAA,cAAA,GAAiB,QAAA;AACjB,MAAA,WAAA,GAAc,cAAA;AACd,MAAA,WAAA,GAAc,CAAA;AAAA,IAChB,CAAA;AAAA,IAEA,cAAc,KAAA,EAAe;AAC3B,MAAA,WAAA,GAAc,KAAA;AAAA,IAChB,CAAA;AAAA,IAEA,aAAA,GAAgB;AACd,MAAA,IAAI,gBAAgB,IAAA,EAAM;AAIxB,QAAA,IAAI,cAAA,KAAmB,YAAA,IAAgB,KAAA,CAAM,MAAA,KAAW,YAAY,MAAA,EAAQ;AAC1E,UAAA,CAAA,GAAK,CAAA,GAAI,KAAA,CAAM,MAAA,GAAU,WAAA,CAAY,MAAA;AAAA,QACvC;AACA,QAAA,KAAA,GAAQ,WAAA;AAAA,MACV;AACA,MAAA,WAAA,GAAc,IAAA;AACd,MAAA,WAAA,GAAc,IAAA;AAAA,IAChB,CAAA;AAAA,IAEA,iBAAA,GAAkC;AAChC,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,SAAS,sBAAsB,CAAA;AAE7D,MAAA,MAAM,MAAA,GAAuB,IAAI,KAAA,CAAM,KAAK,CAAA;AAE5C,MAAA,IAAI,WAAA,KAAgB,IAAA,IAAQ,WAAA,KAAgB,IAAA,EAAM;AAChD,QAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,CAAA,EAAA,EAAK;AAC9B,UAAA,MAAM,OAAA,GAAW,CAAA,IAAK,KAAA,GAAQ,CAAA,CAAA,GAAM,KAAA,CAAM,MAAA;AAC1C,UAAA,MAAM,CAAA,GAAI,cAAA,CAAe,KAAA,EAAO,OAAO,CAAA;AACvC,UAAA,MAAM,KACJ,cAAA,KAAmB,YAAA,GACd,UAAU,KAAA,CAAM,MAAA,GAAU,YAAY,MAAA,GACvC,OAAA;AACN,UAAA,MAAM,CAAA,GAAI,cAAA,CAAe,WAAA,EAAa,EAAE,CAAA;AAExC,UAAA,MAAA,CAAO,CAAC,CAAA,GAAI;AAAA,YACV,GAAG,CAAA,CAAE,CAAA,GAAA,CAAK,CAAA,CAAE,CAAA,GAAI,EAAE,CAAA,IAAK,WAAA;AAAA,YACvB,GAAG,CAAA,CAAE,CAAA,GAAA,CAAK,CAAA,CAAE,CAAA,GAAI,EAAE,CAAA,IAAK;AAAA,WACzB;AAAA,QACF;AACA,QAAA,OAAO,MAAA;AAAA,MACT;AAEA,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,CAAA,EAAA,EAAK;AAC9B,QAAA,MAAM,OAAA,GAAW,CAAA,IAAK,KAAA,GAAQ,CAAA,CAAA,GAAM,KAAA,CAAM,MAAA;AAC1C,QAAA,MAAA,CAAO,CAAC,CAAA,GAAI,cAAA,CAAe,KAAA,EAAO,OAAO,CAAA;AAAA,MAC3C;AAEA,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IAEA,SAAS,KAAA,EAAqB;AAC5B,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAC3B,QAAA,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAAA,MACjD;AACA,MAAA,IAAI,qBAAqB,IAAA,EAAM;AAC7B,QAAA,gBAAA,CAAiB,MAAA,CAAO,IAAI,KAAA,CAAM,4BAA4B,CAAC,CAAA;AAC/D,QAAA,gBAAA,GAAmB,IAAA;AAAA,MACrB;AACA,MAAA,iBAAA,GAAoB,KAAA;AAAA,IACtB,CAAA;AAAA,IAEA,QAAA,GAAmB;AACjB,MAAA,OAAO,qBAAqB,KAAA,CAAM,KAAA;AAAA,IACpC,CAAA;AAAA,IAEA,UAAA,GAAmB;AACjB,MAAA,iBAAA,GAAoB,IAAA;AAAA,IACtB,CAAA;AAAA,IAEA,YAAA,CAAa,OAAe,QAAA,EAAiC;AAC3D,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,KAAK,CAAA,EAAG;AAC3B,QAAA,MAAM,IAAI,MAAM,+BAA+B,CAAA;AAAA,MACjD;AACA,MAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,QAAQ,CAAA,IAAK,YAAY,CAAA,EAAG;AAC/C,QAAA,MAAM,IAAI,MAAM,iDAAiD,CAAA;AAAA,MACnE;AAEA,MAAA,IAAI,qBAAqB,IAAA,EAAM;AAC7B,QAAA,gBAAA,CAAiB,MAAA,CAAO,IAAI,KAAA,CAAM,4BAA4B,CAAC,CAAA;AAC/D,QAAA,gBAAA,GAAmB,IAAA;AAAA,MACrB;AAEA,MAAA,MAAM,IAAA,GAAO,qBAAqB,KAAA,CAAM,KAAA;AAExC,MAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAC5C,QAAA,gBAAA,GAAmB,EAAE,MAAM,EAAA,EAAI,KAAA,EAAO,SAAS,CAAA,EAAG,QAAA,EAAU,SAAS,MAAA,EAAO;AAAA,MAC9E,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,qBAAA,GAA8B;AAC5B,MAAA,IAAI,qBAAqB,IAAA,EAAM;AAC7B,QAAA,gBAAA,CAAiB,MAAA,CAAO,IAAI,KAAA,CAAM,4BAA4B,CAAC,CAAA;AAC/D,QAAA,gBAAA,GAAmB,IAAA;AAAA,MACrB;AAAA,IACF;AAAA,GACF;AACF;;;AC9WO,IAAM,yBAAA,GAA4B,GAAA;AAClC,IAAM,wBAAA,GAA2B,IAAA;AAEjC,IAAM,WAAA,GAAc,GAAA;AAEpB,IAAM,gBAAA,GAAmB,GAAA;AACzB,IAAM,iBAAA,GAAoB,IAAA;AAE1B,IAAM,eAAA,GAAkB,GAAA;AAExB,IAAM,eAAA,GAAkB,GAAA;AAYxB,SAAS,cAAA,CAAe,OAAqB,CAAA,EAAuB;AACzE,EAAA,MAAM,QAAQ,KAAA,CAAM,MAAA;AACpB,EAAA,IAAI,QAAQ,CAAA,EAAG;AACb,IAAA,OAAO,EAAE,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAE;AAAA,EACtB;AAEA,EAAA,IAAI,MAAM,CAAA,EAAG;AACX,IAAA,MAAMA,MAAK,KAAA,CAAM,CAAC,EAAG,CAAA,GAAI,KAAA,CAAM,CAAC,CAAA,CAAG,CAAA;AACnC,IAAA,MAAMC,MAAK,KAAA,CAAM,CAAC,EAAG,CAAA,GAAI,KAAA,CAAM,CAAC,CAAA,CAAG,CAAA;AACnC,IAAA,MAAMC,OAAM,IAAA,CAAK,IAAA,CAAKF,MAAKA,GAAAA,GAAKC,GAAAA,GAAKA,GAAE,CAAA,IAAK,CAAA;AAC5C,IAAA,OAAO,EAAE,CAAA,EAAGD,GAAAA,GAAKE,IAAAA,EAAK,CAAA,EAAGD,MAAKC,IAAAA,EAAI;AAAA,EACpC;AAEA,EAAA,IAAI,CAAA,KAAM,QAAQ,CAAA,EAAG;AACnB,IAAA,MAAMF,GAAAA,GAAK,MAAM,KAAA,GAAQ,CAAC,EAAG,CAAA,GAAI,KAAA,CAAM,KAAA,GAAQ,CAAC,CAAA,CAAG,CAAA;AACnD,IAAA,MAAMC,GAAAA,GAAK,MAAM,KAAA,GAAQ,CAAC,EAAG,CAAA,GAAI,KAAA,CAAM,KAAA,GAAQ,CAAC,CAAA,CAAG,CAAA;AACnD,IAAA,MAAMC,OAAM,IAAA,CAAK,IAAA,CAAKF,MAAKA,GAAAA,GAAKC,GAAAA,GAAKA,GAAE,CAAA,IAAK,CAAA;AAC5C,IAAA,OAAO,EAAE,CAAA,EAAGD,GAAAA,GAAKE,IAAAA,EAAK,CAAA,EAAGD,MAAKC,IAAAA,EAAI;AAAA,EACpC;AAEA,EAAA,MAAM,EAAA,GAAK,MAAM,CAAA,GAAI,CAAC,EAAG,CAAA,GAAI,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,CAAG,CAAA;AAC3C,EAAA,MAAM,EAAA,GAAK,MAAM,CAAA,GAAI,CAAC,EAAG,CAAA,GAAI,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA,CAAG,CAAA;AAC3C,EAAA,MAAM,MAAM,IAAA,CAAK,IAAA,CAAK,KAAK,EAAA,GAAK,EAAA,GAAK,EAAE,CAAA,IAAK,CAAA;AAC5C,EAAA,OAAO,EAAE,CAAA,EAAG,EAAA,GAAK,GAAA,EAAK,CAAA,EAAG,KAAK,GAAA,EAAI;AACpC;AAMO,SAAS,aAAA,CAAc,OAAqB,CAAA,EAAuB;AACxE,EAAA,MAAM,OAAA,GAAU,cAAA,CAAe,KAAA,EAAO,CAAC,CAAA;AACvC,EAAA,OAAO,EAAE,CAAA,EAAG,CAAC,QAAQ,CAAA,EAAG,CAAA,EAAG,QAAQ,CAAA,EAAE;AACvC;AAmCO,SAAS,gBAAA,CACd,KAAA,EACA,CAAA,EACA,UAAA,EACA,KACA,GAAA,EACW;AACX,EAAA,MAAM,QAAA,GAAW,KAAK,UAAA,GAAa,CAAA,CAAA;AACnC,EAAA,MAAM,YAAA,GAAA,CAAgB,CAAA,GAAI,CAAA,KAAM,UAAA,GAAa,CAAA,CAAA;AAC7C,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,QAAA,EAAU,gBAAgB,CAAA,GAAI,iBAAA;AACvD,EAAA,MAAM,EAAA,GAAA,CAAM,eAAA,GAAkB,QAAA,IAAY,eAAA,GAAkB,eAAA,CAAA,IAAoB,CAAA;AAChF,EAAA,MAAM,EAAA,GAAA,CAAM,eAAA,GAAkB,YAAA,IAAgB,eAAA,GAAkB,eAAA,CAAA,IAAoB,CAAA;AAEpF,EAAA,MAAM,IAAA,GAAO,MAAM,CAAC,CAAA;AACpB,EAAA,MAAM,IAAA,GAAO,KAAA,CAAM,CAAA,GAAI,CAAC,CAAA;AACxB,EAAA,MAAM,EAAA,GAAK,aAAA,CAAc,KAAA,EAAO,CAAC,CAAA;AACjC,EAAA,MAAM,EAAA,GAAK,aAAA,CAAc,KAAA,EAAO,CAAA,GAAI,CAAC,CAAA;AAErC,EAAA,MAAM,EAAA,GAAK,IAAI,IAAI,CAAA;AACnB,EAAA,MAAM,EAAA,GAAK,IAAI,IAAI,CAAA;AACnB,EAAA,MAAM,EAAA,GAAK,IAAI,IAAI,CAAA;AACnB,EAAA,MAAM,EAAA,GAAK,IAAI,IAAI,CAAA;AAEnB,EAAA,OAAO;AAAA,IACL,GAAA,EAAK,EAAA,GAAK,EAAA,CAAG,CAAA,GAAI,EAAA;AAAA,IACjB,GAAA,EAAK,EAAA,GAAK,EAAA,CAAG,CAAA,GAAI,EAAA;AAAA,IACjB,GAAA,EAAK,EAAA,GAAK,EAAA,CAAG,CAAA,GAAI,EAAA;AAAA,IACjB,GAAA,EAAK,EAAA,GAAK,EAAA,CAAG,CAAA,GAAI,EAAA;AAAA,IACjB,GAAA,EAAK,EAAA,GAAK,EAAA,CAAG,CAAA,GAAI,EAAA;AAAA,IACjB,GAAA,EAAK,EAAA,GAAK,EAAA,CAAG,CAAA,GAAI,EAAA;AAAA,IACjB,GAAA,EAAK,EAAA,GAAK,EAAA,CAAG,CAAA,GAAI,EAAA;AAAA,IACjB,GAAA,EAAK,EAAA,GAAK,EAAA,CAAG,CAAA,GAAI,EAAA;AAAA,IACjB,OAAA;AAAA,IACA;AAAA,GACF;AACF;AAeO,SAAS,iBAAA,CACd,GAAA,EACA,YAAA,EACA,aAAA,EACuB;AACvB,EAAA,IAAI,GAAA,CAAI,MAAA,KAAW,CAAA,EAAG,OAAO,IAAA;AAE7B,EAAA,MAAM,KAAA,GAAQ,IAAI,CAAC,CAAA;AACnB,EAAA,IAAI,IAAA,GAAO,KAAA,CAAM,CAAA,EACf,IAAA,GAAO,KAAA,CAAM,GACb,IAAA,GAAO,KAAA,CAAM,CAAA,EACb,IAAA,GAAO,KAAA,CAAM,CAAA;AAEf,EAAA,KAAA,MAAW,KAAK,GAAA,EAAK;AACnB,IAAA,IAAI,CAAA,CAAE,IAAI,IAAA,EAAM;AACd,MAAA,IAAA,GAAO,CAAA,CAAE,CAAA;AAAA,IACX;AACA,IAAA,IAAI,CAAA,CAAE,IAAI,IAAA,EAAM;AACd,MAAA,IAAA,GAAO,CAAA,CAAE,CAAA;AAAA,IACX;AACA,IAAA,IAAI,CAAA,CAAE,IAAI,IAAA,EAAM;AACd,MAAA,IAAA,GAAO,CAAA,CAAE,CAAA;AAAA,IACX;AACA,IAAA,IAAI,CAAA,CAAE,IAAI,IAAA,EAAM;AACd,MAAA,IAAA,GAAO,CAAA,CAAE,CAAA;AAAA,IACX;AAAA,EACF;AAEA,EAAA,MAAM,IAAI,IAAA,GAAO,IAAA;AACjB,EAAA,MAAM,IAAI,IAAA,GAAO,IAAA;AAEjB,EAAA,IAAI,CAAA,KAAM,CAAA,IAAK,CAAA,KAAM,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF;AAEA,EAAA,MAAM,MAAA,GAAS,YAAA,IAAgB,CAAA,IAAK,CAAA,GAAI,WAAA,GAAc,CAAA,CAAA,CAAA;AACtD,EAAA,MAAM,MAAA,GAAS,aAAA,IAAiB,CAAA,IAAK,CAAA,GAAI,WAAA,GAAc,CAAA,CAAA,CAAA;AACvD,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,MAAA,EAAQ,MAAM,CAAA;AAErC,EAAA,OAAO;AAAA,IACL,KAAA;AAAA,IACA,OAAA,EAAA,CAAU,YAAA,GAAe,CAAA,GAAI,KAAA,IAAS,IAAI,IAAA,GAAO,KAAA;AAAA,IACjD,OAAA,EAAA,CAAU,aAAA,GAAgB,CAAA,GAAI,KAAA,IAAS,IAAI,IAAA,GAAO;AAAA,GACpD;AACF;AAMO,SAAS,mBAAmB,MAAA,EAAgB;AACjD,EAAA,OAAO;AAAA,IACL,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,MAAM,MAAA,CAAO,IAAA;AAAA,IACb,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,YAAY,MAAA,CAAO,UAAA;AAAA,IACnB,cAAc,MAAA,CAAO;AAAA,GACvB;AACF;;;ACxLA,IAAM,sBAAA,GAAyB,SAAA;AAE/B,IAAM,QAAA,GAAW;AAAA,EACf,IAAA,EAAM,CAAC,SAAA,EAAW,SAAA,EAAW,WAAW,SAAS,CAAA;AAAA,EACjD,MAAA,EAAQ,CAAC,SAAA,EAAW,SAAA,EAAW,WAAW,SAAS,CAAA;AAAA,EACnD,KAAA,EAAO,CAAC,SAAA,EAAW,SAAA,EAAW,WAAW,SAAS,CAAA;AAAA,EAClD,GAAA,EAAK,CAAC,SAAA,EAAW,SAAS,CAAA;AAAA,EAC1B,IAAA,EAAM,CAAC,SAAA,EAAW,SAAS,CAAA;AAAA,EAC3B,MAAA,EAAQ,CAAC,SAAA,EAAW,SAAS;AAC/B,CAAA;AAEA,IAAM,OAAA,GAA2C;AAAA,EAC/C,MAAM,QAAA,CAAS,IAAA;AAAA,EACf,QAAQ,QAAA,CAAS,MAAA;AAAA,EACjB,OAAO,QAAA,CAAS,KAAA;AAAA,EAChB,KAAK,QAAA,CAAS,GAAA;AAAA,EACd,MAAM,QAAA,CAAS,IAAA;AAAA,EACf,QAAQ,QAAA,CAAS;AACnB,CAAA;AAUO,SAAS,SAAS,GAAA,EAAkB;AACzC,EAAA,MAAM,IAAI,QAAA,CAAS,GAAA,CAAI,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACnC,EAAA,OAAO,EAAE,CAAA,EAAG,CAAA,IAAK,EAAA,EAAI,CAAA,EAAI,KAAK,CAAA,GAAK,GAAA,EAAK,CAAA,EAAG,CAAA,GAAI,GAAA,EAAI;AACrD;AAGO,IAAM,OAAA,GAAU,CAAC,CAAA,EAAQ,CAAA,EAAQ,CAAA,MAAe;AAAA,EACrD,CAAA,EAAG,KAAK,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA,IAAK,CAAC,CAAA;AAAA,EACnC,CAAA,EAAG,KAAK,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA,IAAK,CAAC,CAAA;AAAA,EACnC,CAAA,EAAG,KAAK,KAAA,CAAM,CAAA,CAAE,KAAK,CAAA,CAAE,CAAA,GAAI,CAAA,CAAE,CAAA,IAAK,CAAC;AACrC,CAAA,CAAA;AAMO,SAAS,eAAA,CAAgB,OAAA,EAAmB,QAAA,EAAkB,UAAA,GAAqB,CAAA,EAAQ;AAChG,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,EAAE,GAAG,GAAA,EAAK,CAAA,EAAG,GAAA,EAAK,CAAA,EAAG,GAAA,EAAI;AAC1D,EAAA,IAAI,QAAQ,MAAA,KAAW,CAAA,SAAU,QAAA,CAAS,OAAA,CAAQ,CAAC,CAAE,CAAA;AAErD,EAAA,MAAM,QAAA,GAAA,CAAY,WAAW,UAAA,IAAc,CAAA;AAC3C,EAAA,MAAM,MAAA,GAAS,WAAW,OAAA,CAAQ,MAAA;AAClC,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,KAAA,CAAM,MAAM,CAAA;AAC7B,EAAA,MAAM,IAAI,MAAA,GAAS,GAAA;AAEnB,EAAA,MAAM,KAAK,QAAA,CAAS,OAAA,CAAQ,GAAA,GAAM,OAAA,CAAQ,MAAM,CAAE,CAAA;AAClD,EAAA,MAAM,KAAK,QAAA,CAAS,OAAA,CAAA,CAAS,MAAM,CAAA,IAAK,OAAA,CAAQ,MAAM,CAAE,CAAA;AAExD,EAAA,OAAO,OAAA,CAAQ,EAAA,EAAI,EAAA,EAAI,CAAC,CAAA;AAC1B;AAGO,SAAS,cAAA,CACd,SACA,UAAA,EACU;AACV,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,EAAG,OAAO,OAAA;AACnC,EAAA,IAAI,OAAA,IAAW,OAAA,IAAW,OAAA,EAAS,OAAO,QAAQ,OAAwB,CAAA;AAC1E,EAAA,OAAO,UAAA,KAAe,mBAAA,GAAsB,QAAA,CAAS,IAAA,GAAO,QAAA,CAAS,GAAA;AACvE;AAGO,SAAS,mBAAmB,GAAA,EAAqB;AACtD,EAAA,MAAM,IAAI,QAAA,CAAS,GAAA,CAAI,KAAA,CAAM,CAAC,GAAG,EAAE,CAAA;AACnC,EAAA,OAAO,CAAA,EAAG,KAAK,EAAE,CAAA,CAAA,EAAK,KAAK,CAAA,GAAK,GAAG,CAAA,CAAA,EAAI,CAAA,GAAI,GAAG,CAAA,CAAA;AAChD;AAmCO,SAAS,cAAA,CACd,MAAA,EACA,YAAA,EACA,aAAA,EACA,GAAA,EACM;AAGN,EAAA,MAAA,CAAO,KAAA,CAAM,KAAA,GAAQ,CAAA,EAAG,YAAY,CAAA,EAAA,CAAA;AACpC,EAAA,MAAA,CAAO,KAAA,CAAM,MAAA,GAAS,CAAA,EAAG,aAAa,CAAA,EAAA,CAAA;AAEtC,EAAA,MAAA,CAAO,QAAQ,YAAA,GAAe,GAAA;AAC9B,EAAA,MAAA,CAAO,SAAS,aAAA,GAAgB,GAAA;AAClC;AAMO,SAAS,eAAe,OAAA,EAA0C;AACvE,EAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AACvB,EAAA,IAAI,CAAC,MAAA,CAAO,UAAA,CAAW,IAAI,CAAA,EAAG;AAC5B,IAAA,MAAM,IAAI,MAAM,sCAAsC,CAAA;AAAA,EACxD;AACA,EAAA,MAAM,GAAA,GAAM,MAAA,CAAO,UAAA,CAAW,IAAI,CAAA;AAElC,EAAA,MAAM,SAAS,OAAA,CAAQ,MAAA;AACvB,EAAA,MAAM,UAAA,GAAyB,QAAQ,UAAA,IAAc,SAAA;AACrD,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,SAAA;AACzC,EAAA,MAAM,OAAA,GAAU,cAAA,CAAe,OAAA,CAAQ,OAAA,EAAS,UAAU,CAAA;AAE1D,EAAA,SAAS,gBAAA,GAA2B;AAClC,IAAA,IAAI,eAAe,SAAA,EAAW;AAC5B,MAAA,MAAM,EAAE,CAAA,EAAG,CAAA,EAAG,GAAE,GAAI,eAAA,CAAgB,SAAS,CAAG,CAAA;AAChD,MAAA,OAAO,CAAA,IAAA,EAAO,CAAC,CAAA,CAAA,EAAI,CAAC,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,IAC3B;AACA,IAAA,OAAO,UAAA;AAAA,EACT;AAEA,EAAA,MAAM,IAAA,GAAO;AAAA,IACX,aAAA,EAAe,QAAQ,aAAA,IAAiB,sBAAA;AAAA,IACxC,UAAA;AAAA,IACA,SAAA,EAAW,OAAA,CAAQ,SAAA,IAAa,gBAAA;AAAiB,GACnD;AAEA,EAAA,MAAM,QAAA,GAAW,kBAAA,CAAmB,IAAA,CAAK,UAAU,CAAA;AAMnD,EAAA,MAAM,MAAM,OAAO,MAAA,KAAW,WAAA,GAAc,MAAA,CAAO,oBAAoB,CAAA,GAAI,CAAA;AAK3E,EAAA,SAAS,WAAA,GAAc;AAErB,IAAA,MAAM,IAAA,GAAO,OAAO,qBAAA,EAAsB;AAC1C,IAAA,MAAM,EAAA,GAAK,KAAK,KAAA,IAAS,GAAA;AACzB,IAAA,MAAM,EAAA,GAAK,KAAK,MAAA,IAAU,GAAA;AAC1B,IAAA,cAAA,CAAe,MAAA,EAAQ,EAAA,EAAI,EAAA,EAAI,GAAG,CAAA;AAClC,IAAA,GAAA,CAAI,aAAa,GAAA,EAAK,CAAA,EAAG,CAAA,EAAG,GAAA,EAAK,GAAG,CAAC,CAAA;AAAA,EACvC;AAEA,EAAA,WAAA,EAAY;AAGZ,EAAA,IAAI,YAAA,GAAe,OAAO,KAAA,GAAQ,GAAA;AAClC,EAAA,IAAI,aAAA,GAAgB,OAAO,MAAA,GAAS,GAAA;AAEpC,EAAA,IAAI,WAAyB,EAAC;AAC9B,EAAA,IAAI,cAAA,GAAyC,IAAA;AAC7C,EAAA,IAAI,QAAsB,EAAC;AAC3B,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,IAAI,IAAA,GAAqB,IAAA;AACzB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,EAAA,IAAI,QAAA,GAAW,CAAA;AAEf,EAAA,IAAI,YAAA,GAAoC,IAAA;AACxC,EAAA,IAAI,eAAA,GAAkB,yBAAA;AACtB,EAAA,IAAI,UAAA,GAAa,CAAA;AAGjB,EAAA,IAAI,gBAAA,GAAmB,CAAA;AAEvB,EAAA,SAAS,mBAAA,GAAsB;AAC7B,IAAA,MAAM,CAAA,GAAI,iBAAA,CAAkB,QAAA,EAAU,YAAA,EAAc,aAAa,CAAA;AACjE,IAAA,IAAI,CAAA,EAAG;AACL,MAAA,KAAA,GAAQ,CAAA,CAAE,KAAA;AACV,MAAA,OAAA,GAAU,CAAA,CAAE,OAAA;AACZ,MAAA,OAAA,GAAU,CAAA,CAAE,OAAA;AAAA,IACd;AAAA,EACF;AAMA,EAAA,SAAS,mBAAA,GAAsB;AAC7B,IAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AAEzB,IAAA,cAAA,GAAiB,IAAI,eAAA,CAAgB,MAAA,CAAO,KAAA,EAAO,OAAO,MAAM,CAAA;AAChE,IAAA,MAAM,WAAA,GAAc,cAAA,CAAe,UAAA,CAAW,IAAI,CAAA;AAGlD,IAAA,WAAA,CAAY,aAAa,GAAA,EAAK,CAAA,EAAG,CAAA,EAAG,GAAA,EAAK,GAAG,CAAC,CAAA;AAE7C,IAAA,WAAA,CAAY,cAAc,CAAA,KAAA,EAAQ,kBAAA,CAAmB,KAAK,aAAa,CAAC,IAAI,wBAAwB,CAAA,CAAA,CAAA;AACpG,IAAA,WAAA,CAAY,SAAA,GAAY,GAAA;AACxB,IAAA,WAAA,CAAY,SAAA,EAAU;AAEtB,IAAA,MAAM,KAAA,GAAQ,SAAS,CAAC,CAAA;AACxB,IAAA,WAAA,CAAY,MAAA,CAAO,MAAM,CAAA,GAAI,KAAA,GAAQ,SAAS,KAAA,CAAM,CAAA,GAAI,QAAQ,OAAO,CAAA;AAEvE,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACxC,MAAA,MAAM,CAAA,GAAI,SAAS,CAAC,CAAA;AACpB,MAAA,WAAA,CAAY,MAAA,CAAO,EAAE,CAAA,GAAI,KAAA,GAAQ,SAAS,CAAA,CAAE,CAAA,GAAI,QAAQ,OAAO,CAAA;AAAA,IACjE;AAEA,IAAA,WAAA,CAAY,MAAA,EAAO;AAAA,EACrB;AAEA,EAAA,SAAS,gBAAA,CAAiB,KAAmB,OAAA,EAAiB;AAC5D,IAAA,IAAI,GAAA,CAAI,SAAS,CAAA,EAAG;AACpB,IAAA,GAAA,CAAI,cAAc,CAAA,KAAA,EAAQ,kBAAA,CAAmB,KAAK,aAAa,CAAC,IAAI,OAAO,CAAA,CAAA,CAAA;AAC3E,IAAA,GAAA,CAAI,SAAA,GAAY,GAAA;AAChB,IAAA,GAAA,CAAI,SAAA,EAAU;AACd,IAAA,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,CAAG,CAAA,GAAI,KAAA,GAAQ,OAAA,EAAS,GAAA,CAAI,CAAC,CAAA,CAAG,CAAA,GAAI,KAAA,GAAQ,OAAO,CAAA;AACnE,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,QAAQ,CAAA,EAAA,EAAK;AACnC,MAAA,GAAA,CAAI,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,CAAG,CAAA,GAAI,KAAA,GAAQ,OAAA,EAAS,GAAA,CAAI,CAAC,CAAA,CAAG,CAAA,GAAI,KAAA,GAAQ,OAAO,CAAA;AAAA,IACrE;AACA,IAAA,GAAA,CAAI,MAAA,EAAO;AAAA,EACb;AAEA,EAAA,SAAS,YAAA,GAAe;AACtB,IAAA,IAAI,IAAA,CAAK,kBAAkB,aAAA,EAAe;AACxC,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,MAAA,CAAO,eAAe,IAAA,EAAM;AAG9B,MAAA,gBAAA,CAAiB,MAAA,CAAO,iBAAA,EAAkB,EAAG,wBAAwB,CAAA;AACrE,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,OAAO,cAAA,EAAgB;AACzB,MAAA,IAAI,QAAA,CAAS,SAAS,CAAA,EAAG;AACvB,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,cAAc,CAAA,KAAA,EAAQ,kBAAA,CAAmB,KAAK,aAAa,CAAC,IAAI,wBAAwB,CAAA,CAAA,CAAA;AAC5F,MAAA,GAAA,CAAI,SAAA,GAAY,GAAA;AAChB,MAAA,GAAA,CAAI,SAAA,EAAU;AAEd,MAAA,MAAM,KAAA,GAAQ,SAAS,CAAC,CAAA;AACxB,MAAA,GAAA,CAAI,MAAA,CAAO,MAAM,CAAA,GAAI,KAAA,GAAQ,SAAS,KAAA,CAAM,CAAA,GAAI,QAAQ,OAAO,CAAA;AAE/D,MAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACxC,QAAA,MAAM,CAAA,GAAI,SAAS,CAAC,CAAA;AACpB,QAAA,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,GAAI,KAAA,GAAQ,SAAS,CAAA,CAAE,CAAA,GAAI,QAAQ,OAAO,CAAA;AAAA,MACzD;AAEA,MAAA,GAAA,CAAI,MAAA,EAAO;AAAA,IACb,WAAW,cAAA,EAAgB;AAKzB,MAAA,GAAA,CAAI,SAAA,CAAU,cAAA,EAAgB,CAAA,EAAG,CAAA,EAAG,cAAc,aAAa,CAAA;AAAA,IACjE;AAAA,EACF;AAEA,EAAA,SAAS,SAAA,GAAY;AACnB,IAAA,IAAI,aAAa,CAAA,EAAG;AAClB,MAAA;AAAA,IACF;AAYA,IAAA,MAAM,GAAA,GAAM,CAAC,CAAA,KAAqB,CAAA,CAAE,IAAI,KAAA,GAAQ,OAAA;AAChD,IAAA,MAAM,GAAA,GAAM,CAAC,CAAA,KAAqB,CAAA,CAAE,IAAI,KAAA,GAAQ,OAAA;AAChD,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,GAAa,GAAG,CAAA,EAAA,EAAK;AACvC,MAAA,MAAM,EAAE,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,OAAA,EAAS,QAAA,EAAS,GAAI,gBAAA;AAAA,QACpE,KAAA;AAAA,QACA,CAAA;AAAA,QACA,UAAA;AAAA,QACA,GAAA;AAAA,QACA;AAAA,OACF;AAGA,MAAA,IAAI,eAAe,SAAA,EAAW;AAC5B,QAAA,GAAA,CAAI,SAAA,GAAY,CAAA,KAAA,EAAQ,QAAQ,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,CAAA;AAAA,MAC7C,CAAA,MAAO;AACL,QAAA,MAAM,UAAA,GAAa,UAAA,KAAe,mBAAA,GAAsB,gBAAA,GAAmB,IAAA,GAAS,CAAA;AACpF,QAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,OAAA,EAAS,QAAA,EAAU,UAAU,CAAA;AAC3D,QAAA,GAAA,CAAI,SAAA,GAAY,CAAA,KAAA,EAAQ,KAAA,CAAM,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAA,CAAA,EAAI,KAAA,CAAM,CAAC,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA,CAAA;AAAA,MAClE;AAEA,MAAA,GAAA,CAAI,SAAA,EAAU;AACd,MAAA,GAAA,CAAI,MAAA,CAAO,KAAK,GAAG,CAAA;AACnB,MAAA,GAAA,CAAI,MAAA,CAAO,KAAK,GAAG,CAAA;AACnB,MAAA,GAAA,CAAI,MAAA,CAAO,KAAK,GAAG,CAAA;AACnB,MAAA,GAAA,CAAI,MAAA,CAAO,KAAK,GAAG,CAAA;AACnB,MAAA,GAAA,CAAI,SAAA,EAAU;AACd,MAAA,GAAA,CAAI,IAAA,EAAK;AAAA,IACX;AAAA,EACF;AAEA,EAAA,SAAS,QAAA,GAAW;AAClB,IAAA,IAAI,CAAC,IAAA,EAAM;AACT,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,CAAA,GAAI,KAAA,GAAQ,OAAA;AAC3B,IAAA,MAAM,CAAA,GAAI,IAAA,CAAK,CAAA,GAAI,KAAA,GAAQ,OAAA;AAC3B,IAAA,MAAM,CAAA,GACJ,OAAA,CAAQ,UAAA,IAAc,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,KAAK,GAAA,CAAI,YAAA,EAAc,aAAa,CAAA,GAAI,GAAG,CAAC,CAAA;AAE9F,IAAA,GAAA,CAAI,YAAY,IAAA,CAAK,SAAA;AACrB,IAAA,GAAA,CAAI,SAAA,EAAU;AACd,IAAA,GAAA,CAAI,IAAI,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA,EAAG,IAAA,CAAK,KAAK,CAAC,CAAA;AAC/B,IAAA,GAAA,CAAI,IAAA,EAAK;AAAA,EACX;AAEA,EAAA,SAAS,MAAA,GAAS;AAChB,IAAA,MAAM,GAAA,GAAM,YAAY,GAAA,EAAI;AAC5B,IAAA,MAAM,YAAY,IAAA,CAAK,GAAA,CAAA,CAAK,MAAM,QAAA,IAAY,GAAA,EAAM,IAAI,EAAE,CAAA;AAC1D,IAAA,QAAA,GAAW,GAAA;AAGX,IAAA,IAAI,eAAe,mBAAA,EAAqB;AACtC,MAAA,gBAAA,IAAoB,SAAA,GAAY,GAAA;AAAA,IAClC;AAEA,IAAA,IAAI,MAAA,CAAO,eAAe,IAAA,EAAM;AAC9B,MAAA,UAAA,GAAa,KAAK,GAAA,CAAI,CAAA,EAAG,UAAA,GAAa,SAAA,IAAa,kBAAkB,GAAA,CAAK,CAAA;AAC1E,MAAA,MAAA,CAAO,cAAc,UAAU,CAAA;AAM/B,MAAA,MAAM,oBAAA,GAAuB,OAAO,iBAAA,EAAkB;AACtD,MAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,oBAAA,EAAsB,YAAA,EAAc,aAAa,CAAA;AAElF,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA,KAAA,GAAQ,MAAA,CAAO,KAAA;AACf,QAAA,OAAA,GAAU,MAAA,CAAO,OAAA;AACjB,QAAA,OAAA,GAAU,MAAA,CAAO,OAAA;AAAA,MACnB;AAEA,MAAA,IAAI,cAAc,CAAA,EAAG;AACnB,QAAA,MAAA,CAAO,aAAA,EAAc;AACrB,QAAA,YAAA,IAAe;AACf,QAAA,YAAA,GAAe,IAAA;AACf,QAAA,UAAA,GAAa,CAAA;AAEb,QAAA,QAAA,GAAW,OAAO,iBAAA,EAAkB;AACpC,QAAA,IAAI,CAAC,OAAO,cAAA,EAAgB;AAC1B,UAAA,mBAAA,EAAoB;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AAEA,IAAA,KAAA,GAAQ,MAAA,CAAO,KAAK,SAAS,CAAA;AAC7B,IAAA,UAAA,GAAa,MAAA,CAAO,UAAA;AACpB,IAAA,IAAA,GAAO,UAAA,GAAa,CAAA,GAAI,KAAA,CAAM,UAAA,GAAa,CAAC,CAAA,GAAK,IAAA;AAEjD,IAAA,GAAA,CAAI,SAAA,CAAU,CAAA,EAAG,CAAA,EAAG,YAAA,EAAc,aAAa,CAAA;AAE/C,IAAA,IAAI,MAAA,CAAO,cAAA,IAAkB,MAAA,CAAO,UAAA,KAAe,IAAA,EAAM;AACvD,MAAA,QAAA,GAAW,OAAO,iBAAA,EAAkB;AACpC,MAAA,mBAAA,EAAoB;AAAA,IACtB;AAEA,IAAA,YAAA,EAAa;AACb,IAAA,SAAA,EAAU;AACV,IAAA,QAAA,EAAS;AAET,IAAA,WAAA,GAAc,sBAAsB,MAAM,CAAA;AAAA,EAC5C;AAGA,EAAA,QAAA,GAAW,OAAO,iBAAA,EAAkB;AACpC,EAAA,mBAAA,EAAoB;AAEpB,EAAA,IAAI,CAAC,OAAO,cAAA,EAAgB;AAC1B,IAAA,mBAAA,EAAoB;AAAA,EACtB;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,GAAQ;AACN,MAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,QAAA;AAAA,MACF;AAEA,MAAA,QAAA,GAAW,YAAY,GAAA,EAAI;AAC3B,MAAA,MAAA,EAAO;AAAA,IACT,CAAA;AAAA,IAEA,IAAA,GAAO;AACL,MAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,QAAA;AAAA,MACF;AAEA,MAAA,oBAAA,CAAqB,WAAW,CAAA;AAChC,MAAA,WAAA,GAAc,IAAA;AACd,MAAA,MAAA,CAAO,qBAAA,EAAsB;AAAA,IAC/B,CAAA;AAAA,IAEA,KAAA,GAAQ;AACN,MAAA,MAAA,CAAO,KAAA,EAAM;AACb,MAAA,KAAA,GAAQ,EAAC;AACT,MAAA,IAAA,GAAO,IAAA;AAAA,IACT,CAAA;AAAA,IAEA,OAAA,GAAU;AACR,MAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,QAAA,oBAAA,CAAqB,WAAW,CAAA;AAChC,QAAA,WAAA,GAAc,IAAA;AAAA,MAChB;AAAA,IACF,CAAA;AAAA,IAEA,GAAG,mBAAmB,MAAM,CAAA;AAAA,IAE5B,OAAA,CAAQ,QAAkBC,QAAAA,EAAuC;AAC/D,MAAA,IAAI,iBAAiB,IAAA,EAAM;AACzB,QAAA,MAAA,CAAO,aAAA,EAAc;AACrB,QAAA,YAAA,EAAa;AACb,QAAA,YAAA,GAAe,IAAA;AACf,QAAA,UAAA,GAAa,CAAA;AAAA,MACf;AAEA,MAAA,eAAA,GAAkBA,UAAS,QAAA,IAAY,yBAAA;AACvC,MAAA,UAAA,GAAa,CAAA;AAEb,MAAA,MAAA,CAAO,UAAA,CAAW,MAAA,EAAQA,QAAAA,EAAS,aAAa,CAAA;AAEhD,MAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACpC,QAAA,YAAA,GAAe,OAAA;AAAA,MACjB,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;;;ACtcA,IAAM,kBAAA,GAAqB,GAAA;AAE3B,IAAMC,gBAAuC,EAAC;AAE9C,SAAS,kBAAA,CAAmB,GAAA,EAAc,KAAA,EAAe,OAAA,EAAiB,OAAA,EAAyB;AACjG,EAAA,IAAI,GAAA,CAAI,MAAA,GAAS,CAAA,EAAG,OAAO,EAAA;AAC3B,EAAA,MAAM,EAAA,GAAK,CAAC,CAAA,KAAA,CAAc,CAAA,CAAE,IAAI,KAAA,GAAQ,OAAA,EAAS,QAAQ,CAAC,CAAA;AAC1D,EAAA,MAAM,EAAA,GAAK,CAAC,CAAA,KAAA,CAAc,CAAA,CAAE,IAAI,KAAA,GAAQ,OAAA,EAAS,QAAQ,CAAC,CAAA;AAC1D,EAAA,IAAI,CAAA,GAAI,CAAA,CAAA,EAAI,EAAA,CAAG,GAAA,CAAI,CAAC,CAAE,CAAC,CAAA,CAAA,EAAI,EAAA,CAAG,GAAA,CAAI,CAAC,CAAE,CAAC,CAAA,CAAA;AACtC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,QAAQ,CAAA,EAAA,EAAK;AACnC,IAAA,CAAA,IAAK,CAAA,EAAA,EAAK,EAAA,CAAG,GAAA,CAAI,CAAC,CAAE,CAAC,CAAA,CAAA,EAAI,EAAA,CAAG,GAAA,CAAI,CAAC,CAAE,CAAC,CAAA,CAAA;AAAA,EACtC;AACA,EAAA,OAAO,CAAA,GAAI,IAAA;AACb;AAEA,SAAS,oBAAoB,QAAA,EAA6B;AACxD,EAAA,MAAM,MAAA,GAAS,QAAA,CAAS,MAAA,IAAU,IAAA,CAAK,EAAA,GAAK,CAAA;AAC5C,EAAA,MAAM,OAAA,GAAU,IAAA,CAAK,IAAA,CAAK,MAAA,GAAS,EAAE,CAAA;AACrC,EAAA,MAAM,MAAe,KAAA,CAAM,IAAA,CAAK,EAAE,MAAA,EAAQ,SAAS,CAAA;AACnD,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,OAAA,EAAS,CAAA,EAAA,EAAK;AAChC,IAAA,MAAM,CAAA,GAAK,CAAA,IAAK,OAAA,GAAU,CAAA,CAAA,GAAM,MAAA;AAChC,IAAA,GAAA,CAAI,CAAC,CAAA,GAAI,QAAA,CAAS,UAAA,GAAa,QAAA,CAAS,UAAA,CAAW,CAAC,CAAA,GAAI,QAAA,CAAS,EAAA,CAAG,CAAA,EAAG,CAAA,EAAGA,aAAY,CAAA;AAAA,EACxF;AACA,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,GAAG,GAAA,EAAyB;AACnC,EAAA,OAAO,QAAA,CAAS,eAAA,CAAgB,4BAAA,EAA8B,GAAG,CAAA;AACnE;AAMO,SAAS,kBAAkB,OAAA,EAA6C;AAC7E,EAAA,MAAM,EAAE,SAAA,EAAW,MAAA,EAAO,GAAI,OAAA;AAC9B,EAAA,MAAM,UAAA,GAAa,QAAQ,UAAA,IAAc,SAAA;AACzC,EAAA,MAAM,IAAA,GAAO;AAAA,IACX,aAAA,EAAe,QAAQ,aAAA,IAAiB,SAAA;AAAA,IACxC,UAAA;AAAA,IACA,SAAA,EAAW,QAAQ,SAAA,IAAa,UAAA;AAAA,IAChC,SAAA,EAAW,QAAQ,SAAA,IAAa;AAAA,GAClC;AAEA,EAAA,MAAM,IAAA,GAAO,UAAU,qBAAA,EAAsB;AAC7C,EAAA,MAAM,KAAA,GAAQ,KAAK,KAAA,IAAS,GAAA;AAC5B,EAAA,MAAM,MAAA,GAAS,KAAK,MAAA,IAAU,GAAA;AAC9B,EAAA,MAAM,UAAA,GACJ,OAAA,CAAQ,UAAA,IAAc,IAAA,CAAK,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,KAAK,GAAA,CAAI,KAAA,EAAO,MAAM,CAAA,GAAI,GAAG,CAAC,CAAA;AAEhF,EAAA,MAAM,GAAA,GAAM,GAAG,KAAK,CAAA;AACpB,EAAA,GAAA,CAAI,YAAA,CAAa,OAAA,EAAS,MAAA,CAAO,KAAK,CAAC,CAAA;AACvC,EAAA,GAAA,CAAI,YAAA,CAAa,QAAA,EAAU,MAAA,CAAO,MAAM,CAAC,CAAA;AACzC,EAAA,GAAA,CAAI,aAAa,SAAA,EAAW,CAAA,IAAA,EAAO,KAAK,CAAA,CAAA,EAAI,MAAM,CAAA,CAAE,CAAA;AACpD,EAAA,GAAA,CAAI,YAAA,CAAa,QAAQ,KAAK,CAAA;AAC9B,EAAA,GAAA,CAAI,YAAA,CAAa,YAAA,EAAc,IAAA,CAAK,SAAS,CAAA;AAE7C,EAAA,MAAM,OAAA,GAAU,GAAG,OAAO,CAAA;AAC1B,EAAA,OAAA,CAAQ,cAAc,IAAA,CAAK,SAAA;AAC3B,EAAA,GAAA,CAAI,YAAY,OAAO,CAAA;AAEvB,EAAA,MAAM,YAAA,GAAe,GAAG,MAAM,CAAA;AAC9B,EAAA,YAAA,CAAa,YAAA,CAAa,QAAQ,MAAM,CAAA;AACxC,EAAA,YAAA,CAAa,YAAA,CAAa,QAAA,EAAU,IAAA,CAAK,aAAa,CAAA;AACtD,EAAA,YAAA,CAAa,YAAA,CAAa,gBAAA,EAAkB,MAAA,CAAO,wBAAwB,CAAC,CAAA;AAC5E,EAAA,YAAA,CAAa,YAAA,CAAa,gBAAgB,KAAK,CAAA;AAC/C,EAAA,GAAA,CAAI,YAAY,YAAY,CAAA;AAE5B,EAAA,MAAM,aAAA,GAAgB,GAAG,MAAM,CAAA;AAC/B,EAAA,aAAA,CAAc,YAAA,CAAa,QAAQ,MAAM,CAAA;AACzC,EAAA,aAAA,CAAc,YAAA,CAAa,QAAA,EAAU,IAAA,CAAK,aAAa,CAAA;AACvD,EAAA,aAAA,CAAc,YAAA,CAAa,gBAAgB,KAAK,CAAA;AAChD,EAAA,aAAA,CAAc,YAAA,CAAa,cAAc,QAAQ,CAAA;AACjD,EAAA,GAAA,CAAI,YAAY,aAAa,CAAA;AAE7B,EAAA,MAAM,aAAA,GAAgB,GAAG,MAAM,CAAA;AAC/B,EAAA,aAAA,CAAc,YAAA,CAAa,QAAQ,MAAM,CAAA;AACzC,EAAA,aAAA,CAAc,YAAA,CAAa,QAAA,EAAU,IAAA,CAAK,aAAa,CAAA;AACvD,EAAA,aAAA,CAAc,YAAA,CAAa,gBAAgB,KAAK,CAAA;AAChD,EAAA,aAAA,CAAc,YAAA,CAAa,cAAc,QAAQ,CAAA;AACjD,EAAA,GAAA,CAAI,YAAY,aAAa,CAAA;AAE7B,EAAA,IAAI,eAAA,GAAkB,EAAA;AACtB,EAAA,IAAI,eAAA,GAAkB,EAAA;AAEtB,EAAA,MAAM,aAA+B,EAAC;AACtC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,kBAAA,EAAoB,CAAA,EAAA,EAAK;AAC3C,IAAA,MAAM,IAAA,GAAO,GAAG,MAAM,CAAA;AACtB,IAAA,IAAA,CAAK,YAAA,CAAa,MAAA,EAAQ,IAAA,CAAK,UAAU,CAAA;AACzC,IAAA,GAAA,CAAI,YAAY,IAAI,CAAA;AACpB,IAAA,UAAA,CAAW,KAAK,IAAI,CAAA;AAAA,EACtB;AAEA,EAAA,MAAM,UAAA,GAAa,GAAG,QAAQ,CAAA;AAC9B,EAAA,UAAA,CAAW,YAAA,CAAa,MAAA,EAAQ,IAAA,CAAK,SAAS,CAAA;AAC9C,EAAA,UAAA,CAAW,YAAA,CAAa,GAAA,EAAK,MAAA,CAAO,UAAU,CAAC,CAAA;AAC/C,EAAA,GAAA,CAAI,YAAY,UAAU,CAAA;AAE1B,EAAA,SAAA,CAAU,YAAY,GAAG,CAAA;AAEzB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,OAAA,GAAU,CAAA;AAEd,EAAA,SAAS,gBAAgBC,SAAAA,EAAmB;AAC1C,IAAA,MAAM,CAAA,GAAI,iBAAA,CAAkBA,SAAAA,EAAU,KAAA,EAAO,MAAM,CAAA;AACnD,IAAA,IAAI,CAAA,EAAG;AACL,MAAA,KAAA,GAAQ,CAAA,CAAE,KAAA;AACV,MAAA,OAAA,GAAU,CAAA,CAAE,OAAA;AACZ,MAAA,OAAA,GAAU,CAAA,CAAE,OAAA;AAAA,IACd;AAAA,EACF;AAGA,EAAA,SAAS,GAAG,CAAA,EAAkB;AAC5B,IAAA,OAAO,CAAA,CAAE,IAAI,KAAA,GAAQ,OAAA;AAAA,EACvB;AACA,EAAA,SAAS,GAAG,CAAA,EAAkB;AAC5B,IAAA,OAAO,CAAA,CAAE,IAAI,KAAA,GAAQ,OAAA;AAAA,EACvB;AAEA,EAAA,SAAS,eAAeA,SAAAA,EAAmB;AACzC,IAAA,YAAA,CAAa,aAAa,GAAA,EAAK,kBAAA,CAAmBA,WAAU,KAAA,EAAO,OAAA,EAAS,OAAO,CAAC,CAAA;AAAA,EACtF;AAEA,EAAA,MAAM,QAAA,GAAW,OAAO,iBAAA,EAAkB;AAC1C,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAExB,EAAA,IAAI,CAAC,OAAO,cAAA,EAAgB;AAC1B,IAAA,cAAA,CAAe,QAAQ,CAAA;AAAA,EACzB;AAEA,EAAA,SAAS,WAAA,CAAY,OAAgB,UAAA,EAAoB;AACvD,IAAA,IAAI,aAAa,CAAA,EAAG;AAClB,MAAA,KAAA,MAAW,KAAK,UAAA,EAAY;AAC1B,QAAA,CAAA,CAAE,YAAA,CAAa,KAAK,EAAE,CAAA;AAAA,MACxB;AACA,MAAA;AAAA,IACF;AAMA,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,UAAA,GAAa,GAAG,CAAA,EAAA,EAAK;AACvC,MAAA,MAAM,EAAE,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,GAAA,EAAK,OAAA,EAAQ,GAAI,gBAAA;AAAA,QAC1D,KAAA;AAAA,QACA,CAAA;AAAA,QACA,UAAA;AAAA,QACA,EAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,MAAM,IAAI,CAAA,CAAA,EAAI,GAAA,CAAI,QAAQ,CAAC,CAAC,IAAI,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,KAAK,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,EAAI,IAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,EAAA,EAAK,IAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,CAAA,EAAI,GAAA,CAAI,QAAQ,CAAC,CAAC,CAAA,EAAA,EAAK,GAAA,CAAI,QAAQ,CAAC,CAAC,IAAI,GAAA,CAAI,OAAA,CAAQ,CAAC,CAAC,CAAA,EAAA,CAAA;AAE7J,MAAA,UAAA,CAAW,CAAC,CAAA,CAAG,YAAA,CAAa,GAAA,EAAK,CAAC,CAAA;AAClC,MAAA,UAAA,CAAW,CAAC,CAAA,CAAG,YAAA,CAAa,gBAAgB,OAAA,CAAQ,OAAA,CAAQ,CAAC,CAAC,CAAA;AAAA,IAChE;AAGA,IAAA,KAAA,IAAS,IAAI,UAAA,GAAa,CAAA,EAAG,CAAA,GAAI,UAAA,CAAW,QAAQ,CAAA,EAAA,EAAK;AACvD,MAAA,UAAA,CAAW,CAAC,CAAA,CAAG,YAAA,CAAa,GAAA,EAAK,EAAE,CAAA;AAAA,IACrC;AAAA,EACF;AAEA,EAAA,SAAS,UAAA,CAAW,OAAgB,UAAA,EAAoB;AACtD,IAAA,IAAI,eAAe,CAAA,EAAG;AACpB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,IAAA,GAAO,KAAA,CAAM,UAAA,GAAa,CAAC,CAAA;AACjC,IAAA,MAAM,CAAA,GAAI,GAAG,IAAI,CAAA;AACjB,IAAA,MAAM,CAAA,GAAI,GAAG,IAAI,CAAA;AAEjB,IAAA,UAAA,CAAW,YAAA,CAAa,IAAA,EAAM,MAAA,CAAO,CAAC,CAAC,CAAA;AACvC,IAAA,UAAA,CAAW,YAAA,CAAa,IAAA,EAAM,MAAA,CAAO,CAAC,CAAC,CAAA;AAAA,EACzC;AAEA,EAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,MAAM,uBACJ,OAAO,MAAA,KAAW,eAAe,MAAA,CAAO,UAAA,CAAW,kCAAkC,CAAA,CAAE,OAAA;AAEzF,EAAA,IAAI,YAAA,GAAoC,IAAA;AACxC,EAAA,IAAI,eAAA,GAAkB,yBAAA;AACtB,EAAA,IAAI,WAAA,GAA+B,IAAA;AACnC,EAAA,IAAI,UAAA,GAAa,CAAA;AAEjB,EAAA,SAAS,WAAA,GAAc;AACrB,IAAA,MAAM,GAAA,GAAM,YAAY,GAAA,EAAI;AAC5B,IAAA,MAAM,KAAK,IAAA,CAAK,GAAA,CAAA,CAAK,MAAM,QAAA,IAAY,GAAA,EAAM,IAAI,EAAE,CAAA;AACnD,IAAA,QAAA,GAAW,GAAA;AAEX,IAAA,IAAI,MAAA,CAAO,eAAe,IAAA,EAAM;AAC9B,MAAA,UAAA,GAAa,KAAK,GAAA,CAAI,CAAA,EAAG,UAAA,GAAa,EAAA,IAAM,kBAAkB,GAAA,CAAK,CAAA;AACnE,MAAA,MAAA,CAAO,cAAc,UAAU,CAAA;AAE/B,MAAA,IAAI,eAAA,EAAiB;AACnB,QAAA,aAAA,CAAc,YAAA,CAAa,KAAK,eAAe,CAAA;AAC/C,QAAA,aAAA,CAAc,YAAA,CAAa,cAAc,SAAS,CAAA;AAClD,QAAA,aAAA,CAAc,YAAA;AAAA,UACZ,gBAAA;AAAA,UACA,MAAA,CAAA,CAAQ,CAAA,GAAI,UAAA,IAAc,wBAAwB;AAAA,SACpD;AAAA,MACF;AAEA,MAAA,IAAI,eAAA,EAAiB;AACnB,QAAA,aAAA,CAAc,YAAA,CAAa,KAAK,eAAe,CAAA;AAC/C,QAAA,aAAA,CAAc,YAAA,CAAa,cAAc,SAAS,CAAA;AAClD,QAAA,aAAA,CAAc,YAAA,CAAa,gBAAA,EAAkB,MAAA,CAAO,UAAA,GAAa,wBAAwB,CAAC,CAAA;AAAA,MAC5F;AAEA,MAAA,IAAI,cAAc,CAAA,EAAG;AACnB,QAAA,MAAA,CAAO,aAAA,EAAc;AACrB,QAAA,YAAA,IAAe;AACf,QAAA,YAAA,GAAe,IAAA;AACf,QAAA,WAAA,GAAc,IAAA;AACd,QAAA,UAAA,GAAa,CAAA;AACb,QAAA,eAAA,GAAkB,EAAA;AAClB,QAAA,eAAA,GAAkB,EAAA;AAClB,QAAA,aAAA,CAAc,YAAA,CAAa,cAAc,QAAQ,CAAA;AACjD,QAAA,aAAA,CAAc,YAAA,CAAa,cAAc,QAAQ,CAAA;AAEjD,QAAA,MAAM,WAAA,GAAc,OAAO,iBAAA,EAAkB;AAC7C,QAAA,eAAA,CAAgB,WAAW,CAAA;AAC3B,QAAA,cAAA,CAAe,WAAW,CAAA;AAAA,MAC5B;AAAA,IACF;AAEA,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,EAAE,CAAA;AAC5B,IAAA,MAAM,aAAa,MAAA,CAAO,UAAA;AAE1B,IAAA,IAAI,MAAA,CAAO,cAAA,IAAkB,MAAA,CAAO,UAAA,KAAe,IAAA,EAAM;AACvD,MAAA,MAAM,YAAA,GAAe,OAAO,iBAAA,EAAkB;AAC9C,MAAA,eAAA,CAAgB,YAAY,CAAA;AAC5B,MAAA,cAAA,CAAe,YAAY,CAAA;AAAA,IAC7B;AAEA,IAAA,WAAA,CAAY,OAAO,UAAU,CAAA;AAC7B,IAAA,UAAA,CAAW,OAAO,UAAU,CAAA;AAE5B,IAAA,IAAI,CAAC,oBAAA,EAAsB;AACzB,MAAA,WAAA,GAAc,sBAAsB,WAAW,CAAA;AAAA,IACjD;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,GAAQ;AACN,MAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,QAAA;AAAA,MACF;AACA,MAAA,QAAA,GAAW,YAAY,GAAA,EAAI;AAC3B,MAAA,WAAA,EAAY;AAAA,IACd,CAAA;AAAA,IAEA,IAAA,GAAO;AACL,MAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,QAAA;AAAA,MACF;AACA,MAAA,oBAAA,CAAqB,WAAW,CAAA;AAChC,MAAA,WAAA,GAAc,IAAA;AACd,MAAA,MAAA,CAAO,qBAAA,EAAsB;AAAA,IAC/B,CAAA;AAAA,IAEA,KAAA,GAAQ;AACN,MAAA,MAAA,CAAO,KAAA,EAAM;AAAA,IACf,CAAA;AAAA,IAEA,OAAA,GAAU;AACR,MAAA,IAAI,gBAAgB,IAAA,EAAM;AACxB,QAAA,oBAAA,CAAqB,WAAW,CAAA;AAChC,QAAA,WAAA,GAAc,IAAA;AAAA,MAChB;AACA,MAAA,GAAA,CAAI,MAAA,EAAO;AAAA,IACb,CAAA;AAAA,IAEA,GAAG,mBAAmB,MAAM,CAAA;AAAA,IAE5B,OAAA,CAAQ,QAAkBF,QAAAA,EAAuC;AAC/D,MAAA,IAAI,iBAAiB,IAAA,EAAM;AACzB,QAAA,MAAA,CAAO,aAAA,EAAc;AACrB,QAAA,YAAA,EAAa;AACb,QAAA,YAAA,GAAe,IAAA;AACf,QAAA,UAAA,GAAa,CAAA;AACb,QAAA,aAAA,CAAc,YAAA,CAAa,cAAc,QAAQ,CAAA;AACjD,QAAA,aAAA,CAAc,YAAA,CAAa,cAAc,QAAQ,CAAA;AAAA,MACnD;AAEA,MAAA,eAAA,GAAkBA,UAAS,QAAA,IAAY,yBAAA;AACvC,MAAA,WAAA,GAAc,MAAA;AACd,MAAA,UAAA,GAAa,CAAA;AAEb,MAAA,MAAM,eAAA,GAAkB,OAAO,iBAAA,EAAkB;AACjD,MAAA,eAAA,GAAkB,kBAAA,CAAmB,eAAA,EAAiB,KAAA,EAAO,OAAA,EAAS,OAAO,CAAA;AAE7E,MAAA,MAAA,CAAO,UAAA,CAAW,MAAA,EAAQA,QAAAA,EAAS,aAAa,CAAA;AAEhD,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,cAAA,GAAiB,oBAAoB,MAAM,CAAA;AACjD,QAAA,eAAA,GAAkB,kBAAA,CAAmB,cAAA,EAAgB,KAAA,EAAO,OAAA,EAAS,OAAO,CAAA;AAAA,MAC9E;AAEA,MAAA,OAAO,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACpC,QAAA,YAAA,GAAe,OAAA;AAAA,MACjB,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF;AAaO,SAAS,eAAA,CACd,SAAA,EACA,QAAA,EACA,OAAA,EACgB;AAChB,EAAA,MAAM,EAAE,WAAA,EAAa,GAAG,YAAA,EAAa,GAAI,WAAW,EAAC;AACrD,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,QAAA,EAAU,WAAW,CAAA;AACjD,EAAA,OAAO,kBAAkB,EAAE,SAAA,EAAW,MAAA,EAAQ,GAAG,cAAc,CAAA;AACjE;;;ACrWA,IAAMG,OAAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AASzB,SAAS,UAAA,CAAW,CAAA,EAAW,KAAA,EAAe,OAAA,EAAiC;AAC7E,EAAA,MAAM,CAAA,GAAI,IAAA,EACR,CAAA,GAAI,IAAA,EACJ,EAAA,GAAK,KAAA;AACP,EAAA,MAAM,CAAA,GAAI,KAAK,GAAA,CAAI,CAAC,GAClB,CAAA,GAAI,IAAA,CAAK,IAAI,CAAC,CAAA;AAChB,EAAA,MAAM,KAAA,GAAQ,IAAI,CAAA,GAAI,CAAA;AACtB,EAAA,OAAO;AAAA,IACL,CAAA,EAAI,CAAA,IAAK,CAAA,GAAI,CAAA,GAAI,KAAM,KAAA,GAAQ,EAAA;AAAA,IAC/B,CAAA,EAAI,CAAA,GAAI,CAAA,IAAK,CAAA,GAAI,IAAI,CAAA,CAAA,GAAM;AAAA,GAC7B;AACF;AAMO,IAAM,QAAA,GAAqB;AAAA,EAChC,IAAA,EAAM,YAAA;AAAA,EACN,EAAA,EAAI,UAAA;AAAA,EACJ,MAAA,EAAQA,OAAAA;AAAA,EACR,KAAA,EAAO;AACT;;;AC/BA,IAAMA,OAAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AAEzB,SAAS,SAAA,CAAU,CAAA,EAAW,KAAA,EAAe,OAAA,EAAiC;AAC5E,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AACpB,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AACpB,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,IAAI,CAAA,GAAI,CAAA;AAAA,IACX,CAAA,EAAG,IAAI,CAAA,GAAI;AAAA,GACb;AACF;AAMO,IAAM,OAAA,GAAoB;AAAA,EAC/B,IAAA,EAAM,SAAA;AAAA,EACN,EAAA,EAAI,SAAA;AAAA,EACJ,MAAA,EAAQA,OAAAA;AAAA,EACR,KAAA,EAAO;AACT;;;ACpBA,IAAMA,OAAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AAEzB,SAAS,SAAA,CAAU,CAAA,EAAW,KAAA,EAAe,OAAA,EAAiC;AAC5E,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,IAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AAAA,IACnC,CAAA,EAAG,IAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC;AAAA,GACrC;AACF;AAMO,IAAM,OAAA,GAAoB;AAAA,EAC/B,IAAA,EAAM,SAAA;AAAA,EACN,EAAA,EAAI,SAAA;AAAA,EACJ,MAAA,EAAQA,OAAAA;AAAA,EACR,KAAA,EAAO;AACT;;;AClBA,IAAMA,OAAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AAEzB,SAAS,aAAA,CAAc,CAAA,EAAW,KAAA,EAAe,OAAA,EAAiC;AAChF,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,IAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AAAA,IACnC,CAAA,EAAG,IAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC;AAAA,GACrC;AACF;AAMO,IAAM,WAAA,GAAwB;AAAA,EACnC,IAAA,EAAM,kBAAA;AAAA,EACN,EAAA,EAAI,aAAA;AAAA,EACJ,MAAA,EAAQA,OAAAA;AAAA,EACR,KAAA,EAAO;AACT;;;AClBA,IAAMA,OAAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AAEzB,SAAS,cAAA,CAAe,CAAA,EAAW,KAAA,EAAe,OAAA,EAAiC;AACjF,EAAA,MAAM,IAAI,CAAA,GAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,IAAI,GAAG,CAAA;AACvC,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,IAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AAAA,IACvC,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,IAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC;AAAA,GACzC;AACF;AAEA,SAAS,uBAAuB,CAAA,EAAkB;AAEhD,EAAA,MAAM,CAAA,GAAI,KAAA;AACV,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,IAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AAAA,IACvC,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,IAAI,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC;AAAA,GACzC;AACF;AAMO,IAAM,YAAA,GAAyB;AAAA,EACpC,IAAA,EAAM,aAAA;AAAA,EACN,EAAA,EAAI,cAAA;AAAA,EACJ,MAAA,EAAQA,OAAAA;AAAA,EACR,KAAA,EAAO,GAAA;AAAA,EACP,UAAA,EAAY;AACd;;;AC7BA,IAAMA,OAAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AAEzB,SAAS,aAAA,CAAc,CAAA,EAAW,IAAA,EAAc,OAAA,EAAiC;AAC/E,EAAA,MAAM,MAAM,IAAA,GAAO,IAAA;AACnB,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,IAAI,GAAG,CAAA;AAAA,IACvB,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC;AAAA,GACnB;AACF;AAMO,IAAM,WAAA,GAAwB;AAAA,EACnC,IAAA,EAAM,eAAA;AAAA,EACN,EAAA,EAAI,aAAA;AAAA,EACJ,MAAA,EAAQA,OAAAA;AAAA,EACR,KAAA,EAAO,CAAA;AAAA,EACP,QAAA,EAAU;AACZ;;;ACpBA,IAAMA,OAAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AAEzB,SAAS,aAAA,CAAc,CAAA,EAAW,IAAA,EAAc,OAAA,EAAiC;AAC/E,EAAA,MAAM,MAAM,IAAA,GAAO,IAAA;AACnB,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,IAAI,GAAG,CAAA;AAAA,IACvB,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC;AAAA,GACnB;AACF;AAMO,IAAM,WAAA,GAAwB;AAAA,EACnC,IAAA,EAAM,eAAA;AAAA,EACN,EAAA,EAAI,aAAA;AAAA,EACJ,MAAA,EAAQA,OAAAA;AAAA,EACR,KAAA,EAAO,GAAA;AAAA,EACP,QAAA,EAAU;AACZ;;;ACpBA,IAAMA,OAAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AAEzB,SAAS,MAAA,CAAO,CAAA,EAAW,IAAA,EAAc,OAAA,EAAiC;AACxE,EAAA,MAAM,IAAI,IAAA,GAAO,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,OAAO,IAAI,CAAA;AAC5C,EAAA,MAAM,CAAA,GAAI,KAAK,GAAA,CAAI,CAAC,GAClB,CAAA,GAAI,IAAA,CAAK,IAAI,CAAC,CAAA;AAChB,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG,CAAC,CAAA;AAAA,IACzC,CAAA,EAAG,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG,CAAC;AAAA,GAC3C;AACF;AAMO,IAAM,IAAA,GAAiB;AAAA,EAC5B,IAAA,EAAM,eAAA;AAAA,EACN,EAAA,EAAI,MAAA;AAAA,EACJ,MAAA,EAAQA,OAAAA;AAAA,EACR,KAAA,EAAO,CAAA;AAAA,EACP,QAAA,EAAU;AACZ;;;ACtBA,IAAMA,QAAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AAEzB,SAAS,OAAA,CAAQ,CAAA,EAAW,KAAA,EAAe,OAAA,EAAiC;AAC1E,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AACxB,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AAAA,IACjB,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC;AAAA,GACnB;AACF;AAMO,IAAM,KAAA,GAAkB;AAAA,EAC7B,IAAA,EAAM,YAAA;AAAA,EACN,EAAA,EAAI,OAAA;AAAA,EACJ,MAAA,EAAQA,QAAAA;AAAA,EACR,KAAA,EAAO;AACT;;;ACnBA,IAAMA,QAAAA,GAAS,KAAK,EAAA,GAAK,CAAA;AAEzB,SAAS,OAAA,CAAQ,CAAA,EAAW,KAAA,EAAe,OAAA,EAAiC;AAC1E,EAAA,MAAM,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AACxB,EAAA,OAAO;AAAA,IACL,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AAAA,IACjB,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,GAAA,CAAI,CAAC;AAAA,GACnB;AACF;AAMO,IAAM,KAAA,GAAkB;AAAA,EAC7B,IAAA,EAAM,YAAA;AAAA,EACN,EAAA,EAAI,OAAA;AAAA,EACJ,MAAA,EAAQA,QAAAA;AAAA,EACR,KAAA,EAAO;AACT;;;ACSO,IAAM,MAAA,GAAS;AAAA,EACpB,QAAA;AAAA,EACA,YAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA,WAAA;AAAA,EACA;AACF;;;ACKO,SAAS,YAAA,CACd,MAAA,EACA,QAAA,EACA,OAAA,EACgB;AAChB,EAAA,MAAM,EAAE,WAAA,EAAa,GAAG,YAAA,EAAa,GAAI,WAAW,EAAC;AACrD,EAAA,MAAM,MAAA,GAAS,YAAA,CAAa,QAAA,EAAU,WAAW,CAAA;AAEjD,EAAA,OAAO,eAAe,EAAE,MAAA,EAAQ,MAAA,EAAQ,GAAG,cAAc,CAAA;AAC3D","file":"index.js","sourcesContent":["import type { CurveDef, Engine, JumpOptions, MorpStrategy, Point, SeekOptions } from \"./types\";\n\nconst TWO_PI = Math.PI * 2;\nconst POINTS_PER_PERIOD_UNIT = 50;\n\ntype SpeedTransition = {\n from: number;\n to: number;\n elapsed: number;\n duration: number;\n resolve: () => void;\n reject: (err: Error) => void;\n};\n\n/** Linearly interpolate from start to end by factor t (0→1) */\nfunction lerp(start: number, end: number, t: number): number {\n return start + (end - start) * t;\n}\n\n/** Reused across all curve fn calls — params is never populated, allocation is wasteful */\nconst EMPTY_PARAMS: Record<string, number> = {};\n\n/**\n * A fixed-size list of points with first in, last out method\n * The oldest entry is automatically discarded when the list is at capacity\n *\n * Note: `result.length` is *never* changed,\n * so callers use the separate `count` getter to know valid size\n */\nclass CircularBuffer {\n private data: Array<Point>;\n private result: Array<Point>;\n private capacity: number;\n private head: number = 0;\n private count: number = 0;\n\n constructor(capacity: number) {\n this.capacity = capacity;\n this.data = Array.from({ length: capacity }, () => ({ x: 0, y: 0 }));\n this.result = Array.from({ length: capacity }, () => ({ x: 0, y: 0 }));\n }\n\n /** Mutates in-place */\n push(x: number, y: number): void {\n const slot = this.data[this.head]!;\n\n slot.x = x;\n slot.y = y;\n this.head = (this.head + 1) % this.capacity;\n\n if (this.count < this.capacity) {\n this.count++;\n }\n }\n\n /**\n * Copies ordered points into the pre-allocated result buffer and returns it\n * Note: The *same* array reference is returned every call,\n * so `result.length` is also always `capacity`\n */\n toArray(): Array<Point> {\n const start = this.count < this.capacity ? 0 : this.head;\n\n for (let i = 0; i < this.count; i++) {\n const src = this.data[(start + i) % this.capacity]!;\n const dst = this.result[i]!;\n dst.x = src.x;\n dst.y = src.y;\n }\n\n return this.result;\n }\n\n clear(): void {\n this.head = 0;\n this.count = 0;\n }\n\n get length() {\n return this.count;\n }\n}\n\n/**\n * Creates the core simulation engine for a sarmal\n *\n * it runs a clock (time `t`), asks the curve for the current Point position at that time,\n * and remembers the last N positions so the renderer can draw the trail\n *\n * The engine is only responsible for math coordinates,\n * so it is not responsible for drawing or colors\n *\n * @param curveDef A curve definition\n * @param trailLength default: `120`\n */\n/** Normalised resolution of a CurveDef, with required fields filled in */\ntype ResolvedCurve = {\n name: string;\n fn: CurveDef[\"fn\"];\n period: number;\n speed: number;\n skeleton?: CurveDef[\"skeleton\"];\n skeletonFn?: CurveDef[\"skeletonFn\"];\n};\n\nfunction resolveCurve(curveDef: CurveDef): ResolvedCurve {\n const period = curveDef.period ?? TWO_PI;\n\n if (!Number.isFinite(period) || period <= 0) {\n throw new RangeError(`[sarmal] period must be a positive finite number, got ${period}`);\n }\n\n const speed = curveDef.speed ?? 1;\n\n if (!Number.isFinite(speed)) {\n throw new RangeError(`[sarmal] speed must be a finite number, got ${speed}`);\n }\n\n return {\n name: curveDef.name,\n fn: curveDef.fn,\n period,\n speed,\n skeleton: curveDef.skeleton,\n skeletonFn: curveDef.skeletonFn,\n };\n}\n\nexport function createEngine(curveDef: CurveDef, trailLength: number = 120): Engine {\n if (!Number.isFinite(trailLength) || trailLength <= 0) {\n throw new RangeError(\n `[sarmal] trailLength must be a positive finite number, got ${trailLength}`,\n );\n }\n\n let curve = resolveCurve(curveDef);\n const trail = new CircularBuffer(trailLength);\n let t = 0;\n let actualTime = 0;\n let userSpeedOverride: number | null = null;\n\n // Morph state which is `null` when not morphing\n let morphCurveB: ResolvedCurve | null = null;\n let _morphAlpha: number | null = null;\n let _morphStrategy: MorpStrategy = \"normalized\";\n\n // Speed transition state which is `null` when not transitioning\n let _speedTransition: SpeedTransition | null = null;\n\n /** Samples a resolved curve's skeleton at position `sampleT` */\n function sampleSkeleton(c: ResolvedCurve, sampleT: number): Point {\n if (c.skeletonFn) {\n return c.skeletonFn(sampleT);\n }\n if (c.skeleton === \"live\") {\n return c.fn(sampleT, actualTime, EMPTY_PARAMS);\n }\n return c.fn(sampleT, 0, EMPTY_PARAMS);\n }\n\n return {\n tick(deltaTime: number): Array<Point> {\n if (_speedTransition !== null) {\n // tick() receives dt in seconds, but SpeedTransition.duration is in milliseconds.\n // Convert dt to ms so the elapsed/duration ratio is dimensionless.\n _speedTransition.elapsed += deltaTime * 1000;\n const alpha = Math.min(_speedTransition.elapsed / _speedTransition.duration, 1);\n userSpeedOverride = lerp(_speedTransition.from, _speedTransition.to, alpha);\n if (alpha >= 1) {\n userSpeedOverride = _speedTransition.to;\n _speedTransition.resolve();\n _speedTransition = null;\n }\n }\n\n let effectiveSpeed = userSpeedOverride ?? curve.speed;\n if (morphCurveB !== null && _morphAlpha !== null) {\n effectiveSpeed = lerp(effectiveSpeed, morphCurveB.speed, _morphAlpha);\n }\n t = (t + effectiveSpeed * deltaTime) % curve.period;\n actualTime += deltaTime;\n\n if (morphCurveB !== null && _morphAlpha !== null) {\n const a = curve.fn(t, actualTime, EMPTY_PARAMS);\n const tB = _morphStrategy === \"normalized\" ? (t / curve.period) * morphCurveB.period : t;\n const b = morphCurveB.fn(tB, actualTime, EMPTY_PARAMS);\n trail.push(a.x + (b.x - a.x) * _morphAlpha, a.y + (b.y - a.y) * _morphAlpha);\n } else {\n const point = curve.fn(t, actualTime, EMPTY_PARAMS);\n trail.push(point.x, point.y);\n }\n\n return trail.toArray();\n },\n\n get trailCount() {\n return trail.length;\n },\n\n get isLiveSkeleton() {\n return curve.skeleton === \"live\";\n },\n\n get morphAlpha() {\n return _morphAlpha;\n },\n\n reset() {\n t = 0;\n actualTime = 0;\n trail.clear();\n },\n\n jump(newT: number, { clearTrail = false }: JumpOptions = {}) {\n t = ((newT % curve.period) + curve.period) % curve.period;\n if (clearTrail) {\n trail.clear();\n }\n },\n\n seek(targetT: number, { wrap = false, step = curve.period / trailLength }: SeekOptions = {}) {\n const advance = curve.speed * step;\n const target = ((targetT % curve.period) + curve.period) % curve.period;\n const targetTime = target / curve.speed;\n\n t = target;\n actualTime = targetTime;\n trail.clear();\n\n const pointsFromStart = Math.floor(target / advance) + 1;\n const count = wrap ? trailLength : Math.min(trailLength, pointsFromStart);\n\n for (let i = count - 1; i >= 0; i--) {\n const sampleT = target - i * advance;\n const wrappedT = ((sampleT % curve.period) + curve.period) % curve.period;\n const time = targetTime - i * step;\n const point = curve.fn(wrappedT, time, EMPTY_PARAMS);\n\n trail.push(point.x, point.y);\n }\n },\n\n startMorph(target: CurveDef, strategy: MorpStrategy = \"normalized\") {\n const resolvedTarget = resolveCurve(target);\n\n if (morphCurveB !== null && _morphAlpha !== null) {\n const frozenAlpha = _morphAlpha;\n const frozenA = curve;\n const frozenB = morphCurveB;\n const frozenStrategy = _morphStrategy;\n\n curve = {\n ...frozenB,\n fn: (sampleT: number, time: number, params: Record<string, number>) => {\n const a = frozenA.fn(sampleT, time, params);\n const tB =\n frozenStrategy === \"normalized\"\n ? (sampleT / frozenA.period) * frozenB.period\n : sampleT;\n const b = frozenB.fn(tB, time, params);\n return {\n x: a.x + (b.x - a.x) * frozenAlpha,\n y: a.y + (b.y - a.y) * frozenAlpha,\n };\n },\n };\n }\n\n _morphStrategy = strategy;\n morphCurveB = resolvedTarget;\n _morphAlpha = 0;\n },\n\n setMorphAlpha(alpha: number) {\n _morphAlpha = alpha;\n },\n\n completeMorph() {\n if (morphCurveB !== null) {\n // Normalized strategy drives `curveB` at `tB` = `(t / periodA) * periodB`\n // Remap `t` so the trail continues from the same position on `curveB`,\n // not from a raw `t` value that belongs to `curveA`'s smaller range.\n if (_morphStrategy === \"normalized\" && curve.period !== morphCurveB.period) {\n t = (t / curve.period) * morphCurveB.period;\n }\n curve = morphCurveB;\n }\n morphCurveB = null;\n _morphAlpha = null;\n },\n\n getSarmalSkeleton(): Array<Point> {\n const steps = Math.ceil(curve.period * POINTS_PER_PERIOD_UNIT);\n // oxlint-disable-next-line unicorn/no-new-array -- array is pre-allocated, filled immediately below\n const points: Array<Point> = new Array(steps);\n\n if (morphCurveB !== null && _morphAlpha !== null) {\n for (let i = 0; i < steps; i++) {\n const sampleT = (i / (steps - 1)) * curve.period;\n const a = sampleSkeleton(curve, sampleT);\n const tB =\n _morphStrategy === \"normalized\"\n ? (sampleT / curve.period) * morphCurveB.period\n : sampleT;\n const b = sampleSkeleton(morphCurveB, tB);\n\n points[i] = {\n x: a.x + (b.x - a.x) * _morphAlpha,\n y: a.y + (b.y - a.y) * _morphAlpha,\n };\n }\n return points;\n }\n\n for (let i = 0; i < steps; i++) {\n const sampleT = (i / (steps - 1)) * curve.period;\n points[i] = sampleSkeleton(curve, sampleT);\n }\n\n return points;\n },\n\n setSpeed(speed: number): void {\n if (!Number.isFinite(speed)) {\n throw new Error(\"speed must be a finite number\");\n }\n if (_speedTransition !== null) {\n _speedTransition.reject(new Error(\"Speed transition cancelled\"));\n _speedTransition = null;\n }\n userSpeedOverride = speed;\n },\n\n getSpeed(): number {\n return userSpeedOverride ?? curve.speed;\n },\n\n resetSpeed(): void {\n userSpeedOverride = null;\n },\n\n setSpeedOver(speed: number, duration: number): Promise<void> {\n if (!Number.isFinite(speed)) {\n throw new Error(\"speed must be a finite number\");\n }\n if (!Number.isFinite(duration) || duration <= 0) {\n throw new Error(\"duration must be a finite number greater than 0\");\n }\n\n if (_speedTransition !== null) {\n _speedTransition.reject(new Error(\"Speed transition cancelled\"));\n _speedTransition = null;\n }\n\n const from = userSpeedOverride ?? curve.speed;\n\n return new Promise<void>((resolve, reject) => {\n _speedTransition = { from, to: speed, elapsed: 0, duration, resolve, reject };\n });\n },\n\n cancelSpeedTransition(): void {\n if (_speedTransition !== null) {\n _speedTransition.reject(new Error(\"Speed transition cancelled\"));\n _speedTransition = null;\n }\n },\n };\n}\n","import type { Engine, Point } from \"./types\";\n\nexport const DEFAULT_MORPH_DURATION_MS = 300;\nexport const DEFAULT_SKELETON_OPACITY = 0.15;\n/** Fraction of the bounding box added as padding when fitting the curve to the viewport */\nexport const FIT_PADDING = 0.1;\n/** Higher values = sharper fade near the tail, more of the trail appears faint */\nexport const TRAIL_FADE_CURVE = 1.5;\nexport const TRAIL_MAX_OPACITY = 0.88;\n/** Stroke/line width at the tail */\nexport const TRAIL_MIN_WIDTH = 0.5;\n/** Stroke/line width at the head */\nexport const TRAIL_MAX_WIDTH = 2.5;\n\nexport interface TrailPoint {\n x: number;\n y: number;\n}\n\n/**\n * Computes the unit tangent vector at a point on the trail.\n * - Interior points: central difference (previous -> next)\n * - Endpoints: forward/backward difference\n */\nexport function computeTangent(trail: TrailPoint[], i: number): TrailPoint {\n const count = trail.length;\n if (count < 2) {\n return { x: 1, y: 0 };\n }\n\n if (i === 0) {\n const dx = trail[1]!.x - trail[0]!.x;\n const dy = trail[1]!.y - trail[0]!.y;\n const len = Math.sqrt(dx * dx + dy * dy) || 1;\n return { x: dx / len, y: dy / len };\n }\n\n if (i === count - 1) {\n const dx = trail[count - 1]!.x - trail[count - 2]!.x;\n const dy = trail[count - 1]!.y - trail[count - 2]!.y;\n const len = Math.sqrt(dx * dx + dy * dy) || 1;\n return { x: dx / len, y: dy / len };\n }\n\n const dx = trail[i + 1]!.x - trail[i - 1]!.x;\n const dy = trail[i + 1]!.y - trail[i - 1]!.y;\n const len = Math.sqrt(dx * dx + dy * dy) || 1;\n return { x: dx / len, y: dy / len };\n}\n\n/**\n * Computes the unit normal vector at a point on the trail.\n * The normal is perpendicular to the tangent, rotated 90° counter-clockwise\n */\nexport function computeNormal(trail: TrailPoint[], i: number): TrailPoint {\n const tangent = computeTangent(trail, i);\n return { x: -tangent.y, y: tangent.x };\n}\n\n/** The four pixel-space corners and per-segment style values for one ribbon quad */\nexport interface TrailQuad {\n /** Left corner at the tail end of this segment */\n l0x: number;\n l0y: number;\n /** Right corner at the tail end of this segment */\n r0x: number;\n r0y: number;\n /** Left corner at the head end of this segment */\n l1x: number;\n l1y: number;\n /** Right corner at the head end of this segment */\n r1x: number;\n r1y: number;\n /** Fill opacity for this segment (0–1) */\n opacity: number;\n /** Position along the trail (0 = tail, 1 = head) */\n progress: number;\n}\n\n/**\n * Computes the pixel-space quad corners and style for one ribbon segment.\n *\n * @param trail Full trail array\n * @param i Segment index (draws from point i to point i+1)\n * @param trailCount Number of active trail points\n * @param toX Convert a trail point to its pixel X coordinate\n * @param toY Convert a trail point to its pixel Y coordinate\n *\n * @see https://mattdesl.svbtle.com/drawing-lines-is-hard\n * DesLauriers: \"Triangulated Lines\" — expand points outward by half\n * the thickness on either side using normals to create thick lines.\n */\nexport function computeTrailQuad(\n trail: TrailPoint[],\n i: number,\n trailCount: number,\n toX: (p: TrailPoint) => number,\n toY: (p: TrailPoint) => number,\n): TrailQuad {\n const progress = i / (trailCount - 1);\n const nextProgress = (i + 1) / (trailCount - 1);\n const opacity = Math.pow(progress, TRAIL_FADE_CURVE) * TRAIL_MAX_OPACITY;\n const w0 = (TRAIL_MIN_WIDTH + progress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH)) / 2;\n const w1 = (TRAIL_MIN_WIDTH + nextProgress * (TRAIL_MAX_WIDTH - TRAIL_MIN_WIDTH)) / 2;\n\n const curr = trail[i]!;\n const next = trail[i + 1]!;\n const n0 = computeNormal(trail, i);\n const n1 = computeNormal(trail, i + 1);\n\n const cx = toX(curr);\n const cy = toY(curr);\n const nx = toX(next);\n const ny = toY(next);\n\n return {\n l0x: cx + n0.x * w0,\n l0y: cy + n0.y * w0,\n r0x: cx - n0.x * w0,\n r0y: cy - n0.y * w0,\n l1x: nx + n1.x * w1,\n l1y: ny + n1.y * w1,\n r1x: nx - n1.x * w1,\n r1y: ny - n1.y * w1,\n opacity,\n progress,\n };\n}\n\nexport interface BoundaryResult {\n scale: number;\n offsetX: number;\n offsetY: number;\n}\n\n/**\n * Computes how to map engine coordinates into a viewport of the given logical size.\n * ! Returns `null` if `pts` is empty\n * ! Throws if all points are identical\n *\n * Steps: find bounding box -> compute uniform scale that fits with padding -> center offsets\n */\nexport function computeBoundaries(\n pts: Point[],\n logicalWidth: number,\n logicalHeight: number,\n): BoundaryResult | null {\n if (pts.length === 0) return null;\n\n const first = pts[0]!;\n let minX = first.x,\n maxX = first.x,\n minY = first.y,\n maxY = first.y;\n\n for (const p of pts) {\n if (p.x < minX) {\n minX = p.x;\n }\n if (p.x > maxX) {\n maxX = p.x;\n }\n if (p.y < minY) {\n minY = p.y;\n }\n if (p.y > maxY) {\n maxY = p.y;\n }\n }\n\n const w = maxX - minX;\n const h = maxY - minY;\n\n if (w === 0 && h === 0) {\n throw new Error(\n \"[sarmal] Degenerate curve: all skeleton points are identical. \" +\n \"Check that your curve fn returns distinct points for different values of t.\",\n );\n }\n\n const scaleX = logicalWidth / (w * (1 + FIT_PADDING * 2));\n const scaleY = logicalHeight / (h * (1 + FIT_PADDING * 2));\n const scale = Math.min(scaleX, scaleY);\n\n return {\n scale,\n offsetX: (logicalWidth - w * scale) / 2 - minX * scale,\n offsetY: (logicalHeight - h * scale) / 2 - minY * scale,\n };\n}\n\n/**\n * Returns the engine methods that are pure pass-throughs on both renderers\n * The engine does not use `this`, so direct assignment is safe\n */\nexport function enginePassthroughs(engine: Engine) {\n return {\n jump: engine.jump,\n seek: engine.seek,\n setSpeed: engine.setSpeed,\n getSpeed: engine.getSpeed,\n resetSpeed: engine.resetSpeed,\n setSpeedOver: engine.setSpeedOver,\n };\n}\n","import type {\n CurveDef,\n MorphOptions,\n PalettePreset,\n Point,\n RendererOptions,\n SarmalInstance,\n TrailStyle,\n} from \"./types\";\nimport {\n DEFAULT_MORPH_DURATION_MS,\n DEFAULT_SKELETON_OPACITY,\n computeBoundaries,\n computeTrailQuad,\n enginePassthroughs,\n} from \"./renderer-shared\";\n\n// Re-exported so existing test imports (renderer.test.ts) keep working\nexport { computeTangent, computeNormal, TrailPoint } from \"./renderer-shared\";\n\nconst DEFAULT_SKELETON_COLOR = \"#ffffff\";\n\nconst GRADIENT = {\n bard: [\"#a855f7\", \"#3b82f6\", \"#14b8a6\", \"#ec4899\"],\n sunset: [\"#f97316\", \"#dc2626\", \"#9333ea\", \"#f472b6\"],\n ocean: [\"#1e3a8a\", \"#06b6d4\", \"#22d3ee\", \"#e0f2fe\"],\n ice: [\"#1e3a8a\", \"#67e8f9\"],\n fire: [\"#7f1d1d\", \"#fbbf24\"],\n forest: [\"#14532d\", \"#86efac\"],\n};\n\nconst PRESETS: Record<PalettePreset, string[]> = {\n bard: GRADIENT.bard,\n sunset: GRADIENT.sunset,\n ocean: GRADIENT.ocean,\n ice: GRADIENT.ice,\n fire: GRADIENT.fire,\n forest: GRADIENT.forest,\n};\n\n// ? exported for testing\nexport interface Rgb {\n r: number;\n g: number;\n b: number;\n}\n\n// ? exported for testing\nexport function hexToRgb(hex: string): Rgb {\n const n = parseInt(hex.slice(1), 16);\n return { r: n >> 16, g: (n >> 8) & 255, b: n & 255 };\n}\n\n// ? exported for testing\nexport const lerpRgb = (a: Rgb, b: Rgb, t: number) => ({\n r: Math.round(a.r + (b.r - a.r) * t),\n g: Math.round(a.g + (b.g - a.g) * t),\n b: Math.round(a.b + (b.b - a.b) * t),\n});\n\n/**\n * Gets a color from a palette based on position (0-1) with optional time-based cycling\n * ? Exported for testing.\n */\nexport function getPaletteColor(palette: string[], position: number, timeOffset: number = 0): Rgb {\n if (palette.length === 0) return { r: 255, g: 255, b: 255 };\n if (palette.length === 1) return hexToRgb(palette[0]!);\n\n const cyclePos = (position + timeOffset) % 1;\n const scaled = cyclePos * palette.length;\n const idx = Math.floor(scaled);\n const t = scaled - idx;\n\n const c1 = hexToRgb(palette[idx % palette.length]!);\n const c2 = hexToRgb(palette[(idx + 1) % palette.length]!);\n\n return lerpRgb(c1, c2, t);\n}\n\n// ? exported for testing\nexport function resolvePalette(\n palette: PalettePreset | string[] | undefined,\n trailStyle: TrailStyle,\n): string[] {\n if (Array.isArray(palette)) return palette;\n if (palette && palette in PRESETS) return PRESETS[palette as PalettePreset]!;\n return trailStyle === \"gradient-animated\" ? GRADIENT.bard : GRADIENT.ice;\n}\n\n// TODO: accept rgb(a)\nexport function hexToRgbComponents(hex: string): string {\n const n = parseInt(hex.slice(1), 16);\n return `${n >> 16},${(n >> 8) & 255},${n & 255}`;\n}\n\n/**\n * ! Exported purely so `applyDprSizing` can be unit-tested without a DOM\n */\nexport interface DprSizingTarget {\n width: number;\n height: number;\n style: { width: string; height: string };\n}\n\n/**\n * Applies DPR sizing to a target\n *\n * ! DO NOT REMOVE THE `style.width` and `style.height` ASSIGNMENTS\n *\n * A canvas with only `width`/`height` HTML attributes and no CSS derives\n * its displayed size from those attributes.\n * If we set `canvas.width = logicalWidth * dpr` to scale the drawing buffer for \"crispness\",\n * the element ALSO visually grows by the DPR factor\n * ! The bug is silent and sneaky. It just resulsts in a broken render without any obvious reasons\n *\n * @see https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Optimizing_canvas\n * MDN: \"If you don't set the CSS attributes, the intrinsic size of the canvas will be used as its display size\"\n *\n * @see https://webglfundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html\n * \"Every canvas has 2 sizes: the drawingbuffer (pixels) and the display\n * size (CSS). If no CSS affects display size, it equals drawingbuffer.\"\n *\n * @see https://stackoverflow.com/questions/4938346/canvas-width-and-height-in-html5\n * Phrogz: \"If you don't set the CSS attributes, the intrinsic size of\n * the canvas will be used as its display size.\"\n *\n * The regression test for this lives in **renderer.test.ts**\n */\nexport function applyDprSizing(\n target: DprSizingTarget,\n logicalWidth: number,\n logicalHeight: number,\n dpr: number,\n): void {\n // Pin the CSS display size FIRST so changing the attributes below\n // cannot resize the element.\n target.style.width = `${logicalWidth}px`;\n target.style.height = `${logicalHeight}px`;\n\n target.width = logicalWidth * dpr;\n target.height = logicalHeight * dpr;\n}\n\n/**\n * Creates a Canvas 2D renderer for sarmal animations\n * Renders the skeleton and the trail\n */\nexport function createRenderer(options: RendererOptions): SarmalInstance {\n const canvas = options.canvas;\n if (!canvas.getContext(\"2d\")) {\n throw new Error(\"Could not get 2d context from canvas\");\n }\n const ctx = canvas.getContext(\"2d\")!;\n\n const engine = options.engine;\n const trailStyle: TrailStyle = options.trailStyle ?? \"default\";\n const trailColor = options.trailColor ?? \"#ffffff\";\n const palette = resolvePalette(options.palette, trailStyle);\n\n function defaultHeadColor(): string {\n if (trailStyle !== \"default\") {\n const { r, g, b } = getPaletteColor(palette, 1.0);\n return `rgb(${r},${g},${b})`;\n }\n return trailColor;\n }\n\n const opts = {\n skeletonColor: options.skeletonColor ?? DEFAULT_SKELETON_COLOR,\n trailColor,\n headColor: options.headColor ?? defaultHeadColor(),\n };\n\n const trailRgb = hexToRgbComponents(opts.trailColor);\n\n /**\n * Device pixel ratio for high-DPI displays.\n * We scale the canvas buffer size by DPR and apply a transform scale\n */\n const dpr = typeof window !== \"undefined\" ? window.devicePixelRatio || 1 : 1;\n\n /**\n * Sets up the canvas for DPR scaling\n */\n function setupCanvas() {\n // TODO: attach a ResizeObserver so this function can be called again for the right scale of canvas\n const rect = canvas.getBoundingClientRect();\n const lw = rect.width || 200;\n const lh = rect.height || 200;\n applyDprSizing(canvas, lw, lh, dpr);\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n }\n\n setupCanvas();\n\n // Store logical dimensions for boundary calculations\n let logicalWidth = canvas.width / dpr;\n let logicalHeight = canvas.height / dpr;\n\n let skeleton: Array<Point> = [];\n let skeletonCanvas: OffscreenCanvas | null = null;\n let trail: Array<Point> = [];\n let trailCount = 0;\n let head: Point | null = null;\n let scale = 1;\n let offsetX = 0;\n let offsetY = 0;\n let animationId: number | null = null;\n let lastTime = 0;\n\n let morphResolve: (() => void) | null = null;\n let morphDurationMs = DEFAULT_MORPH_DURATION_MS;\n let morphAlpha = 0;\n\n /** Accumulated time for \"gradient-animated\" trail style */\n let gradientAnimTime = 0;\n\n function calculateBoundaries() {\n const b = computeBoundaries(skeleton, logicalWidth, logicalHeight);\n if (b) {\n scale = b.scale;\n offsetX = b.offsetX;\n offsetY = b.offsetY;\n }\n }\n\n /**\n * Draws the skeleton once into an OffscreenCanvas so that every frame\n * only needs a single ctx.drawImage() instead of rebuilding the full path.\n */\n function buildSkeletonCanvas() {\n if (skeleton.length < 2) return;\n\n skeletonCanvas = new OffscreenCanvas(canvas.width, canvas.height);\n const skeletonCtx = skeletonCanvas.getContext(\"2d\")!;\n\n // Apply DPR scale to draw in logical coordinates\n skeletonCtx.setTransform(dpr, 0, 0, dpr, 0, 0);\n\n skeletonCtx.strokeStyle = `rgba(${hexToRgbComponents(opts.skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;\n skeletonCtx.lineWidth = 1.5;\n skeletonCtx.beginPath();\n\n const first = skeleton[0]!;\n skeletonCtx.moveTo(first.x * scale + offsetX, first.y * scale + offsetY);\n\n for (let i = 1; i < skeleton.length; i++) {\n const p = skeleton[i]!;\n skeletonCtx.lineTo(p.x * scale + offsetX, p.y * scale + offsetY);\n }\n\n skeletonCtx.stroke();\n }\n\n function drawSkeletonPath(pts: Array<Point>, opacity: number) {\n if (pts.length < 2) return;\n ctx.strokeStyle = `rgba(${hexToRgbComponents(opts.skeletonColor)},${opacity})`;\n ctx.lineWidth = 1.5;\n ctx.beginPath();\n ctx.moveTo(pts[0]!.x * scale + offsetX, pts[0]!.y * scale + offsetY);\n for (let i = 1; i < pts.length; i++) {\n ctx.lineTo(pts[i]!.x * scale + offsetX, pts[i]!.y * scale + offsetY);\n }\n ctx.stroke();\n }\n\n function drawSkeleton() {\n if (opts.skeletonColor === \"transparent\") {\n return;\n }\n\n if (engine.morphAlpha !== null) {\n // Draw the live lerped skeleton every frame so it always matches the current\n // scale/offset and correctly tracks live curves that change with actualTime\n drawSkeletonPath(engine.getSarmalSkeleton(), DEFAULT_SKELETON_OPACITY);\n return;\n }\n\n if (engine.isLiveSkeleton) {\n if (skeleton.length < 2) {\n return;\n }\n\n ctx.strokeStyle = `rgba(${hexToRgbComponents(opts.skeletonColor)},${DEFAULT_SKELETON_OPACITY})`;\n ctx.lineWidth = 1.5;\n ctx.beginPath();\n\n const first = skeleton[0]!;\n ctx.moveTo(first.x * scale + offsetX, first.y * scale + offsetY);\n\n for (let i = 1; i < skeleton.length; i++) {\n const p = skeleton[i]!;\n ctx.lineTo(p.x * scale + offsetX, p.y * scale + offsetY);\n }\n\n ctx.stroke();\n } else if (skeletonCanvas) {\n /**\n * ! The offscreen buffer is *already* DPR-scaled, but the main ctx also has a DPR transform applied,\n * ! so passing natural pixel size would **double-scale** it.\n */\n ctx.drawImage(skeletonCanvas, 0, 0, logicalWidth, logicalHeight);\n }\n }\n\n function drawTrail() {\n if (trailCount < 2) {\n return;\n }\n\n /**\n * Ribbon approach: draw the trail as a sequence of filled quads.\n * Each quad connects two consecutive trail points with left/right offsets\n * based on the width at that position. Quads are drawn from tail to head\n * so later quads naturally overlay earlier ones.\n *\n * @see https://cesium.com/blog/2013/04/22/robust-polyline-rendering-with-webgl\n * Cesium: \"draw a screen-aligned quad for each segment... extrude them\n * in screen space in the direction normal to the line.\"\n */\n const toX = (p: { x: number }) => p.x * scale + offsetX;\n const toY = (p: { y: number }) => p.y * scale + offsetY;\n for (let i = 0; i < trailCount - 1; i++) {\n const { l0x, l0y, r0x, r0y, l1x, l1y, r1x, r1y, opacity, progress } = computeTrailQuad(\n trail,\n i,\n trailCount,\n toX,\n toY,\n );\n\n // Determine fill color based on trail style\n if (trailStyle === \"default\") {\n ctx.fillStyle = `rgba(${trailRgb},${opacity})`;\n } else {\n const timeOffset = trailStyle === \"gradient-animated\" ? gradientAnimTime * 0.0005 : 0;\n const color = getPaletteColor(palette, progress, timeOffset);\n ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${opacity})`;\n }\n\n ctx.beginPath();\n ctx.moveTo(l0x, l0y);\n ctx.lineTo(l1x, l1y);\n ctx.lineTo(r1x, r1y);\n ctx.lineTo(r0x, r0y);\n ctx.closePath();\n ctx.fill();\n }\n }\n\n function drawHead() {\n if (!head) {\n return;\n }\n\n const x = head.x * scale + offsetX;\n const y = head.y * scale + offsetY;\n const r =\n options.headRadius ?? Math.max(2, 3 * Math.sqrt(Math.min(logicalWidth, logicalHeight) / 160));\n\n ctx.fillStyle = opts.headColor;\n ctx.beginPath();\n ctx.arc(x, y, r, 0, Math.PI * 2);\n ctx.fill();\n }\n\n function render() {\n const now = performance.now();\n const deltaTime = Math.min((now - lastTime) / 1000, 1 / 30);\n lastTime = now;\n\n // Update gradient animation time for animated trail style\n if (trailStyle === \"gradient-animated\") {\n gradientAnimTime += deltaTime * 1000; // Convert to ms for consistent speed\n }\n\n if (engine.morphAlpha !== null) {\n morphAlpha = Math.min(1, morphAlpha + deltaTime / (morphDurationMs / 1000));\n engine.setMorphAlpha(morphAlpha);\n\n /**\n * Compute bounds from the actual interpolated skeleton during morph\n * ! This ensures the curve stays properly centered and scaled\n */\n const interpolatedSkeleton = engine.getSarmalSkeleton();\n const bounds = computeBoundaries(interpolatedSkeleton, logicalWidth, logicalHeight);\n\n if (bounds) {\n scale = bounds.scale;\n offsetX = bounds.offsetX;\n offsetY = bounds.offsetY;\n }\n\n if (morphAlpha >= 1) {\n engine.completeMorph();\n morphResolve?.();\n morphResolve = null;\n morphAlpha = 0;\n\n skeleton = engine.getSarmalSkeleton();\n if (!engine.isLiveSkeleton) {\n buildSkeletonCanvas();\n }\n }\n }\n\n trail = engine.tick(deltaTime);\n trailCount = engine.trailCount;\n head = trailCount > 0 ? trail[trailCount - 1]! : null;\n\n ctx.clearRect(0, 0, logicalWidth, logicalHeight);\n\n if (engine.isLiveSkeleton && engine.morphAlpha === null) {\n skeleton = engine.getSarmalSkeleton();\n calculateBoundaries();\n }\n\n drawSkeleton();\n drawTrail();\n drawHead();\n\n animationId = requestAnimationFrame(render);\n }\n\n // Initialize skeleton and offscreen canvas on creation\n skeleton = engine.getSarmalSkeleton();\n calculateBoundaries();\n\n if (!engine.isLiveSkeleton) {\n buildSkeletonCanvas();\n }\n\n return {\n start() {\n if (animationId !== null) {\n return;\n }\n\n lastTime = performance.now();\n render();\n },\n\n stop() {\n if (animationId === null) {\n return;\n }\n\n cancelAnimationFrame(animationId);\n animationId = null;\n engine.cancelSpeedTransition();\n },\n\n reset() {\n engine.reset();\n trail = [];\n head = null;\n },\n\n destroy() {\n if (animationId !== null) {\n cancelAnimationFrame(animationId);\n animationId = null;\n }\n },\n\n ...enginePassthroughs(engine),\n\n morphTo(target: CurveDef, options?: MorphOptions): Promise<void> {\n if (morphResolve !== null) {\n engine.completeMorph();\n morphResolve();\n morphResolve = null;\n morphAlpha = 0;\n }\n\n morphDurationMs = options?.duration ?? DEFAULT_MORPH_DURATION_MS;\n morphAlpha = 0;\n\n engine.startMorph(target, options?.morphStrategy);\n\n return new Promise<void>((resolve) => {\n morphResolve = resolve;\n });\n },\n };\n}\n","import type { CurveDef, Engine, MorphOptions, Point, SarmalInstance } from \"./types\";\nimport {\n DEFAULT_MORPH_DURATION_MS,\n DEFAULT_SKELETON_OPACITY,\n computeBoundaries,\n computeTrailQuad,\n enginePassthroughs,\n} from \"./renderer-shared\";\nimport { createEngine } from \"./engine\";\n\nexport interface SVGRendererOptions {\n /** Container element that will contain the SVG */\n container: Element;\n engine: Engine;\n /** @default '#ffffff' */\n skeletonColor?: string;\n /** @default '#ffffff' */\n trailColor?: string;\n /** @default '#ffffff' */\n headColor?: string;\n /** @default 4 */\n headRadius?: number;\n /** @default 'Loading' */\n ariaLabel?: string;\n}\n\nexport interface SVGSarmalOptions extends Omit<SVGRendererOptions, \"container\" | \"engine\"> {\n /** @default 120 */\n trailLength?: number;\n}\n/** Maximum number of trail segment paths pre-created for the ribbon */\nconst MAX_TRAIL_SEGMENTS = 200;\n\nconst EMPTY_PARAMS: Record<string, number> = {};\n\nfunction pointsToPathString(pts: Point[], scale: number, offsetX: number, offsetY: number): string {\n if (pts.length < 2) return \"\";\n const px = (p: Point) => (p.x * scale + offsetX).toFixed(2);\n const py = (p: Point) => (p.y * scale + offsetY).toFixed(2);\n let d = `M${px(pts[0]!)} ${py(pts[0]!)}`;\n for (let i = 1; i < pts.length; i++) {\n d += ` L${px(pts[i]!)} ${py(pts[i]!)}`;\n }\n return d + \" Z\";\n}\n\nfunction sampleCurveSkeleton(curveDef: CurveDef): Point[] {\n const period = curveDef.period ?? Math.PI * 2;\n const samples = Math.ceil(period * 50); // match engine's POINTS_PER_PERIOD_UNIT\n const pts: Point[] = Array.from({ length: samples });\n for (let i = 0; i < samples; i++) {\n const t = (i / (samples - 1)) * period;\n pts[i] = curveDef.skeletonFn ? curveDef.skeletonFn(t) : curveDef.fn(t, 0, EMPTY_PARAMS);\n }\n return pts;\n}\n\nfunction el(tag: string): SVGElement {\n return document.createElementNS(\"http://www.w3.org/2000/svg\", tag);\n}\n\n/**\n * Creates a live SVG renderer for sarmal animations\n * The SVG is appended into `container` and updated each frame via **requestAnimationFrame**\n */\nexport function createSVGRenderer(options: SVGRendererOptions): SarmalInstance {\n const { container, engine } = options;\n const trailColor = options.trailColor ?? \"#ffffff\";\n const opts = {\n skeletonColor: options.skeletonColor ?? \"#ffffff\",\n trailColor,\n headColor: options.headColor ?? trailColor,\n ariaLabel: options.ariaLabel ?? \"Loading\",\n };\n\n const rect = container.getBoundingClientRect();\n const width = rect.width || 200;\n const height = rect.height || 200;\n const headRadius =\n options.headRadius ?? Math.max(2, 3 * Math.sqrt(Math.min(width, height) / 160));\n\n const svg = el(\"svg\") as SVGSVGElement;\n svg.setAttribute(\"width\", String(width));\n svg.setAttribute(\"height\", String(height));\n svg.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n svg.setAttribute(\"role\", \"img\");\n svg.setAttribute(\"aria-label\", opts.ariaLabel);\n\n const titleEl = el(\"title\");\n titleEl.textContent = opts.ariaLabel;\n svg.appendChild(titleEl);\n\n const skeletonPath = el(\"path\") as SVGPathElement;\n skeletonPath.setAttribute(\"fill\", \"none\");\n skeletonPath.setAttribute(\"stroke\", opts.skeletonColor);\n skeletonPath.setAttribute(\"stroke-opacity\", String(DEFAULT_SKELETON_OPACITY));\n skeletonPath.setAttribute(\"stroke-width\", \"1.5\");\n svg.appendChild(skeletonPath);\n\n const skeletonPathA = el(\"path\") as SVGPathElement;\n skeletonPathA.setAttribute(\"fill\", \"none\");\n skeletonPathA.setAttribute(\"stroke\", opts.skeletonColor);\n skeletonPathA.setAttribute(\"stroke-width\", \"1.5\");\n skeletonPathA.setAttribute(\"visibility\", \"hidden\");\n svg.appendChild(skeletonPathA);\n\n const skeletonPathB = el(\"path\") as SVGPathElement;\n skeletonPathB.setAttribute(\"fill\", \"none\");\n skeletonPathB.setAttribute(\"stroke\", opts.skeletonColor);\n skeletonPathB.setAttribute(\"stroke-width\", \"1.5\");\n skeletonPathB.setAttribute(\"visibility\", \"hidden\");\n svg.appendChild(skeletonPathB);\n\n let morphPathABuilt = \"\";\n let morphPathBBuilt = \"\";\n\n const trailPaths: SVGPathElement[] = [];\n for (let i = 0; i < MAX_TRAIL_SEGMENTS; i++) {\n const path = el(\"path\") as SVGPathElement;\n path.setAttribute(\"fill\", opts.trailColor);\n svg.appendChild(path);\n trailPaths.push(path);\n }\n\n const headCircle = el(\"circle\") as SVGCircleElement;\n headCircle.setAttribute(\"fill\", opts.headColor);\n headCircle.setAttribute(\"r\", String(headRadius));\n svg.appendChild(headCircle);\n\n container.appendChild(svg);\n\n let scale = 1;\n let offsetX = 0;\n let offsetY = 0;\n\n function applyBoundaries(skeleton: Point[]) {\n const b = computeBoundaries(skeleton, width, height);\n if (b) {\n scale = b.scale;\n offsetX = b.offsetX;\n offsetY = b.offsetY;\n }\n }\n\n // Coordinate transform helpers: numeric (for math)\n function px(p: Point): number {\n return p.x * scale + offsetX;\n }\n function py(p: Point): number {\n return p.y * scale + offsetY;\n }\n\n function updateSkeleton(skeleton: Point[]) {\n skeletonPath.setAttribute(\"d\", pointsToPathString(skeleton, scale, offsetX, offsetY));\n }\n\n const skeleton = engine.getSarmalSkeleton();\n applyBoundaries(skeleton);\n\n if (!engine.isLiveSkeleton) {\n updateSkeleton(skeleton);\n }\n\n function updateTrail(trail: Point[], trailCount: number) {\n if (trailCount < 2) {\n for (const p of trailPaths) {\n p.setAttribute(\"d\", \"\");\n }\n return;\n }\n\n /**\n * Ribbon approach: each segment is a filled quad with its own opacity.\n * Quads are drawn from tail to head, with later quads overlaying earlier ones.\n */\n for (let i = 0; i < trailCount - 1; i++) {\n const { l0x, l0y, r0x, r0y, l1x, l1y, r1x, r1y, opacity } = computeTrailQuad(\n trail,\n i,\n trailCount,\n px,\n py,\n );\n\n const d = `M${l0x.toFixed(2)} ${l0y.toFixed(2)} L${l1x.toFixed(2)} ${l1y.toFixed(2)} L${r1x.toFixed(2)} ${r1y.toFixed(2)} L${r0x.toFixed(2)} ${r0y.toFixed(2)} Z`;\n\n trailPaths[i]!.setAttribute(\"d\", d);\n trailPaths[i]!.setAttribute(\"fill-opacity\", opacity.toFixed(3));\n }\n\n // Hide unused paths\n for (let i = trailCount - 1; i < trailPaths.length; i++) {\n trailPaths[i]!.setAttribute(\"d\", \"\");\n }\n }\n\n function updateHead(trail: Point[], trailCount: number) {\n if (trailCount === 0) {\n return;\n }\n\n const head = trail[trailCount - 1]!;\n const x = px(head);\n const y = py(head);\n\n headCircle.setAttribute(\"cx\", String(x));\n headCircle.setAttribute(\"cy\", String(y));\n }\n\n let animationId: number | null = null;\n let lastTime = 0;\n const prefersReducedMotion =\n typeof window !== \"undefined\" && window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n\n let morphResolve: (() => void) | null = null;\n let morphDurationMs = DEFAULT_MORPH_DURATION_MS;\n let morphTarget: CurveDef | null = null;\n let morphAlpha = 0;\n\n function renderFrame() {\n const now = performance.now();\n const dt = Math.min((now - lastTime) / 1000, 1 / 30);\n lastTime = now;\n\n if (engine.morphAlpha !== null) {\n morphAlpha = Math.min(1, morphAlpha + dt / (morphDurationMs / 1000));\n engine.setMorphAlpha(morphAlpha);\n\n if (morphPathABuilt) {\n skeletonPathA.setAttribute(\"d\", morphPathABuilt);\n skeletonPathA.setAttribute(\"visibility\", \"visible\");\n skeletonPathA.setAttribute(\n \"stroke-opacity\",\n String((1 - morphAlpha) * DEFAULT_SKELETON_OPACITY),\n );\n }\n\n if (morphPathBBuilt) {\n skeletonPathB.setAttribute(\"d\", morphPathBBuilt);\n skeletonPathB.setAttribute(\"visibility\", \"visible\");\n skeletonPathB.setAttribute(\"stroke-opacity\", String(morphAlpha * DEFAULT_SKELETON_OPACITY));\n }\n\n if (morphAlpha >= 1) {\n engine.completeMorph();\n morphResolve?.();\n morphResolve = null;\n morphTarget = null;\n morphAlpha = 0;\n morphPathABuilt = \"\";\n morphPathBBuilt = \"\";\n skeletonPathA.setAttribute(\"visibility\", \"hidden\");\n skeletonPathB.setAttribute(\"visibility\", \"hidden\");\n // Snap coordinate space to `curveB` and update skeleton path\n const newSkeleton = engine.getSarmalSkeleton();\n applyBoundaries(newSkeleton);\n updateSkeleton(newSkeleton);\n }\n }\n\n const trail = engine.tick(dt);\n const trailCount = engine.trailCount;\n\n if (engine.isLiveSkeleton && engine.morphAlpha === null) {\n const liveSkeleton = engine.getSarmalSkeleton();\n applyBoundaries(liveSkeleton);\n updateSkeleton(liveSkeleton);\n }\n\n updateTrail(trail, trailCount);\n updateHead(trail, trailCount);\n\n if (!prefersReducedMotion) {\n animationId = requestAnimationFrame(renderFrame);\n }\n }\n\n return {\n start() {\n if (animationId !== null) {\n return;\n }\n lastTime = performance.now();\n renderFrame();\n },\n\n stop() {\n if (animationId === null) {\n return;\n }\n cancelAnimationFrame(animationId);\n animationId = null;\n engine.cancelSpeedTransition();\n },\n\n reset() {\n engine.reset();\n },\n\n destroy() {\n if (animationId !== null) {\n cancelAnimationFrame(animationId);\n animationId = null;\n }\n svg.remove();\n },\n\n ...enginePassthroughs(engine),\n\n morphTo(target: CurveDef, options?: MorphOptions): Promise<void> {\n if (morphResolve !== null) {\n engine.completeMorph();\n morphResolve();\n morphResolve = null;\n morphAlpha = 0;\n skeletonPathA.setAttribute(\"visibility\", \"hidden\");\n skeletonPathB.setAttribute(\"visibility\", \"hidden\");\n }\n\n morphDurationMs = options?.duration ?? DEFAULT_MORPH_DURATION_MS;\n morphTarget = target;\n morphAlpha = 0;\n\n const currentSkeleton = engine.getSarmalSkeleton();\n morphPathABuilt = pointsToPathString(currentSkeleton, scale, offsetX, offsetY);\n\n engine.startMorph(target, options?.morphStrategy);\n\n if (morphTarget) {\n const targetSkeleton = sampleCurveSkeleton(target);\n morphPathBBuilt = pointsToPathString(targetSkeleton, scale, offsetX, offsetY);\n }\n\n return new Promise<void>((resolve) => {\n morphResolve = resolve;\n });\n },\n };\n}\n\n/**\n * Creates a sarmal animation inside a container element using an SVG renderer\n * The SVG is appended to the container and animated via requestAnimationFrame\n *\n * @example\n * ```ts\n * import { createSarmalSVG, curves } from '@sarmal/core'\n * const sarmal = createSarmalSVG(document.getElementById('spinner'), curves.epitrochoid7)\n * sarmal.start()\n * ```\n */\nexport function createSarmalSVG(\n container: Element,\n curveDef: CurveDef,\n options?: SVGSarmalOptions,\n): SarmalInstance {\n const { trailLength, ...rendererOpts } = options ?? {};\n const engine = createEngine(curveDef, trailLength);\n return createSVGRenderer({ container, engine, ...rendererOpts });\n}\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\n/**\n * Artemis II free-return lunar trajectory\n * @see https://www.nasa.gov/wp-content/uploads/2025/09/artemis-ii-map-508.pdf\n * a = x-axis asymmetry (widens one lobe),\n * b = y-axis asymmetry,\n * ox = horizontal offset to visually center the shape\n */\nfunction artemis2Fn(t: number, _time: number, _params: Record<string, number>) {\n const a = 0.35,\n b = 0.15,\n ox = 0.175;\n const s = Math.sin(t),\n c = Math.cos(t);\n const denom = 1 + s * s;\n return {\n x: (c * (1 + a * c)) / denom - ox,\n y: (s * c * (1 + b * c)) / denom,\n };\n}\n\n/**\n * Artemis II free-return lunar trajectory curve\n * Traces the path of the Orion spacecraft during the Artemis II mission\n */\nexport const artemis2: CurveDef = {\n name: \"Artemis II\",\n fn: artemis2Fn,\n period: TWO_PI,\n speed: 0.7,\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction astroidFn(t: number, _time: number, _params: Record<string, number>) {\n const c = Math.cos(t);\n const s = Math.sin(t);\n return {\n x: c * c * c,\n y: s * s * s,\n };\n}\n\n/**\n * Astroid curve - a 4-cusped hypocycloid\n * Creates a star-like shape with four sharp corners\n */\nexport const astroid: CurveDef = {\n name: \"Astroid\",\n fn: astroidFn,\n period: TWO_PI,\n speed: 1.1,\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction deltoidFn(t: number, _time: number, _params: Record<string, number>) {\n return {\n x: 2 * Math.cos(t) + Math.cos(2 * t),\n y: 2 * Math.sin(t) - Math.sin(2 * t),\n };\n}\n\n/**\n * Deltoid curve - a 3-cusped hypocycloid\n * Creates a triangular shape with curved sides\n */\nexport const deltoid: CurveDef = {\n name: \"Deltoid\",\n fn: deltoidFn,\n period: TWO_PI,\n speed: 0.9,\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction epicycloid3Fn(t: number, _time: number, _params: Record<string, number>) {\n return {\n x: 4 * Math.cos(t) - Math.cos(4 * t),\n y: 4 * Math.sin(t) - Math.sin(4 * t),\n };\n}\n\n/**\n * Epicycloid with 3 cusps\n * Creates a three-pointed star shape\n */\nexport const epicycloid3: CurveDef = {\n name: \"Epicycloid (n=3)\",\n fn: epicycloid3Fn,\n period: TWO_PI,\n speed: 0.75,\n};\n","import type { CurveDef, Point } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction epitrochoid7Fn(t: number, _time: number, _params: Record<string, number>) {\n const d = 1.0 + 0.55 * Math.sin(t * 0.5);\n return {\n x: 7 * Math.cos(t) - d * Math.cos(7 * t),\n y: 7 * Math.sin(t) - d * Math.sin(7 * t),\n };\n}\n\nfunction epitrochoid7SkeletonFn(t: number): Point {\n // average of the oscillating range for a stable base shape\n const d = 1.275;\n return {\n x: 7 * Math.cos(t) - d * Math.cos(7 * t),\n y: 7 * Math.sin(t) - d * Math.sin(7 * t),\n };\n}\n\n/**\n * Epitrochoid with 7 lobes and dynamic variation\n * Creates a flower-like pattern with undulating petals\n */\nexport const epitrochoid7: CurveDef = {\n name: \"Epitrochoid\",\n fn: epitrochoid7Fn,\n period: TWO_PI,\n speed: 1.4,\n skeletonFn: epitrochoid7SkeletonFn,\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction lissajous32Fn(t: number, time: number, _params: Record<string, number>) {\n const phi = time * 0.45;\n return {\n x: Math.sin(3 * t + phi),\n y: Math.sin(2 * t),\n };\n}\n\n/**\n * Lissajous curve with frequency ratio 3:2\n * Creates a figure-eight-like pattern with live skeleton\n */\nexport const lissajous32: CurveDef = {\n name: \"Lissajous 3:2\",\n fn: lissajous32Fn,\n period: TWO_PI,\n speed: 2.0,\n skeleton: \"live\",\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction lissajous43Fn(t: number, time: number, _params: Record<string, number>) {\n const phi = time * 0.38;\n return {\n x: Math.sin(4 * t + phi),\n y: Math.sin(3 * t),\n };\n}\n\n/**\n * Lissajous curve with frequency ratio 4:3\n * Creates a complex interweaving pattern with live skeleton\n */\nexport const lissajous43: CurveDef = {\n name: \"Lissajous 4:3\",\n fn: lissajous43Fn,\n period: TWO_PI,\n speed: 1.8,\n skeleton: \"live\",\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction lameFn(t: number, time: number, _params: Record<string, number>) {\n const p = 1.75 + 1.25 * Math.sin(time * 0.48);\n const c = Math.cos(t),\n s = Math.sin(t);\n return {\n x: Math.sign(c) * Math.pow(Math.abs(c), p),\n y: Math.sign(s) * Math.pow(Math.abs(s), p),\n };\n}\n\n/**\n * Lamé curve (superellipse) with time-varying exponent\n * Creates a squircle-like shape that morphs over time\n */\nexport const lame: CurveDef = {\n name: \"Lamé Curve\",\n fn: lameFn,\n period: TWO_PI,\n speed: 1.0,\n skeleton: \"live\",\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction rose3Fn(t: number, _time: number, _params: Record<string, number>) {\n const r = Math.cos(3 * t);\n return {\n x: r * Math.cos(t),\n y: r * Math.sin(t),\n };\n}\n\n/**\n * Rose curve with 3 petals\n * Creates a three-petaled flower pattern\n */\nexport const rose3: CurveDef = {\n name: \"Rose (n=3)\",\n fn: rose3Fn,\n period: TWO_PI,\n speed: 1.15,\n};\n","import type { CurveDef } from \"../types\";\n\nconst TWO_PI = Math.PI * 2;\n\nfunction rose5Fn(t: number, _time: number, _params: Record<string, number>) {\n const r = Math.cos(5 * t);\n return {\n x: r * Math.cos(t),\n y: r * Math.sin(t),\n };\n}\n\n/**\n * Rose curve with 5 petals\n * Creates a five-petaled flower pattern\n */\nexport const rose5: CurveDef = {\n name: \"Rose (n=5)\",\n fn: rose5Fn,\n period: TWO_PI,\n speed: 1.0,\n};\n","// Individual curve exports for tree-shaking\nexport { artemis2 } from \"./artemis2\";\nexport { astroid } from \"./astroid\";\nexport { deltoid } from \"./deltoid\";\nexport { epicycloid3 } from \"./epicycloid3\";\nexport { epitrochoid7 } from \"./epitrochoid7\";\nexport { lissajous32 } from \"./lissajous32\";\nexport { lissajous43 } from \"./lissajous43\";\nexport { lame } from \"./lame\";\nexport { rose3 } from \"./rose3\";\nexport { rose5 } from \"./rose5\";\n\n// Bulk export for convenience\n// >> Standard\nimport { rose3 } from \"./rose3\";\nimport { rose5 } from \"./rose5\";\nimport { astroid } from \"./astroid\";\nimport { deltoid } from \"./deltoid\";\nimport { epicycloid3 } from \"./epicycloid3\";\nimport { epitrochoid7 } from \"./epitrochoid7\";\nimport { lissajous32 } from \"./lissajous32\";\nimport { lissajous43 } from \"./lissajous43\";\nimport { lame } from \"./lame\";\n// >> Iconic\nimport { artemis2 } from \"./artemis2\";\n\n/**\n * Collection of all built-in sarmal curves\n * Import individual curves for better tree-shaking\n */\nexport const curves = {\n artemis2,\n epitrochoid7,\n astroid,\n deltoid,\n rose5,\n rose3,\n lissajous32,\n lissajous43,\n epicycloid3,\n lame,\n} as const;\nexport type CurveName = keyof typeof curves;\n","import type { CurveDef, SarmalInstance, SarmalOptions } from \"./types\";\nexport type { SVGRendererOptions, SVGSarmalOptions } from \"./renderer-svg\";\nexport type {\n Point,\n CurveDef,\n Engine,\n SarmalInstance,\n JumpOptions,\n SeekOptions,\n RendererOptions,\n SarmalOptions,\n TrailStyle,\n PalettePreset,\n} from \"./types\";\nexport type { CurveName } from \"./curves\";\n\nexport { createEngine } from \"./engine\";\nexport { createRenderer } from \"./renderer\";\nexport { createSVGRenderer, createSarmalSVG } from \"./renderer-svg\";\nexport { curves } from \"./curves\";\nexport {\n artemis2,\n epitrochoid7,\n astroid,\n deltoid,\n rose5,\n rose3,\n lissajous32,\n lissajous43,\n epicycloid3,\n lame,\n} from \"./curves\";\n\nimport { createEngine } from \"./engine\";\nimport { createRenderer } from \"./renderer\";\n\n/**\n * Creates a sarmal animation on a canvas element\n *\n * @example\n * ```ts\n * import { createSarmal, curves } from '@sarmal/core'\n * const sarmal = createSarmal(canvas, curves.artemis2)\n * sarmal.start()\n * ```\n */\nexport function createSarmal(\n canvas: HTMLCanvasElement,\n curveDef: CurveDef,\n options?: SarmalOptions,\n): SarmalInstance {\n const { trailLength, ...rendererOpts } = options ?? {};\n const engine = createEngine(curveDef, trailLength);\n\n return createRenderer({ canvas, engine, ...rendererOpts });\n}\n"]}
|
|
@@ -42,13 +42,14 @@ interface CurveDef {
|
|
|
42
42
|
*/
|
|
43
43
|
skeletonFn?: (t: number) => Point;
|
|
44
44
|
}
|
|
45
|
-
type
|
|
45
|
+
type JumpOptions = {
|
|
46
46
|
/**
|
|
47
|
-
*
|
|
47
|
+
* When true, clears the trail on jump. When false (default), the trail is left as-is.
|
|
48
|
+
* @default false
|
|
48
49
|
*/
|
|
49
50
|
clearTrail?: boolean;
|
|
50
51
|
};
|
|
51
|
-
type
|
|
52
|
+
type SeekOptions = {
|
|
52
53
|
/**
|
|
53
54
|
* When true, the trail wraps around the period boundary,
|
|
54
55
|
* which results in a full trail even near `t=0`
|
|
@@ -64,6 +65,66 @@ type SeekWithTrailOptions = {
|
|
|
64
65
|
step?: number;
|
|
65
66
|
};
|
|
66
67
|
type MorpStrategy = "raw" | "normalized";
|
|
68
|
+
/**
|
|
69
|
+
* The shared animation state types
|
|
70
|
+
* Both `Engine` and `SarmalInstance` extend this
|
|
71
|
+
* In the renderer, these are passthroughs
|
|
72
|
+
*/
|
|
73
|
+
interface AnimationControls {
|
|
74
|
+
/**
|
|
75
|
+
* Resets the simulation state, clearing the trail and reverting internal time `t` to 0
|
|
76
|
+
* The next call to `tick` will start fresh from the beginning of the curve
|
|
77
|
+
*/
|
|
78
|
+
reset(): void;
|
|
79
|
+
/**
|
|
80
|
+
* Instantly moves the head to position `t`.
|
|
81
|
+
*
|
|
82
|
+
* ! Does NOT update `actualTime`.
|
|
83
|
+
*
|
|
84
|
+
* Trail is left untouched by default. You can pass `clearTrail: true` to wipe it.
|
|
85
|
+
* Use for morphing mid-flight or any time you don't need trail context.
|
|
86
|
+
* @param t The position to jump to (will be wrapped into [0, period))
|
|
87
|
+
*/
|
|
88
|
+
jump(t: number, options?: JumpOptions): void;
|
|
89
|
+
/**
|
|
90
|
+
* Moves to `t` AND reconstructs the trail as if the animation naturally arrived there from `t=0`
|
|
91
|
+
* Also updates `actualTime` to match. Trail is always rebuilt from scratch
|
|
92
|
+
* Use for initialisation or any jump where you want the trail to look meaningful
|
|
93
|
+
* @param t The position to seek to (will be wrapped into [0, period))
|
|
94
|
+
*/
|
|
95
|
+
seek(t: number, options?: SeekOptions): void;
|
|
96
|
+
/**
|
|
97
|
+
* Overrides the animation speed at runtime
|
|
98
|
+
* `0` freezes `t` but the loop keeps running
|
|
99
|
+
* Negative values reverse traversal.
|
|
100
|
+
*
|
|
101
|
+
* ! Does NOT affect a curve's inherent speed given in CurveDef
|
|
102
|
+
* @param speed 0 = freeze, negative = reverse, no upper bound
|
|
103
|
+
*/
|
|
104
|
+
setSpeed(speed: number): void;
|
|
105
|
+
/**
|
|
106
|
+
* Returns the *effective speed* the engine is currently using:
|
|
107
|
+
* `userSpeedOverride` if set, otherwise the curve's default speed.
|
|
108
|
+
* This is what `tick()` actually uses
|
|
109
|
+
*/
|
|
110
|
+
getSpeed(): number;
|
|
111
|
+
/**
|
|
112
|
+
* Drops the speed override and defers back to the curve's inherent default speed.
|
|
113
|
+
* ! Sets `userSpeedOverride` to `null`
|
|
114
|
+
*/
|
|
115
|
+
resetSpeed(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Transitions to the target speed over `duration` milliseconds using linear interpolation.
|
|
118
|
+
* Resolves when the transition completes.
|
|
119
|
+
*
|
|
120
|
+
* Calling this while a transition is already in progress cancels the old transition
|
|
121
|
+
* (rejecting its Promise) and starts a new one from the current interpolated speed.
|
|
122
|
+
*
|
|
123
|
+
* @param speed Target speed
|
|
124
|
+
* @param duration Transition duration in milliseconds (must be > 0)
|
|
125
|
+
*/
|
|
126
|
+
setSpeedOver(speed: number, duration: number): Promise<void>;
|
|
127
|
+
}
|
|
67
128
|
type MorphOptions = {
|
|
68
129
|
/**
|
|
69
130
|
* Duration of the morph transition in milliseconds
|
|
@@ -78,7 +139,7 @@ type MorphOptions = {
|
|
|
78
139
|
*/
|
|
79
140
|
morphStrategy?: MorpStrategy;
|
|
80
141
|
};
|
|
81
|
-
interface Engine {
|
|
142
|
+
interface Engine extends AnimationControls {
|
|
82
143
|
/**
|
|
83
144
|
* Advances the Sarmal simulation by the given delta time (dt) in seconds.
|
|
84
145
|
* Internally, this increases the simulation time `t` by `speed * dt`,
|
|
@@ -94,11 +155,6 @@ interface Engine {
|
|
|
94
155
|
* ! Use this instead of `trail.length`
|
|
95
156
|
*/
|
|
96
157
|
readonly trailCount: number;
|
|
97
|
-
/**
|
|
98
|
-
* Resets the simulation state, by clearing the trail and reverting internal time `t` to 0.
|
|
99
|
-
* The next call to `tick` will start fresh from the beginning of the curve.
|
|
100
|
-
*/
|
|
101
|
-
reset(): void;
|
|
102
158
|
/**
|
|
103
159
|
* Returns the *skeleton* of the curve.
|
|
104
160
|
* In technicality, it just represents the complete traversal of the curve over one full period,
|
|
@@ -112,17 +168,6 @@ interface Engine {
|
|
|
112
168
|
*/
|
|
113
169
|
getSarmalSkeleton(): Array<Point>;
|
|
114
170
|
readonly isLiveSkeleton: boolean;
|
|
115
|
-
/**
|
|
116
|
-
* Sets the simulation time `t` directly to the specified value.
|
|
117
|
-
* By default, the trail is preserved
|
|
118
|
-
* @param t The time value to seek to (will be wrapped into [0, period))
|
|
119
|
-
*/
|
|
120
|
-
seek(t: number, options?: SeekOptions): void;
|
|
121
|
-
/**
|
|
122
|
-
* Seeks to `t` and rebuilds the trail as if the animation naturally arrived there from `t=0`
|
|
123
|
-
* @param t The time value to seek to (will be wrapped into [0, period))
|
|
124
|
-
*/
|
|
125
|
-
seekWithTrail(t: number, options?: SeekWithTrailOptions): void;
|
|
126
171
|
/**
|
|
127
172
|
* Begins a smooth transition from the current curve to `target`
|
|
128
173
|
* Saves the current curve as `curveA`, registers `target` as `curveB`, and resets `morphAlpha` to `0`
|
|
@@ -151,25 +196,17 @@ interface Engine {
|
|
|
151
196
|
* `null` when no morph is in progress
|
|
152
197
|
*/
|
|
153
198
|
readonly morphAlpha: number | null;
|
|
199
|
+
/**
|
|
200
|
+
* Cancels any in-progress speed transition initiated by `setSpeedOver()`.
|
|
201
|
+
* Called internally by the renderer's `stop()` method.
|
|
202
|
+
*/
|
|
203
|
+
cancelSpeedTransition(): void;
|
|
154
204
|
}
|
|
155
|
-
interface SarmalInstance {
|
|
205
|
+
interface SarmalInstance extends AnimationControls {
|
|
156
206
|
start(): void;
|
|
157
207
|
stop(): void;
|
|
158
|
-
/** Resets the engine and clears the trail */
|
|
159
|
-
reset(): void;
|
|
160
208
|
/** Stops the animation and cleans up resources */
|
|
161
209
|
destroy(): void;
|
|
162
|
-
/**
|
|
163
|
-
* Sets the simulation time `t` directly to the specified value.
|
|
164
|
-
* By default, the trail is preserved
|
|
165
|
-
* @param t The time value to seek to (will be wrapped into [0, period))
|
|
166
|
-
*/
|
|
167
|
-
seek(t: number, options?: SeekOptions): void;
|
|
168
|
-
/**
|
|
169
|
-
* Seeks to `t` and rebuilds the trail as if the animation naturally arrived there from `t=0`
|
|
170
|
-
* @param t The time value to seek to (will be wrapped into [0, period))
|
|
171
|
-
*/
|
|
172
|
-
seekWithTrail(t: number, options?: SeekWithTrailOptions): void;
|
|
173
210
|
/**
|
|
174
211
|
* Smoothly transitions from the current curve to `target`.
|
|
175
212
|
* The trail naturally reflects the new curve as new points are added.
|
|
@@ -220,4 +257,4 @@ interface SarmalOptions extends Omit<RendererOptions, "canvas" | "engine"> {
|
|
|
220
257
|
trailLength?: number;
|
|
221
258
|
}
|
|
222
259
|
|
|
223
|
-
export type { CurveDef as C, Engine as E, PalettePreset as P, RendererOptions as R, SarmalInstance as S, TrailStyle as T, SarmalOptions as a, Point as b, SeekOptions as c
|
|
260
|
+
export type { CurveDef as C, Engine as E, JumpOptions as J, PalettePreset as P, RendererOptions as R, SarmalInstance as S, TrailStyle as T, SarmalOptions as a, Point as b, SeekOptions as c };
|