@sarmal/core 0.36.4 → 0.37.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/auto-init.cjs +472 -2
  2. package/dist/auto-init.cjs.map +1 -1
  3. package/dist/auto-init.d.cts +6 -0
  4. package/dist/auto-init.d.ts +6 -0
  5. package/dist/auto-init.js +472 -2
  6. package/dist/auto-init.js.map +1 -1
  7. package/dist/curves/artemis2.d.cts +1 -1
  8. package/dist/curves/artemis2.d.ts +1 -1
  9. package/dist/curves/astroid.d.cts +1 -1
  10. package/dist/curves/astroid.d.ts +1 -1
  11. package/dist/curves/deltoid.d.cts +1 -1
  12. package/dist/curves/deltoid.d.ts +1 -1
  13. package/dist/curves/epicycloid3.d.cts +1 -1
  14. package/dist/curves/epicycloid3.d.ts +1 -1
  15. package/dist/curves/epitrochoid7.d.cts +1 -1
  16. package/dist/curves/epitrochoid7.d.ts +1 -1
  17. package/dist/curves/index.d.cts +1 -1
  18. package/dist/curves/index.d.ts +1 -1
  19. package/dist/curves/lame.d.cts +1 -1
  20. package/dist/curves/lame.d.ts +1 -1
  21. package/dist/curves/lissajous32.d.cts +1 -1
  22. package/dist/curves/lissajous32.d.ts +1 -1
  23. package/dist/curves/lissajous43.d.cts +1 -1
  24. package/dist/curves/lissajous43.d.ts +1 -1
  25. package/dist/curves/rose3.d.cts +1 -1
  26. package/dist/curves/rose3.d.ts +1 -1
  27. package/dist/curves/rose5.d.cts +1 -1
  28. package/dist/curves/rose5.d.ts +1 -1
  29. package/dist/curves/rose52.d.cts +1 -1
  30. package/dist/curves/rose52.d.ts +1 -1
  31. package/dist/curves/star.d.cts +1 -1
  32. package/dist/curves/star.d.ts +1 -1
  33. package/dist/curves/star4.d.cts +1 -1
  34. package/dist/curves/star4.d.ts +1 -1
  35. package/dist/curves/star7.d.cts +1 -1
  36. package/dist/curves/star7.d.ts +1 -1
  37. package/dist/index.cjs.map +1 -1
  38. package/dist/index.d.cts +3 -3
  39. package/dist/index.d.ts +3 -3
  40. package/dist/index.js.map +1 -1
  41. package/dist/{renderer-shared-CFimm7VD.d.cts → renderer-shared-BDDSZhB6.d.cts} +1 -1
  42. package/dist/{renderer-shared-BZV9ELOa.d.ts → renderer-shared-D7ZDFZqK.d.ts} +1 -1
  43. package/dist/terminal.d.cts +2 -2
  44. package/dist/terminal.d.ts +2 -2
  45. package/dist/{types-CCgSK31t.d.cts → types-DS2VYCEa.d.cts} +3 -2
  46. package/dist/{types-CCgSK31t.d.ts → types-DS2VYCEa.d.ts} +3 -2
  47. package/package.json +2 -1
  48. package/skills/core/SKILL.md +180 -15
@@ -1,4 +1,4 @@
1
- import { P as Point } from './types-CCgSK31t.cjs';
1
+ import { P as Point } from './types-DS2VYCEa.cjs';
2
2
 
3
3
  interface BoundaryResult {
4
4
  scale: number;
@@ -1,4 +1,4 @@
1
- import { P as Point } from './types-CCgSK31t.js';
1
+ import { P as Point } from './types-DS2VYCEa.js';
2
2
 
3
3
  interface BoundaryResult {
4
4
  scale: number;
@@ -1,5 +1,5 @@
1
- import { C as CurveDef } from './types-CCgSK31t.cjs';
2
- import { R as Rgb } from './renderer-shared-CFimm7VD.cjs';
1
+ import { C as CurveDef } from './types-DS2VYCEa.cjs';
2
+ import { R as Rgb } from './renderer-shared-BDDSZhB6.cjs';
3
3
 
4
4
  type ColorCapability = "truecolor" | "256-color" | "monochrome";
5
5
  type DotCol = 0 | 1;
@@ -1,5 +1,5 @@
1
- import { C as CurveDef } from './types-CCgSK31t.js';
2
- import { R as Rgb } from './renderer-shared-BZV9ELOa.js';
1
+ import { C as CurveDef } from './types-DS2VYCEa.js';
2
+ import { R as Rgb } from './renderer-shared-D7ZDFZqK.js';
3
3
 
4
4
  type ColorCapability = "truecolor" | "256-color" | "monochrome";
5
5
  type DotCol = 0 | 1;
@@ -244,9 +244,10 @@ interface SarmalInstance<T extends BaseRuntimeRenderOptions = RuntimeRenderOptio
244
244
  */
245
245
  type TrailStyle = "default" | "gradient-static" | "gradient-animated";
246
246
  /**
247
- * The value must be a single hex string or an array of hex strings.
247
+ * A single color string or an array of color strings for gradient trails.
248
248
  *
249
- * ! Named colors, shorthand hex, `rgb()`, and `hsl()` notations are not yet supported.
249
+ * Accepted formats: `#rrggbb`, `#rgb`, `rgb()`, `rgba()`, `oklch()`.
250
+ * ! `hsl()` and named colors (e.g. `"red"`) are not supported.
250
251
  */
251
252
  type TrailColor = string | string[];
252
253
  /**
@@ -244,9 +244,10 @@ interface SarmalInstance<T extends BaseRuntimeRenderOptions = RuntimeRenderOptio
244
244
  */
245
245
  type TrailStyle = "default" | "gradient-static" | "gradient-animated";
246
246
  /**
247
- * The value must be a single hex string or an array of hex strings.
247
+ * A single color string or an array of color strings for gradient trails.
248
248
  *
249
- * ! Named colors, shorthand hex, `rgb()`, and `hsl()` notations are not yet supported.
249
+ * Accepted formats: `#rrggbb`, `#rgb`, `rgb()`, `rgba()`, `oklch()`.
250
+ * ! `hsl()` and named colors (e.g. `"red"`) are not supported.
250
251
  */
251
252
  type TrailColor = string | string[];
252
253
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sarmal/core",
3
- "version": "0.36.4",
3
+ "version": "0.37.0",
4
4
  "description": "Curve path based loading indicators and their renderer",
5
5
  "keywords": [
6
6
  "animation",
@@ -85,6 +85,7 @@
85
85
  "bench": "vitest bench"
86
86
  },
87
87
  "devDependencies": {
88
+ "@tanstack/intent": "0.0.41",
88
89
  "@types/node": "^25.5.2",
89
90
  "jsdom": "^29.0.2",
90
91
  "oxfmt": "^0.44.0",
@@ -2,7 +2,8 @@
2
2
  name: core
3
3
  description: Parametric curve loading indicators for the web. Use when adding animated
4
4
  spinners or loading indicators with @sarmal/core — covers createSarmal (canvas),
5
- createSarmalSVG, built-in curves, lifecycle, and animation controls.
5
+ createSarmalSVG, createSarmalDotMatrix, terminal renderer, built-in curves,
6
+ lifecycle, animation controls, and auto-init.
6
7
  license: MIT
7
8
  ---
8
9
 
@@ -14,8 +15,9 @@ sarmal renders parametric math curves as animated loading/thinking indicators. I
14
15
 
15
16
  The package ships TypeScript definitions that are the authoritative, always-current API reference. Read them before writing any code:
16
17
 
17
- - `node_modules/@sarmal/core/dist/index.d.ts` — `SarmalInstance`, `SarmalOptions`, `createSarmal`, `createSarmalSVG`, `RuntimeRenderOptions`, `TrailStyle`, `TrailColor`, and all other types
18
+ - `node_modules/@sarmal/core/dist/index.d.ts` — `SarmalInstance`, `SarmalOptions`, `SVGSarmalOptions`, `DotMatrixSarmalOptions`, `RuntimeRenderOptions`, `DotMatrixRuntimeRenderOptions`, `BaseRendererOptions`, `TrailStyle`, `TrailColor`, `Engine`, and all other types
18
19
  - `node_modules/@sarmal/core/dist/curves/index.d.ts` — `CurveName` union type listing every available built-in curve name; individual curve exports
20
+ - `node_modules/@sarmal/core/dist/terminal.d.ts` — `terminalSarmal`, `TerminalSarmalOptions`
19
21
 
20
22
  Do not rely on training data for option names, defaults, or curve names — read the `.d.ts` files.
21
23
 
@@ -28,13 +30,28 @@ npm install @sarmal/core
28
30
  ## Entry points
29
31
 
30
32
  ```ts
31
- import { createSarmal, createSarmalSVG, curves } from "@sarmal/core";
33
+ // Main package — canvas, SVG, dot matrix, utilities
34
+ import { createSarmal, createSarmalSVG, createSarmalDotMatrix, curves } from "@sarmal/core";
35
+
36
+ // Auto-init (no-JS CDN usage)
37
+ import "@sarmal/core/auto";
38
+
39
+ // Terminal renderer (Node.js only)
40
+ import { terminalSarmal } from "@sarmal/core/terminal";
32
41
  ```
33
42
 
34
- **`createSarmal(canvas, curveDef, options?): SarmalInstance`** — canvas renderer
35
- **`createSarmalSVG(svg, curveDef, options?): SarmalInstance`** — SVG renderer
43
+ ### Exported functions
36
44
 
37
- Both accept the same options and return the same `SarmalInstance` interface.
45
+ | Function | Purpose |
46
+ | --------------------------------------------------- | -------------------------------------------------- |
47
+ | `createSarmal(canvas, curveDef, options?)` | Canvas ribbon renderer |
48
+ | `createSarmalSVG(svg, curveDef, options?)` | SVG ribbon renderer |
49
+ | `createSarmalDotMatrix(canvas, curveDef, options?)` | Dot matrix canvas renderer |
50
+ | `createEngine(curveDef, trailLength?)` | Math-only engine, no rendering |
51
+ | `createRenderer(options)` | Low-level canvas renderer (advanced) |
52
+ | `createSVGRenderer(options)` | Low-level SVG renderer (advanced) |
53
+ | `drawCurve(points, options?)` | Build a `CurveDef` from Catmull-Rom control points |
54
+ | `terminalSarmal(stream, curveDef, options?)` | Braille/ANSI terminal renderer |
38
55
 
39
56
  ## Using built-in curves
40
57
 
@@ -52,7 +69,7 @@ For all available curve names, read the `CurveName` type in `dist/curves/index.d
52
69
 
53
70
  ## Coordinate space — most important gotcha
54
71
 
55
- The two renderers use **different coordinate spaces** for all size values:
72
+ The two ribbon renderers use **different coordinate spaces** for all size values:
56
73
 
57
74
  | Renderer | Space | `headRadius` default |
58
75
  | ----------------------- | ------------------- | -------------------- |
@@ -63,6 +80,8 @@ When configuring `headRadius` or any size option for the SVG renderer, use viewB
63
80
 
64
81
  The same applies to `setRenderOptions` calls on SVG instances.
65
82
 
83
+ The dot matrix renderer does not use either coordinate space — it maps the curve onto a grid of dots specified by `cols` and `rows`.
84
+
66
85
  ## Lifecycle
67
86
 
68
87
  ```ts
@@ -75,6 +94,16 @@ sarmal.destroy(); // REQUIRED: stops the loop and frees resources
75
94
 
76
95
  **Always call `destroy()`** when removing the element or unmounting a component. Omitting it leaks a `requestAnimationFrame` loop.
77
96
 
97
+ **`autoStart`** defaults to `true` — the animation begins immediately on creation. Pass `{ autoStart: false }` to start paused.
98
+
99
+ **`pauseOnHidden`** defaults to `true` — the animation automatically pauses when the browser tab is hidden and resumes when visible. Pass `{ pauseOnHidden: false }` to keep running in background tabs.
100
+
101
+ **`initialPhase`** — seeks to the given phase before the first frame, so the animation starts mid-curve with a full trail already rendered.
102
+
103
+ ```ts
104
+ const sarmal = createSarmal(canvas, curveDef, { initialPhase: Math.PI });
105
+ ```
106
+
78
107
  ## Animation controls
79
108
 
80
109
  ```ts
@@ -99,29 +128,162 @@ await sarmal.morphTo(rose5, { duration: 600 });
99
128
 
100
129
  ## Runtime style changes
101
130
 
102
- A subset of options can be changed on a live instance via `setRenderOptions`. For the exact list, read `RuntimeRenderOptions` in `dist/index.d.ts`. Validation is strict — if any field fails, the entire call is rejected.
131
+ `setRenderOptions` changes visual options on a live instance without recreating it. Validation is fail-atomic — if any field fails, the entire call is rejected and nothing changes.
103
132
 
104
133
  ```ts
105
134
  sarmal.setRenderOptions({
106
135
  trailColor: ["#ff0000", "#0000ff"],
107
136
  trailStyle: "gradient-animated",
137
+ trailWidth: 1.5, // multiplier: 1 = default, 2 = double width
108
138
  skeletonColor: "transparent", // hides the skeleton
109
139
  headColor: null, // null = derive from trail automatically
110
140
  });
111
141
  ```
112
142
 
143
+ For the exact list of accepted fields, read `RuntimeRenderOptions` in `dist/index.d.ts`.
144
+
145
+ **Dot matrix instances** use `DotMatrixRuntimeRenderOptions` which only supports `trailColor`, `trailStyle`, and `skeletonColor`. Passing `headColor`, `headRadius`, or `trailWidth` to `setRenderOptions` on a dot matrix instance throws.
146
+
147
+ ## Dot matrix renderer
148
+
149
+ `createSarmalDotMatrix` renders the curve as a grid of rounded dots on a canvas. The head and trail are expressed as brightness on the grid rather than a ribbon path.
150
+
151
+ ```ts
152
+ import { createSarmalDotMatrix, rose3 } from "@sarmal/core";
153
+
154
+ const instance = createSarmalDotMatrix(canvas, rose3, {
155
+ cols: 32, // dot columns (default: 32)
156
+ rows: 32, // dot rows (default: 32)
157
+ roundness: 1, // 0 = square, 1 = full circle (default: 1)
158
+ trailColor: "#2dd4bf",
159
+ trailStyle: "gradient-animated",
160
+ });
161
+ ```
162
+
163
+ The canvas `width` and `height` HTML attributes (not CSS) determine the rendering area. The dot matrix renderer reads pixel dimensions directly; CSS sizing alone has no effect on the grid.
164
+
165
+ `trailLength` defaults to `cols * 3`. `DotMatrixSarmalOptions` supports the same lifecycle options as the ribbon renderers (`autoStart`, `pauseOnHidden`, `initialPhase`) but not `headColor`, `headRadius`, or `trailWidth`.
166
+
167
+ ## Built-in palettes
168
+
169
+ `palettes` is a named collection of multi-stop color arrays ready to pass as `trailColor`:
170
+
171
+ ```ts
172
+ import { palettes } from "@sarmal/core";
173
+
174
+ sarmal.setRenderOptions({
175
+ trailColor: palettes.bard, // ["#a855f7", "#3b82f6", "#14b8a6", "#ec4899"]
176
+ trailStyle: "gradient-animated",
177
+ });
178
+ ```
179
+
180
+ Available names: `bard`, `carnival`, `ocean`, `sunset`, `ice`, `rocketpop`, `neon`, `vaporwave`, `pastel`, `sakura`. Read `SarmalPalette` in `dist/index.d.ts` for the full union.
181
+
182
+ ## Drawing curves from control points
183
+
184
+ `drawCurve` builds a `CurveDef` from Catmull-Rom spline control points — no math required:
185
+
186
+ ```ts
187
+ import { createSarmal, drawCurve } from "@sarmal/core";
188
+
189
+ const curve = drawCurve([
190
+ [0, -0.8],
191
+ [0.8, 0],
192
+ [0, 0.8],
193
+ [-0.8, 0],
194
+ ]);
195
+
196
+ const sarmal = createSarmal(canvas, curve);
197
+ ```
198
+
199
+ Control points are `[x, y]` tuples in `[-1, 1]` space. The spline is closed automatically.
200
+
201
+ ## Terminal renderer
202
+
203
+ `@sarmal/core/terminal` renders curves in the terminal using braille characters and ANSI colors. Node.js only.
204
+
205
+ ```ts
206
+ import { terminalSarmal } from "@sarmal/core/terminal";
207
+ import { artemis2 } from "@sarmal/core";
208
+
209
+ const stop = terminalSarmal(process.stdout, artemis2, {
210
+ size: 16, // braille cell width (default: 16)
211
+ fps: 30,
212
+ speed: 1,
213
+ color: "rgb", // "rgb" | "256" | "mono"
214
+ });
215
+
216
+ // stop() to clean up and restore cursor
217
+ ```
218
+
219
+ Or run directly: `npx @sarmal/core` — accepts `--name`, `--fps`, `--speed`, `--size`, `--color`.
220
+
113
221
  ## Auto-init (no JS required)
114
222
 
223
+ Import the side-effect module or drop in the CDN script:
224
+
115
225
  ```ts
116
226
  import "@sarmal/core/auto";
117
227
  ```
118
228
 
119
229
  ```html
230
+ <script src="https://cdn.jsdelivr.net/npm/@sarmal/core/dist/auto-init.js"></script>
231
+ ```
232
+
233
+ Then annotate elements with `data-sarmal`:
234
+
235
+ ```html
236
+ <!-- canvas ribbon renderer -->
120
237
  <canvas data-sarmal="lissajous32" width="200" height="200"></canvas>
121
- <svg data-sarmal="rose5" width="200" height="200"></svg>
238
+
239
+ <!-- SVG ribbon renderer -->
240
+ <svg data-sarmal="rose5" style="width:200px; height:200px;"></svg>
241
+
242
+ <!-- dot matrix renderer — requires data-renderer="dot-matrix" -->
243
+ <canvas
244
+ data-sarmal="rose3"
245
+ data-renderer="dot-matrix"
246
+ data-cols="32"
247
+ data-rows="32"
248
+ width="200"
249
+ height="200"
250
+ ></canvas>
122
251
  ```
123
252
 
124
- Data attributes mirror the option names in kebab-case: `data-trail-color`, `data-trail-length`, `data-trail-style`, `data-skeleton-color`, `data-head-color`, `data-head-radius`.
253
+ `data-renderer` accepts `"dot-matrix"` or `"canvas"` (explicit but redundant). Any other value is an error — the element is skipped and a `console.error` is emitted. Omitting the attribute defaults to the canvas ribbon renderer.
254
+
255
+ ### Supported data attributes
256
+
257
+ Shared by all three renderers:
258
+
259
+ | Attribute | Mirrors option | Notes |
260
+ | ---------------------- | --------------- | ------------------------------------------------------- |
261
+ | `data-sarmal` | — | **Required.** Curve name. |
262
+ | `data-trail-color` | `trailColor` | Single color string or JSON array: `'["#f00","#00f"]'` |
263
+ | `data-skeleton-color` | `skeletonColor` | Pass `"transparent"` to hide. |
264
+ | `data-trail-style` | `trailStyle` | `"default"`, `"gradient-static"`, `"gradient-animated"` |
265
+ | `data-trail-length` | `trailLength` | Integer. |
266
+ | `data-speed` | — | Applied via `setSpeed()` after creation. |
267
+ | `data-auto-start` | `autoStart` | Set to `"false"` to start paused. Omit to auto-play. |
268
+ | `data-pause-on-hidden` | `pauseOnHidden` | Set to `"false"` to keep running when tab is hidden. |
269
+ | `data-initial-phase` | `initialPhase` | Number. `"0"` is valid and seeks to phase 0. |
270
+
271
+ Canvas and SVG ribbon renderers only:
272
+
273
+ | Attribute | Mirrors option |
274
+ | ------------------ | -------------- |
275
+ | `data-head-color` | `headColor` |
276
+ | `data-head-radius` | `headRadius` |
277
+ | `data-trail-width` | `trailWidth` |
278
+
279
+ Dot matrix renderer only:
280
+
281
+ | Attribute | Mirrors option |
282
+ | ---------------- | -------------- |
283
+ | `data-renderer` | — | `"dot-matrix"` selects this renderer. `"canvas"` is accepted but redundant. Any other value logs an error and skips the element. |
284
+ | `data-cols` | `cols` |
285
+ | `data-rows` | `rows` |
286
+ | `data-roundness` | `roundness` |
125
287
 
126
288
  ## CDN usage
127
289
 
@@ -143,9 +305,12 @@ Auto-init script (no JS needed):
143
305
 
144
306
  ## Common mistakes
145
307
 
146
- - **`trailColor` with named colors or `hsl()`** — accepted formats are `#rrggbb`, `#rgb`, `#rrggbbaa` (alpha stripped), `rgb()`, `rgba()` (alpha stripped); named colors (`'red'`) and `hsl()` throw
147
- - **SVG `headRadius` with pixel values** — SVG space is 0–100 viewBox units; a canvas value of `4` renders as a large dot in SVG
308
+ - **Named colors or `hsl()` in `trailColor`** — not supported; accepted formats are `#rrggbb`, `#rgb`, `rgb()`, `rgba()`, and `oklch()`. Named colors (`'red'`) and `hsl()` throw.
309
+ - **SVG `headRadius` with pixel values** — SVG space is 0–100 viewBox units; a canvas value of `4` renders as a large dot in SVG. Use `0.5`–`2` for SVG.
310
+ - **Dot matrix `setRenderOptions` with canvas-only fields** — `headColor`, `headRadius`, and `trailWidth` throw on dot matrix instances; use `DotMatrixRuntimeRenderOptions` fields only.
311
+ - **Dot matrix canvas sizing** — set `width` and `height` HTML attributes, not just CSS. The renderer reads `canvas.width` / `canvas.height` directly; CSS-only sizing produces a mismatched grid.
148
312
  - **Forgetting `destroy()`** — always clean up in React `useEffect` return, Vue `onUnmounted`, etc.
149
- - **Changing `trailLength` after construction** — not possible; `trailLength` is fixed at creation; create a new instance
150
- - **Gradient colors without a gradient `trailStyle`** — `string[]` for `trailColor` has no visual effect unless `trailStyle` is `'gradient-static'` or `'gradient-animated'`
151
- - **Reading trail length from `trail.length`** — when using the engine directly, use `engine.trailCount`; the buffer is pre-allocated and always full-length
313
+ - **Changing `trailLength` after construction** — not possible; `trailLength` is fixed at creation; create a new instance.
314
+ - **Gradient colors without a gradient `trailStyle`** — `string[]` for `trailColor` has no visual effect unless `trailStyle` is `'gradient-static'` or `'gradient-animated'`.
315
+ - **Reading trail size from `trail.length`** — when using `createEngine` directly, use `engine.trailCount`; the buffer is pre-allocated and always full-length.
316
+ - **`data-initial-phase="0"` ignored** — auto-init uses a `!== undefined` check for this attribute specifically, so `"0"` correctly seeks to phase 0. All other numeric attributes use truthy checks and would ignore `"0"`.