@viji-dev/core 0.16.0 → 0.17.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.
@@ -284,16 +284,28 @@ declare global {
284
284
  group?: string;
285
285
  /** Visibility category. The control hides when its capability is unavailable. Default: `'general'`. */
286
286
  category?: ParameterCategory;
287
+ /**
288
+ * Enable a transparency channel. When `true` the canonical value is always an
289
+ * 8-digit `#rrggbbaa` (opaque inputs are padded `ff`), the picker shows an alpha
290
+ * slider, and the shader uniform is a `vec4`. When `false` (default) the value is
291
+ * `#rrggbb` and any alpha-bearing input is rejected. Default: `false`.
292
+ */
293
+ alpha?: boolean;
287
294
  }
288
295
 
289
296
  /**
290
297
  * Accepted input forms for color parameters. Internally normalized to canonical
291
- * lowercase 6-digit hex `#rrggbb`. See `viji.color()` for full documentation.
298
+ * lowercase hex: `#rrggbb` for an opaque parameter, `#rrggbbaa` for a parameter
299
+ * declared with `alpha: true`. See `viji.color()` for full documentation.
292
300
  *
293
301
  * - `string`: hex (`#rrggbb`, `#rgb`), CSS `rgb(r, g, b)`, CSS `hsl(h, s%, l%)`,
294
302
  * GLSL-style `vec3(r, g, b)` (0..1), or P5-style `hsb(h, s, b)` (0..360 / 0..100 / 0..100)
295
303
  * - `{ r, g, b }`: RGB object with components in 0..255
296
304
  * - `{ h, s, b }`: HSB object with `h` in 0..360, `s` and `b` in 0..100
305
+ *
306
+ * Alpha-bearing forms (`#rrggbbaa`, `#rgba`, `rgba()`, `hsla()`, `vec4()`, and the
307
+ * objects with an `a` field in 0..1) are accepted ONLY by a parameter declared with
308
+ * `alpha: true`; an opaque parameter rejects them even when the alpha is `1`.
297
309
  */
298
310
  type ColorInput = string | {
299
311
  /** Red component in 0..255. */
@@ -302,6 +314,8 @@ declare global {
302
314
  g: number;
303
315
  /** Blue component in 0..255. */
304
316
  b: number;
317
+ /** Alpha in 0..1. Only valid on a parameter declared with `alpha: true`. */
318
+ a?: number;
305
319
  } | {
306
320
  /** Hue in 0..360. */
307
321
  h: number;
@@ -309,16 +323,22 @@ declare global {
309
323
  s: number;
310
324
  /** Brightness in 0..100. */
311
325
  b: number;
326
+ /** Alpha in 0..1. Only valid on a parameter declared with `alpha: true`. */
327
+ a?: number;
312
328
  };
313
329
 
314
330
  /**
315
331
  * Reactive object returned by `viji.color()`. `value` is always a canonical
316
- * lowercase 6-digit hex string; `rgb` and `hsb` are derived accessors that are
317
- * recomputed (and frozen) every time the user changes the color.
332
+ * lowercase hex string whose width is fixed by the parameter's mode (`#rrggbb`,
333
+ * or `#rrggbbaa` when declared with `alpha: true`); `rgb`, `hsb` and `alpha` are
334
+ * derived accessors that are recomputed (and frozen) every time the user changes
335
+ * the color.
318
336
  */
319
337
  interface ColorParameter {
320
- /** Canonical hex color string `#rrggbb` (lowercase). Updates in real-time. */
338
+ /** Canonical lowercase hex color string: `#rrggbb`, or `#rrggbbaa` when `alpha: true`. Updates in real-time. */
321
339
  value: string;
340
+ /** Alpha in 0..1. Always present: `1` on an opaque parameter, the live alpha when `alpha: true`. */
341
+ alpha: number;
322
342
  /** RGB components as integers in 0..255 (frozen, recomputed when value changes). */
323
343
  rgb: {
324
344
  /** Red component, integer in 0..255. */
@@ -708,6 +728,101 @@ declare global {
708
728
  max: number;
709
729
  }
710
730
 
731
+ /**
732
+ * Configuration object passed to `viji.gradient()`. Defines the ramp editor's
733
+ * stop bounds, transparency mode, label and UI grouping/visibility.
734
+ */
735
+ interface GradientConfig {
736
+ /**
737
+ * Advanced: explicit parameter identity. Normally you do NOT set this —
738
+ * the parameter's name is inferred from the variable or object key you
739
+ * assign it to (`const ramp = viji.gradient(...)` → `ramp`). Set `name`
740
+ * only for parameters not assigned to a variable or key (created in an
741
+ * array, loop, or factory). Must be a valid identifier and scene-globally
742
+ * unique. When set, it overrides the inferred name.
743
+ */
744
+ name?: string;
745
+ /** Minimum number of stops the editor allows. Integer in `2..32`. Default: `2`. */
746
+ minStops?: number;
747
+ /** Maximum number of stops the editor allows. Integer in `2..32`; sizes the shader uniform arrays. Default: `8`. */
748
+ maxStops?: number;
749
+ /** Display name shown next to the ramp in the parameter UI. Optional — defaults to the parameter's name. */
750
+ label?: string;
751
+ /** Optional tooltip / help text shown next to the control. */
752
+ description?: string;
753
+ /** Group name for organizing related parameters under a shared heading. Default: `'general'`. */
754
+ group?: string;
755
+ /** Visibility category. The control hides when its capability is unavailable. Default: `'general'`. */
756
+ category?: ParameterCategory;
757
+ /**
758
+ * Enable per-stop transparency. When `true` every stop color is `#rrggbbaa`
759
+ * (opaque inputs padded `ff`) and the shader sampler returns a `vec4`. When
760
+ * `false` (default) stops are `#rrggbb` and alpha-bearing stop colors are rejected.
761
+ */
762
+ alpha?: boolean;
763
+ }
764
+
765
+ /**
766
+ * Stop list accepted by `viji.gradient()` and `setParameter()`. Any order;
767
+ * normalized to a sorted, canonical {@link GradientValue}.
768
+ */
769
+ type GradientInput = ReadonlyArray<GradientStopInput>;
770
+
771
+ /**
772
+ * Reactive object returned by `viji.gradient()`. `value` is the live, frozen,
773
+ * sorted stop list; `at(t)` samples the ramp with CSS `linear-gradient`
774
+ * semantics (premultiplied sRGB between stops, hard edges on duplicate
775
+ * positions) and returns a canonical hex string in the same width as the stops.
776
+ */
777
+ interface GradientParameter {
778
+ /** Current stops, frozen and sorted ascending by position. Updates in real-time. */
779
+ value: GradientValue;
780
+ /**
781
+ * Sample the ramp at `t` (clamped to `0..1`). Returns canonical hex in the
782
+ * gradient's width. The shader renderer exposes the same function as
783
+ * `<name>(float t)` in GLSL.
784
+ */
785
+ at(t: number): string;
786
+ /** Display name shown next to the ramp in the parameter UI. */
787
+ label?: string;
788
+ /** Tooltip / help text for the control (empty string when not configured). */
789
+ description?: string;
790
+ /** Group name under which the control appears in the UI. */
791
+ group: string;
792
+ /** Visibility category that controls when the parameter is shown. */
793
+ category: ParameterCategory;
794
+ }
795
+
796
+ /**
797
+ * One stop of a gradient value. `color` is canonical lowercase hex in the
798
+ * gradient's mode (`#rrggbb`, or `#rrggbbaa` when declared with `alpha: true`).
799
+ */
800
+ interface GradientStop {
801
+ /** Canonical hex color of this stop. */
802
+ color: string;
803
+ /** Position along the ramp in `0..1`. */
804
+ position: number;
805
+ }
806
+
807
+ /**
808
+ * One artist- or host-supplied gradient stop. `color` accepts every form a
809
+ * color parameter accepts, normalized per the gradient's `alpha` mode.
810
+ */
811
+ interface GradientStopInput {
812
+ /** Any accepted color form (hex, CSS functions, RGB / HSB objects). */
813
+ color: ColorInput;
814
+ /** Position along the ramp in `0..1`. */
815
+ position: number;
816
+ }
817
+
818
+ /**
819
+ * Value of a gradient parameter: a frozen list of stops sorted ascending by
820
+ * position. Duplicate positions are allowed and form a hard edge. The length is
821
+ * within the parameter's `minStops..maxStops`. No wrapper: geometry (linear,
822
+ * radial, angle) is the scene's concern.
823
+ */
824
+ type GradientValue = readonly GradientStop[];
825
+
711
826
  /**
712
827
  * One detected hand produced by the video CV pipeline. Carries 21 landmarks,
713
828
  * a palm shortcut, and ML-classified gesture confidence scores. Up to two
@@ -1350,7 +1465,7 @@ declare global {
1350
1465
  isEnding: boolean;
1351
1466
  }
1352
1467
 
1353
- const VERSION = "0.16.0";
1468
+ const VERSION = "0.17.0";
1354
1469
 
1355
1470
  /**
1356
1471
  * Real-time video API: drawable frame, dimensions, and the source-side
@@ -1594,12 +1709,17 @@ declare global {
1594
1709
  slider: (defaultValue: number, config: SliderConfig) => SliderParameter;
1595
1710
  /**
1596
1711
  * Declares a color parameter. Accepts hex strings, CSS color functions, or RGB / HSB objects;
1597
- * the value is always normalized to a canonical lowercase hex string and exposes derived `.rgb` / `.hsb` accessors.
1712
+ * the value is always normalized to a canonical lowercase hex string and exposes derived
1713
+ * `.rgb` / `.hsb` / `.alpha` accessors. Pass `alpha: true` to enable transparency: the value
1714
+ * becomes `#rrggbbaa` and alpha-bearing inputs (`rgba()`, `#rrggbbaa`, ...) are accepted.
1715
+ * Without it, alpha-bearing inputs are rejected.
1598
1716
  * Must be called at the top level of the scene, never inside `render()`.
1599
1717
  *
1600
1718
  * @example
1601
1719
  * const tint = viji.color('#ff6600', { label: 'Tint' });
1602
- * // tint.value -> '#ff6600', tint.rgb -> { r: 255, g: 102, b: 0 }, tint.hsb -> { h: 24, s: 100, b: 100 }
1720
+ * // tint.value -> '#ff6600', tint.rgb -> { r: 255, g: 102, b: 0 }, tint.hsb -> { h: 24, s: 100, b: 100 }, tint.alpha -> 1
1721
+ * const glow = viji.color('#ffffff80', { label: 'Glow', alpha: true });
1722
+ * // glow.value -> '#ffffff80', glow.alpha -> 0.5
1603
1723
  */
1604
1724
  color: (defaultValue: ColorInput, config: ColorConfig) => ColorParameter;
1605
1725
  /**
@@ -1665,6 +1785,27 @@ declare global {
1665
1785
  * const cx = viji.width / 2 + origin.value.x * viji.width * 0.4;
1666
1786
  */
1667
1787
  coordinate: (defaultValue: CoordinateValue, config: CoordinateConfig) => CoordinateParameter;
1788
+ /**
1789
+ * Declares a gradient parameter. The host renders a ramp editor; `value` is the live,
1790
+ * sorted stop list and `at(t)` samples the ramp (CSS `linear-gradient` semantics).
1791
+ * Stop colors accept every color form; pass `alpha: true` for per-stop transparency.
1792
+ * `default` is required (no evenly-spaced shorthand). Must be called at the top level
1793
+ * of the scene, never inside `render()`.
1794
+ *
1795
+ * @example
1796
+ * const ramp = viji.gradient(
1797
+ * [{ color: '#ff6b6b', position: 0 }, { color: '#4ecdc4', position: 1 }],
1798
+ * { label: 'Ramp' }
1799
+ * );
1800
+ * function render(viji) {
1801
+ * const fill = viji.ctx.createLinearGradient(0, 0, viji.width, 0);
1802
+ * for (const stop of ramp.value) fill.addColorStop(stop.position, stop.color);
1803
+ * viji.ctx.fillStyle = fill;
1804
+ * viji.ctx.fillRect(0, 0, viji.width, viji.height);
1805
+ * viji.ctx.fillStyle = ramp.at(0.5); // per-element color, same math as the fill
1806
+ * }
1807
+ */
1808
+ gradient: (defaultValue: GradientInput, config: GradientConfig) => GradientParameter;
1668
1809
  /**
1669
1810
  * Selects the 2D canvas rendering context. Returns the same instance on
1670
1811
  * subsequent calls and also stores it on `viji.ctx`. A canvas only supports
@@ -284,16 +284,28 @@ declare global {
284
284
  group?: string;
285
285
  /** Visibility category. The control hides when its capability is unavailable. Default: `'general'`. */
286
286
  category?: ParameterCategory;
287
+ /**
288
+ * Enable a transparency channel. When `true` the canonical value is always an
289
+ * 8-digit `#rrggbbaa` (opaque inputs are padded `ff`), the picker shows an alpha
290
+ * slider, and the shader uniform is a `vec4`. When `false` (default) the value is
291
+ * `#rrggbb` and any alpha-bearing input is rejected. Default: `false`.
292
+ */
293
+ alpha?: boolean;
287
294
  }
288
295
 
289
296
  /**
290
297
  * Accepted input forms for color parameters. Internally normalized to canonical
291
- * lowercase 6-digit hex `#rrggbb`. See `viji.color()` for full documentation.
298
+ * lowercase hex: `#rrggbb` for an opaque parameter, `#rrggbbaa` for a parameter
299
+ * declared with `alpha: true`. See `viji.color()` for full documentation.
292
300
  *
293
301
  * - `string`: hex (`#rrggbb`, `#rgb`), CSS `rgb(r, g, b)`, CSS `hsl(h, s%, l%)`,
294
302
  * GLSL-style `vec3(r, g, b)` (0..1), or P5-style `hsb(h, s, b)` (0..360 / 0..100 / 0..100)
295
303
  * - `{ r, g, b }`: RGB object with components in 0..255
296
304
  * - `{ h, s, b }`: HSB object with `h` in 0..360, `s` and `b` in 0..100
305
+ *
306
+ * Alpha-bearing forms (`#rrggbbaa`, `#rgba`, `rgba()`, `hsla()`, `vec4()`, and the
307
+ * objects with an `a` field in 0..1) are accepted ONLY by a parameter declared with
308
+ * `alpha: true`; an opaque parameter rejects them even when the alpha is `1`.
297
309
  */
298
310
  type ColorInput = string | {
299
311
  /** Red component in 0..255. */
@@ -302,6 +314,8 @@ declare global {
302
314
  g: number;
303
315
  /** Blue component in 0..255. */
304
316
  b: number;
317
+ /** Alpha in 0..1. Only valid on a parameter declared with `alpha: true`. */
318
+ a?: number;
305
319
  } | {
306
320
  /** Hue in 0..360. */
307
321
  h: number;
@@ -309,16 +323,22 @@ declare global {
309
323
  s: number;
310
324
  /** Brightness in 0..100. */
311
325
  b: number;
326
+ /** Alpha in 0..1. Only valid on a parameter declared with `alpha: true`. */
327
+ a?: number;
312
328
  };
313
329
 
314
330
  /**
315
331
  * Reactive object returned by `viji.color()`. `value` is always a canonical
316
- * lowercase 6-digit hex string; `rgb` and `hsb` are derived accessors that are
317
- * recomputed (and frozen) every time the user changes the color.
332
+ * lowercase hex string whose width is fixed by the parameter's mode (`#rrggbb`,
333
+ * or `#rrggbbaa` when declared with `alpha: true`); `rgb`, `hsb` and `alpha` are
334
+ * derived accessors that are recomputed (and frozen) every time the user changes
335
+ * the color.
318
336
  */
319
337
  interface ColorParameter {
320
- /** Canonical hex color string `#rrggbb` (lowercase). Updates in real-time. */
338
+ /** Canonical lowercase hex color string: `#rrggbb`, or `#rrggbbaa` when `alpha: true`. Updates in real-time. */
321
339
  value: string;
340
+ /** Alpha in 0..1. Always present: `1` on an opaque parameter, the live alpha when `alpha: true`. */
341
+ alpha: number;
322
342
  /** RGB components as integers in 0..255 (frozen, recomputed when value changes). */
323
343
  rgb: {
324
344
  /** Red component, integer in 0..255. */
@@ -708,6 +728,101 @@ declare global {
708
728
  max: number;
709
729
  }
710
730
 
731
+ /**
732
+ * Configuration object passed to `viji.gradient()`. Defines the ramp editor's
733
+ * stop bounds, transparency mode, label and UI grouping/visibility.
734
+ */
735
+ interface GradientConfig {
736
+ /**
737
+ * Advanced: explicit parameter identity. Normally you do NOT set this —
738
+ * the parameter's name is inferred from the variable or object key you
739
+ * assign it to (`const ramp = viji.gradient(...)` → `ramp`). Set `name`
740
+ * only for parameters not assigned to a variable or key (created in an
741
+ * array, loop, or factory). Must be a valid identifier and scene-globally
742
+ * unique. When set, it overrides the inferred name.
743
+ */
744
+ name?: string;
745
+ /** Minimum number of stops the editor allows. Integer in `2..32`. Default: `2`. */
746
+ minStops?: number;
747
+ /** Maximum number of stops the editor allows. Integer in `2..32`; sizes the shader uniform arrays. Default: `8`. */
748
+ maxStops?: number;
749
+ /** Display name shown next to the ramp in the parameter UI. Optional — defaults to the parameter's name. */
750
+ label?: string;
751
+ /** Optional tooltip / help text shown next to the control. */
752
+ description?: string;
753
+ /** Group name for organizing related parameters under a shared heading. Default: `'general'`. */
754
+ group?: string;
755
+ /** Visibility category. The control hides when its capability is unavailable. Default: `'general'`. */
756
+ category?: ParameterCategory;
757
+ /**
758
+ * Enable per-stop transparency. When `true` every stop color is `#rrggbbaa`
759
+ * (opaque inputs padded `ff`) and the shader sampler returns a `vec4`. When
760
+ * `false` (default) stops are `#rrggbb` and alpha-bearing stop colors are rejected.
761
+ */
762
+ alpha?: boolean;
763
+ }
764
+
765
+ /**
766
+ * Stop list accepted by `viji.gradient()` and `setParameter()`. Any order;
767
+ * normalized to a sorted, canonical {@link GradientValue}.
768
+ */
769
+ type GradientInput = ReadonlyArray<GradientStopInput>;
770
+
771
+ /**
772
+ * Reactive object returned by `viji.gradient()`. `value` is the live, frozen,
773
+ * sorted stop list; `at(t)` samples the ramp with CSS `linear-gradient`
774
+ * semantics (premultiplied sRGB between stops, hard edges on duplicate
775
+ * positions) and returns a canonical hex string in the same width as the stops.
776
+ */
777
+ interface GradientParameter {
778
+ /** Current stops, frozen and sorted ascending by position. Updates in real-time. */
779
+ value: GradientValue;
780
+ /**
781
+ * Sample the ramp at `t` (clamped to `0..1`). Returns canonical hex in the
782
+ * gradient's width. The shader renderer exposes the same function as
783
+ * `<name>(float t)` in GLSL.
784
+ */
785
+ at(t: number): string;
786
+ /** Display name shown next to the ramp in the parameter UI. */
787
+ label?: string;
788
+ /** Tooltip / help text for the control (empty string when not configured). */
789
+ description?: string;
790
+ /** Group name under which the control appears in the UI. */
791
+ group: string;
792
+ /** Visibility category that controls when the parameter is shown. */
793
+ category: ParameterCategory;
794
+ }
795
+
796
+ /**
797
+ * One stop of a gradient value. `color` is canonical lowercase hex in the
798
+ * gradient's mode (`#rrggbb`, or `#rrggbbaa` when declared with `alpha: true`).
799
+ */
800
+ interface GradientStop {
801
+ /** Canonical hex color of this stop. */
802
+ color: string;
803
+ /** Position along the ramp in `0..1`. */
804
+ position: number;
805
+ }
806
+
807
+ /**
808
+ * One artist- or host-supplied gradient stop. `color` accepts every form a
809
+ * color parameter accepts, normalized per the gradient's `alpha` mode.
810
+ */
811
+ interface GradientStopInput {
812
+ /** Any accepted color form (hex, CSS functions, RGB / HSB objects). */
813
+ color: ColorInput;
814
+ /** Position along the ramp in `0..1`. */
815
+ position: number;
816
+ }
817
+
818
+ /**
819
+ * Value of a gradient parameter: a frozen list of stops sorted ascending by
820
+ * position. Duplicate positions are allowed and form a hard edge. The length is
821
+ * within the parameter's `minStops..maxStops`. No wrapper: geometry (linear,
822
+ * radial, angle) is the scene's concern.
823
+ */
824
+ type GradientValue = readonly GradientStop[];
825
+
711
826
  /**
712
827
  * One detected hand produced by the video CV pipeline. Carries 21 landmarks,
713
828
  * a palm shortcut, and ML-classified gesture confidence scores. Up to two
@@ -1339,7 +1454,7 @@ declare global {
1339
1454
  isEnding: boolean;
1340
1455
  }
1341
1456
 
1342
- const VERSION = "0.16.0";
1457
+ const VERSION = "0.17.0";
1343
1458
 
1344
1459
  /**
1345
1460
  * Real-time video API: drawable frame, dimensions, and the source-side
@@ -1583,12 +1698,17 @@ declare global {
1583
1698
  slider: (defaultValue: number, config: SliderConfig) => SliderParameter;
1584
1699
  /**
1585
1700
  * Declares a color parameter. Accepts hex strings, CSS color functions, or RGB / HSB objects;
1586
- * the value is always normalized to a canonical lowercase hex string and exposes derived `.rgb` / `.hsb` accessors.
1701
+ * the value is always normalized to a canonical lowercase hex string and exposes derived
1702
+ * `.rgb` / `.hsb` / `.alpha` accessors. Pass `alpha: true` to enable transparency: the value
1703
+ * becomes `#rrggbbaa` and alpha-bearing inputs (`rgba()`, `#rrggbbaa`, ...) are accepted.
1704
+ * Without it, alpha-bearing inputs are rejected.
1587
1705
  * Must be called at the top level of the scene, never inside `render()`.
1588
1706
  *
1589
1707
  * @example
1590
1708
  * const tint = viji.color('#ff6600', { label: 'Tint' });
1591
- * // tint.value -> '#ff6600', tint.rgb -> { r: 255, g: 102, b: 0 }, tint.hsb -> { h: 24, s: 100, b: 100 }
1709
+ * // tint.value -> '#ff6600', tint.rgb -> { r: 255, g: 102, b: 0 }, tint.hsb -> { h: 24, s: 100, b: 100 }, tint.alpha -> 1
1710
+ * const glow = viji.color('#ffffff80', { label: 'Glow', alpha: true });
1711
+ * // glow.value -> '#ffffff80', glow.alpha -> 0.5
1592
1712
  */
1593
1713
  color: (defaultValue: ColorInput, config: ColorConfig) => ColorParameter;
1594
1714
  /**
@@ -1654,6 +1774,27 @@ declare global {
1654
1774
  * const cx = viji.width / 2 + origin.value.x * viji.width * 0.4;
1655
1775
  */
1656
1776
  coordinate: (defaultValue: CoordinateValue, config: CoordinateConfig) => CoordinateParameter;
1777
+ /**
1778
+ * Declares a gradient parameter. The host renders a ramp editor; `value` is the live,
1779
+ * sorted stop list and `at(t)` samples the ramp (CSS `linear-gradient` semantics).
1780
+ * Stop colors accept every color form; pass `alpha: true` for per-stop transparency.
1781
+ * `default` is required (no evenly-spaced shorthand). Must be called at the top level
1782
+ * of the scene, never inside `render()`.
1783
+ *
1784
+ * @example
1785
+ * const ramp = viji.gradient(
1786
+ * [{ color: '#ff6b6b', position: 0 }, { color: '#4ecdc4', position: 1 }],
1787
+ * { label: 'Ramp' }
1788
+ * );
1789
+ * function render(viji) {
1790
+ * const fill = viji.ctx.createLinearGradient(0, 0, viji.width, 0);
1791
+ * for (const stop of ramp.value) fill.addColorStop(stop.position, stop.color);
1792
+ * viji.ctx.fillStyle = fill;
1793
+ * viji.ctx.fillRect(0, 0, viji.width, viji.height);
1794
+ * viji.ctx.fillStyle = ramp.at(0.5); // per-element color, same math as the fill
1795
+ * }
1796
+ */
1797
+ gradient: (defaultValue: GradientInput, config: GradientConfig) => GradientParameter;
1657
1798
  /**
1658
1799
  * Selects the 2D canvas rendering context. Returns the same instance on
1659
1800
  * subsequent calls and also stores it on `viji.ctx`. A canvas only supports
@@ -24,6 +24,7 @@
24
24
  * @property {string} [description] - Optional tooltip / help text shown next to the control.
25
25
  * @property {string} [group] - Group name for organizing related parameters under a shared heading. Default: `'general'`.
26
26
  * @property {ParameterCategory} [category] - Visibility category. The control hides when its capability is unavailable. Default: `'general'`.
27
+ * @property {boolean} [alpha] - Enable a transparency channel. When `true` the canonical value is always an 8-digit `#rrggbbaa` (opaque inputs are padded `ff`), the picker shows an alpha slider, and the shader uniform is a `vec4`. When `false` (default) the value is `#rrggbb` and any alpha-bearing input is rejected. Default: `false`.
27
28
  */
28
29
 
29
30
  /**
@@ -102,6 +103,19 @@
102
103
  * @property {ParameterCategory} [category] - Visibility category. The control hides when its capability is unavailable. Default: `'general'`.
103
104
  */
104
105
 
106
+ /**
107
+ * Configuration object passed to `viji.gradient()`. Defines the ramp editor's stop bounds, transparency mode, label and UI grouping/visibility.
108
+ * @typedef {Object} GradientConfig
109
+ * @property {string} [name] - Advanced: explicit parameter identity. Normally you do NOT set this — the parameter's name is inferred from the variable or object key you assign it to (`const ramp = viji.gradient(...)` → `ramp`). Set `name` only for parameters not assigned to a variable or key (created in an array, loop, or factory). Must be a valid identifier and scene-globally unique. When set, it overrides the inferred name.
110
+ * @property {number} [minStops] - Minimum number of stops the editor allows. Integer in `2..32`. Default: `2`.
111
+ * @property {number} [maxStops] - Maximum number of stops the editor allows. Integer in `2..32`; sizes the shader uniform arrays. Default: `8`.
112
+ * @property {string} [label] - Display name shown next to the ramp in the parameter UI. Optional — defaults to the parameter's name.
113
+ * @property {string} [description] - Optional tooltip / help text shown next to the control.
114
+ * @property {string} [group] - Group name for organizing related parameters under a shared heading. Default: `'general'`.
115
+ * @property {ParameterCategory} [category] - Visibility category. The control hides when its capability is unavailable. Default: `'general'`.
116
+ * @property {boolean} [alpha] - Enable per-stop transparency. When `true` every stop color is `#rrggbbaa` (opaque inputs padded `ff`) and the shader sampler returns a `vec4`. When `false` (default) stops are `#rrggbb` and alpha-bearing stop colors are rejected.
117
+ */
118
+
105
119
  /**
106
120
  * Reactive object returned by `viji.slider()`. `value` updates in real-time as the user drags the control; the remaining fields mirror the configuration.
107
121
  * @typedef {Object} SliderParameter
@@ -116,9 +130,10 @@
116
130
  */
117
131
 
118
132
  /**
119
- * Reactive object returned by `viji.color()`. `value` is always a canonical lowercase 6-digit hex string; `rgb` and `hsb` are derived accessors that are recomputed (and frozen) every time the user changes the color.
133
+ * Reactive object returned by `viji.color()`. `value` is always a canonical lowercase hex string whose width is fixed by the parameter's mode (`#rrggbb`, or `#rrggbbaa` when declared with `alpha: true`); `rgb`, `hsb` and `alpha` are derived accessors that are recomputed (and frozen) every time the user changes the color.
120
134
  * @typedef {Object} ColorParameter
121
- * @property {string} value - Canonical hex color string `#rrggbb` (lowercase). Updates in real-time.
135
+ * @property {string} value - Canonical lowercase hex color string: `#rrggbb`, or `#rrggbbaa` when `alpha: true`. Updates in real-time.
136
+ * @property {number} alpha - Alpha in 0..1. Always present: `1` on an opaque parameter, the live alpha when `alpha: true`.
122
137
  * @property {Object} rgb - RGB components as integers in 0..255 (frozen, recomputed when value changes).
123
138
  * @property {number} rgb.r - Red component, integer in 0..255.
124
139
  * @property {number} rgb.g - Green component, integer in 0..255.
@@ -209,6 +224,31 @@
209
224
  * @property {ParameterCategory} category - Visibility category that controls when the parameter is shown.
210
225
  */
211
226
 
227
+ /**
228
+ * Reactive object returned by `viji.gradient()`. `value` is the live, frozen, sorted stop list; `at(t)` samples the ramp with CSS `linear-gradient` semantics (premultiplied sRGB between stops, hard edges on duplicate positions) and returns a canonical hex string in the same width as the stops.
229
+ * @typedef {Object} GradientParameter
230
+ * @property {GradientValue} value - Current stops, frozen and sorted ascending by position. Updates in real-time.
231
+ * @property {(t: number) => string} at - Sample the ramp at `t` (clamped to `0..1`). Returns canonical hex in the gradient's width. The shader renderer exposes the same function as `<name>(float t)` in GLSL.
232
+ * @property {string} [label] - Display name shown next to the ramp in the parameter UI.
233
+ * @property {string} [description] - Tooltip / help text for the control (empty string when not configured).
234
+ * @property {string} group - Group name under which the control appears in the UI.
235
+ * @property {ParameterCategory} category - Visibility category that controls when the parameter is shown.
236
+ */
237
+
238
+ /**
239
+ * One stop of a gradient value. `color` is canonical lowercase hex in the gradient's mode (`#rrggbb`, or `#rrggbbaa` when declared with `alpha: true`).
240
+ * @typedef {Object} GradientStop
241
+ * @property {string} color - Canonical hex color of this stop.
242
+ * @property {number} position - Position along the ramp in `0..1`.
243
+ */
244
+
245
+ /**
246
+ * One artist- or host-supplied gradient stop. `color` accepts every form a color parameter accepts, normalized per the gradient's `alpha` mode.
247
+ * @typedef {Object} GradientStopInput
248
+ * @property {ColorInput} color - Any accepted color form (hex, CSS functions, RGB / HSB objects).
249
+ * @property {number} position - Position along the ramp in `0..1`.
250
+ */
251
+
212
252
  /**
213
253
  * Real-time audio analysis for the main audio stream (`viji.audio`). Provides volume, frequency bands, beat detection (with triggers, events, BPM), spectral features, and access to raw FFT / waveform data. All numeric outputs are zeroed when `isConnected` is `false`.
214
254
  * @typedef {Object} AudioAPI
@@ -358,7 +398,7 @@
358
398
  * @property {DeviceSensorState} device - Internal device sensors (motion + orientation) reported by the device running the scene.
359
399
  * @property {DeviceState[]} devices - External connected devices reporting sensor / camera / audio. Each entry has its own `id`, `name`, and per-device API surface.
360
400
  * @property {(defaultValue: number, config: SliderConfig) => SliderParameter} slider - Declares a numeric slider parameter. The host UI renders a draggable slider. Must be called at the top level of the scene, never inside `render()`. @example const radius = viji.slider(50, { min: 10, max: 200, step: 1, label: 'Radius' }); // ... function render(viji) { drawCircle(radius.value); }
361
- * @property {(defaultValue: ColorInput, config: ColorConfig) => ColorParameter} color - Declares a color parameter. Accepts hex strings, CSS color functions, or RGB / HSB objects; the value is always normalized to a canonical lowercase hex string and exposes derived `.rgb` / `.hsb` accessors. Must be called at the top level of the scene, never inside `render()`. @example const tint = viji.color('#ff6600', { label: 'Tint' }); // tint.value -> '#ff6600', tint.rgb -> { r: 255, g: 102, b: 0 }, tint.hsb -> { h: 24, s: 100, b: 100 }
401
+ * @property {(defaultValue: ColorInput, config: ColorConfig) => ColorParameter} color - Declares a color parameter. Accepts hex strings, CSS color functions, or RGB / HSB objects; the value is always normalized to a canonical lowercase hex string and exposes derived `.rgb` / `.hsb` / `.alpha` accessors. Pass `alpha: true` to enable transparency: the value becomes `#rrggbbaa` and alpha-bearing inputs (`rgba()`, `#rrggbbaa`, ...) are accepted. Without it, alpha-bearing inputs are rejected. Must be called at the top level of the scene, never inside `render()`. @example const tint = viji.color('#ff6600', { label: 'Tint' }); // tint.value -> '#ff6600', tint.rgb -> { r: 255, g: 102, b: 0 }, tint.hsb -> { h: 24, s: 100, b: 100 }, tint.alpha -> 1 const glow = viji.color('#ffffff80', { label: 'Glow', alpha: true }); // glow.value -> '#ffffff80', glow.alpha -> 0.5
362
402
  * @property {(defaultValue: boolean, config: ToggleConfig) => ToggleParameter} toggle - Declares a boolean toggle parameter. The host UI renders an on/off switch. Must be called at the top level of the scene, never inside `render()`. @example const showTrail = viji.toggle(true, { label: 'Show Trail' });
363
403
  * @property {(defaultValue: string | number, config: SelectConfig) => SelectParameter} select - Declares a dropdown selection parameter. The element type of `options` (`string` or `number`) determines the parameter's value type. Must be called at the top level of the scene, never inside `render()`. @example const shape = viji.select('circle', { options: ['circle', 'square', 'triangle'], label: 'Shape' });
364
404
  * @property {(defaultValue: string, config: TextConfig) => TextParameter} text - Declares a text input parameter. The host UI renders a single-line text field. Must be called at the top level of the scene, never inside `render()`. @example const caption = viji.text('Hello', { label: 'Caption', maxLength: 64 });
@@ -366,6 +406,7 @@
366
406
  * @property {(defaultValue: null, config: ImageConfig) => ImageParameter} image - Declares an image upload parameter. The user-supplied image becomes available as `value` (an `ImageBitmap`); in P5 scenes a `.p5` accessor is also added at runtime. Must be called at the top level of the scene, never inside `render()`. @example const tex = viji.image(null, { label: 'Texture' }); if (tex.value) ctx.drawImage(tex.value, 0, 0, viji.width, viji.height);
367
407
  * @property {(config: ButtonConfig) => ButtonParameter} button - Declares a momentary button parameter. `value` is `true` for one frame after the user clicks, then auto-resets. Perfect for triggering discrete events. Must be called at the top level of the scene, never inside `render()`. @example const reset = viji.button({ label: 'Reset' }); function render(viji) { if (reset.value) state = initialState; }
368
408
  * @property {(defaultValue: CoordinateValue, config: CoordinateConfig) => CoordinateParameter} coordinate - Declares a 2D coordinate parameter. Both `value.x` and `value.y` are in `-1..1`. Must be called at the top level of the scene, never inside `render()`. @example const origin = viji.coordinate({ x: 0, y: 0 }, { label: 'Origin' }); const cx = viji.width / 2 + origin.value.x * viji.width * 0.4;
409
+ * @property {(defaultValue: GradientInput, config: GradientConfig) => GradientParameter} gradient - Declares a gradient parameter. The host renders a ramp editor; `value` is the live, sorted stop list and `at(t)` samples the ramp (CSS `linear-gradient` semantics). Stop colors accept every color form; pass `alpha: true` for per-stop transparency. `default` is required (no evenly-spaced shorthand). Must be called at the top level of the scene, never inside `render()`. @example const ramp = viji.gradient( [{ color: '#ff6b6b', position: 0 }, { color: '#4ecdc4', position: 1 }], { label: 'Ramp' } ); function render(viji) { const fill = viji.ctx.createLinearGradient(0, 0, viji.width, 0); for (const stop of ramp.value) fill.addColorStop(stop.position, stop.color); viji.ctx.fillStyle = fill; viji.ctx.fillRect(0, 0, viji.width, viji.height); viji.ctx.fillStyle = ramp.at(0.5); // per-element color, same math as the fill }
369
410
  * @property {(type: '2d') => OffscreenCanvasRenderingContext2D} useContext - Selects the 2D canvas rendering context. Returns the same instance on subsequent calls and also stores it on `viji.ctx`. A canvas only supports one context type. If a different context type was already requested, the call returns `null`. Choose ONE type and use it for the entire scene. @example const ctx = viji.useContext('2d'); ctx.fillRect(0, 0, viji.width, viji.height);
370
411
  * @property {(type: 'webgl') => WebGLRenderingContext} useContext - Selects a WebGL 1 rendering context. Returns the same instance on subsequent calls and also stores it on `viji.gl`. A canvas only supports one context type. If a different context type was already requested, the call returns `null`. Choose ONE type and use it for the entire scene.
371
412
  * @property {(type: 'webgl2') => WebGL2RenderingContext} useContext - Selects a WebGL 2 rendering context. Returns the same instance on subsequent calls and also stores it on `viji.gl`. A canvas only supports one context type. If a different context type was already requested, the call returns `null`. Choose ONE type and use it for the entire scene.