@zakkster/lite-ui-fx 1.2.0 → 1.3.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/CHANGELOG.md CHANGED
@@ -5,7 +5,50 @@ All notable changes to `@zakkster/lite-ui-fx` are documented here.
5
5
  The format follows Keep a Changelog; this project adheres to Semantic
6
6
  Versioning.
7
7
 
8
- ## [1.2.0] -- unreleased
8
+ ## [1.3.0] -- 2026-09-07
9
+
10
+ The recipe sweep (U3), first pass: zero per-frame allocation across all 50
11
+ recipes (U-03) and geometry derived from state (U-05). The `zero-gc` keyword is
12
+ true for the first time. Theming (U-06) and the blueprint-doc rewrite are a
13
+ deferred follow-up; `themeable` / `motionSafe` stay `false`.
14
+
15
+ ### Fixed
16
+
17
+ - U-03 (zero-GC): every built-in recipe now runs its per-frame body -- idle and
18
+ under interaction -- without allocating. Per-frame `rgba(...,${alpha})` colour
19
+ strings became a const colour + `globalAlpha`; recipes whose RGB varies with a
20
+ value (FlameCounter, HeatMap, DayNightToggle) use a precomputed colour LUT;
21
+ particle `push`/`splice` pools became fixed preallocated pools with a live
22
+ flag; per-frame gradients moved to `init` (VolumeKnob / RingProgress build
23
+ once; LaserSlider / AuroraSlider build a reference gradient in `init` and scale
24
+ it to the fill, AuroraSlider cycling a bounded set of phase gradients); value
25
+ labels read a precomputed `PCT` table or a change-detection cache instead of
26
+ building `${n}%` / `String(n)` / `.toFixed()` per frame; the GlitchButton
27
+ per-tick closure and the CompassKnob / ReactionPicker per-frame array literals
28
+ were hoisted; `setLineDash([4,3])` uses one shared module-level array.
29
+ - U-05 (size-true): spawn and inset positions derive from `st.w` -- NeonPulse
30
+ ring origin (was `46`/`18`), SparkSlider and ScratchReveal spark spawn (was
31
+ `val * 200`), BubbleRating bubble gap (was `200 / 5`).
32
+
33
+ ### Added
34
+
35
+ - `test/torture/t3-frame-alloc.mjs` (+ `t3-scan.mjs`): the U-03 gate. It runs in
36
+ a child process under `--max-semi-space-size=1` and gates each recipe on
37
+ `major === 0`, zero gradient constructions after `init`, and a bounded count of
38
+ distinct fill/stroke colour strings (a per-frame colour template mints
39
+ hundreds; a const palette or LUT a few dozen). Wired into `torture.mjs`.
40
+
41
+ ### Changed
42
+
43
+ - Harness: the recording `Ctx2DStub` backs numeric context properties
44
+ (`globalAlpha`, `lineWidth`, ...) with a `Float64Array` so writing a
45
+ non-integer never boxes a HeapNumber -- the gate measures the recipe, not the
46
+ stub. `gcGate` gained a warmup phase and an optional zero-alloc churn driver.
47
+ - `mountUIFX` forwards the validated options to the recipe factory, so a recipe
48
+ can read its own config (a no-arg or wrapped factory ignores the argument).
49
+ This is inert until the U-06 theming pass uses it.
50
+
51
+ ## [1.2.0] -- 2026-09-06
9
52
 
10
53
  Recipes ship as code (U-13). The three GitHub-only recipe volumes are
11
54
  consolidated into one `UIFXRecipes.js` at the package root, exposed as the
package/UIFXController.js CHANGED
@@ -22,7 +22,7 @@ import { Ticker } from '@zakkster/lite-ticker';
22
22
 
23
23
  // Three-place version sync: this constant, package.json "version", and the
24
24
  // VERSION line in llms.txt must always match. /release keeps them locked.
25
- export const VERSION = '1.2.0';
25
+ export const VERSION = '1.3.0';
26
26
 
27
27
  // ---------------------------------------------------------
28
28
  // SHARED TICKER (ref-counted, one RAF for all UI components)
@@ -213,7 +213,10 @@ export function mountUIFX(container, type, recipeFactory, options = {}) {
213
213
 
214
214
  // 4. recipe object + hooks. Created now so a bad recipe throws BEFORE any
215
215
  // DOM/refcount side effect; .init is deferred to phase 2 (needs ctx).
216
- const recipe = recipeFactory();
216
+ // The validated options are forwarded so a recipe factory can read its
217
+ // own visual config and default a canvas `text` to the accessible
218
+ // `label`; a zero-arg or user-wrapped factory ignores the argument.
219
+ const recipe = recipeFactory(options);
217
220
  if (!recipe || typeof recipe !== 'object') {
218
221
  throw new Error('mountUIFX: recipe must be an object');
219
222
  }