@glissade/scene 0.57.1-pre.0 → 0.58.0-pre.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/describe.js +2 -2
- package/dist/gradient.d.ts +16 -0
- package/dist/gradient.js +48 -0
- package/dist/index.js +2 -33
- package/dist/type.d.ts +15 -1
- package/dist/type.js +3 -1
- package/package.json +6 -2
package/dist/describe.js
CHANGED
|
@@ -23,7 +23,7 @@ import { easings, listValueTypes } from "@glissade/core";
|
|
|
23
23
|
* never pulled onto the base embed path — a scene that never calls `describe()`
|
|
24
24
|
* pays zero bytes for it.
|
|
25
25
|
*/
|
|
26
|
-
const RAW_VERSION = "0.
|
|
26
|
+
const RAW_VERSION = "0.58.0-pre.0";
|
|
27
27
|
const PACKAGE_VERSION = RAW_VERSION.includes("GLISSADE_".concat("VERSION")) ? "0.0.0-dev" : RAW_VERSION;
|
|
28
28
|
/**
|
|
29
29
|
* Parse the documented positional-arg count from a helper `usage` string — the
|
|
@@ -682,7 +682,7 @@ const HELPERS = [
|
|
|
682
682
|
name: "typeOn",
|
|
683
683
|
summary: "Kinetic type: one-call typewriter over the shipped typewriter(). DEFAULT emits a STRING hold-key track on `<id>/text` (round-trips to Lottie as stepped text docs). { cursor: true } adds a render-only caret sibling (export warns+drops it); { mask: true } swaps to a render-only `<id>/reveal` grapheme mask (export warns 'reveal not exported'). Factory (no `new`). Inject with tl.tracks([r.track]); draw r.node (+ r.cursor). On @glissade/scene/type.",
|
|
684
684
|
import: "@glissade/scene/type",
|
|
685
|
-
usage: "typeOn(source: Text | TextProps, opts?: { perChar?, start?, cursor?: boolean, mask?: boolean, cursorWidth?, blinkPeriod? }): { node: Text, cursor?: TextCursor, track: Track, marks, duration }"
|
|
685
|
+
usage: "typeOn(source: Text | TextProps, opts?: { perChar?, start?, cursor?: boolean, mask?: boolean, cursorWidth?, blinkPeriod?, cursorFill?, cursorProps? }): { node: Text, cursor?: TextCursor, track: Track, marks, duration } — cursorFill sets a contrasting caret color (default follows text fill); cursorProps forwards any other TextCursor prop"
|
|
686
686
|
},
|
|
687
687
|
{
|
|
688
688
|
name: "revealWords",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { ColorStop, GradientInterpolation } from "@glissade/core";
|
|
2
|
+
|
|
3
|
+
//#region src/gradient.d.ts
|
|
4
|
+
|
|
5
|
+
/** Resolution of the densified ramp — enough that the piecewise-linear blit of
|
|
6
|
+
* the easing curve shows no banding, cheap enough to rebuild per frame. */
|
|
7
|
+
declare const GRADIENT_RAMP_STEPS = 64;
|
|
8
|
+
/**
|
|
9
|
+
* Densify `stops` into a `smooth`/`gaussian` oklab ramp. The output spans the
|
|
10
|
+
* input's offset range with GRADIENT_RAMP_STEPS uniformly-spaced stops; each
|
|
11
|
+
* point eases its blend within the authored segment it falls in. Returns the
|
|
12
|
+
* input unchanged for `linear` (or a single stop) — the canvas-native path.
|
|
13
|
+
*/
|
|
14
|
+
declare function densifyStops(stops: ColorStop[], mode: GradientInterpolation): ColorStop[];
|
|
15
|
+
//#endregion
|
|
16
|
+
export { GRADIENT_RAMP_STEPS, densifyStops };
|
package/dist/gradient.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { lerpColor } from "@glissade/core";
|
|
2
|
+
//#region src/gradient.ts
|
|
3
|
+
/**
|
|
4
|
+
* Gradient stop densification (§3 Paint, 0.10.1). Canvas gradients interpolate
|
|
5
|
+
* BETWEEN stops linearly in the canvas color space, which Mach-bands a 2-3 stop
|
|
6
|
+
* soft-light fill. For `smooth`/`gaussian` interpolation we resample the stops
|
|
7
|
+
* into a dense ramp eased per-segment with oklab `lerpColor`, so the blit melts
|
|
8
|
+
* like a wide blur with no banding and no filter. Pure + deterministic: the same
|
|
9
|
+
* (stops, mode) always produce the same dense stops, so Skia stays byte-exact.
|
|
10
|
+
* `linear` is the canvas-native ramp and is never densified (byte-identical).
|
|
11
|
+
*/
|
|
12
|
+
/** Resolution of the densified ramp — enough that the piecewise-linear blit of
|
|
13
|
+
* the easing curve shows no banding, cheap enough to rebuild per frame. */
|
|
14
|
+
const GRADIENT_RAMP_STEPS = 64;
|
|
15
|
+
const smoothstep = (u) => u * u * (3 - 2 * u);
|
|
16
|
+
const GAUSS_K = 2.4;
|
|
17
|
+
const GAUSS_NORM = 1 - Math.exp(-5.76 / 2);
|
|
18
|
+
const gaussianEase = (u) => (1 - Math.exp(-((u * GAUSS_K) ** 2) / 2)) / GAUSS_NORM;
|
|
19
|
+
/**
|
|
20
|
+
* Densify `stops` into a `smooth`/`gaussian` oklab ramp. The output spans the
|
|
21
|
+
* input's offset range with GRADIENT_RAMP_STEPS uniformly-spaced stops; each
|
|
22
|
+
* point eases its blend within the authored segment it falls in. Returns the
|
|
23
|
+
* input unchanged for `linear` (or a single stop) — the canvas-native path.
|
|
24
|
+
*/
|
|
25
|
+
function densifyStops(stops, mode) {
|
|
26
|
+
if (mode === "linear" || stops.length < 2) return stops;
|
|
27
|
+
const ease = mode === "gaussian" ? gaussianEase : smoothstep;
|
|
28
|
+
const o0 = stops[0].offset;
|
|
29
|
+
const span = stops[stops.length - 1].offset - o0;
|
|
30
|
+
if (span <= 0) return stops;
|
|
31
|
+
const out = [];
|
|
32
|
+
let seg = 0;
|
|
33
|
+
for (let i = 0; i < 64; i++) {
|
|
34
|
+
const offset = o0 + span * (i / 63);
|
|
35
|
+
while (seg < stops.length - 2 && offset > stops[seg + 1].offset) seg++;
|
|
36
|
+
const a = stops[seg];
|
|
37
|
+
const b = stops[seg + 1];
|
|
38
|
+
const w = b.offset - a.offset;
|
|
39
|
+
const u = w > 0 ? Math.min(1, Math.max(0, (offset - a.offset) / w)) : 0;
|
|
40
|
+
out.push({
|
|
41
|
+
offset,
|
|
42
|
+
color: lerpColor(a.color, b.color, ease(u))
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
return out;
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
export { GRADIENT_RAMP_STEPS, densifyStops };
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,9 @@ import { a as evaluate, i as createScene, n as ReservedNodeIdError, r as bindSce
|
|
|
3
3
|
import { i as setLayoutEngine, n as getLayoutEngine, r as requireLayoutEngine, t as LayoutEngineMissingError } from "./layoutEngine.js";
|
|
4
4
|
import { n as TextCursor, r as textCursor, t as typewriter } from "./typewriter.js";
|
|
5
5
|
import { i as echo, n as motionBlur, r as Echo, t as MotionBlur } from "./motionBlur.js";
|
|
6
|
+
import { densifyStops } from "./gradient.js";
|
|
6
7
|
import { n as each, t as EachError } from "./each.js";
|
|
7
|
-
import { emitDevWarning, key,
|
|
8
|
+
import { emitDevWarning, key, oklabToRgba, parseColor, rgbaToOklab, signal, stagger, track } from "@glissade/core";
|
|
8
9
|
//#region src/taxonomy.ts
|
|
9
10
|
/**
|
|
10
11
|
* The CLOSED node taxonomy (DESIGN.md §3.1): exactly nine built-in node TYPES.
|
|
@@ -323,38 +324,6 @@ function trackMatte(content, matte, props = {}) {
|
|
|
323
324
|
matte
|
|
324
325
|
});
|
|
325
326
|
}
|
|
326
|
-
const smoothstep = (u) => u * u * (3 - 2 * u);
|
|
327
|
-
const GAUSS_K = 2.4;
|
|
328
|
-
const GAUSS_NORM = 1 - Math.exp(-5.76 / 2);
|
|
329
|
-
const gaussianEase = (u) => (1 - Math.exp(-((u * GAUSS_K) ** 2) / 2)) / GAUSS_NORM;
|
|
330
|
-
/**
|
|
331
|
-
* Densify `stops` into a `smooth`/`gaussian` oklab ramp. The output spans the
|
|
332
|
-
* input's offset range with GRADIENT_RAMP_STEPS uniformly-spaced stops; each
|
|
333
|
-
* point eases its blend within the authored segment it falls in. Returns the
|
|
334
|
-
* input unchanged for `linear` (or a single stop) — the canvas-native path.
|
|
335
|
-
*/
|
|
336
|
-
function densifyStops(stops, mode) {
|
|
337
|
-
if (mode === "linear" || stops.length < 2) return stops;
|
|
338
|
-
const ease = mode === "gaussian" ? gaussianEase : smoothstep;
|
|
339
|
-
const o0 = stops[0].offset;
|
|
340
|
-
const span = stops[stops.length - 1].offset - o0;
|
|
341
|
-
if (span <= 0) return stops;
|
|
342
|
-
const out = [];
|
|
343
|
-
let seg = 0;
|
|
344
|
-
for (let i = 0; i < 64; i++) {
|
|
345
|
-
const offset = o0 + span * (i / 63);
|
|
346
|
-
while (seg < stops.length - 2 && offset > stops[seg + 1].offset) seg++;
|
|
347
|
-
const a = stops[seg];
|
|
348
|
-
const b = stops[seg + 1];
|
|
349
|
-
const w = b.offset - a.offset;
|
|
350
|
-
const u = w > 0 ? Math.min(1, Math.max(0, (offset - a.offset) / w)) : 0;
|
|
351
|
-
out.push({
|
|
352
|
-
offset,
|
|
353
|
-
color: lerpColor(a.color, b.color, ease(u))
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
return out;
|
|
357
|
-
}
|
|
358
327
|
//#endregion
|
|
359
328
|
//#region src/meshGradient.ts
|
|
360
329
|
/**
|
package/dist/type.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { K as TextMeasurer, a as Group, c as LineBox, h as TextProps, i as GraphemeBox, m as Text, v as WordBox } from "./nodes.js";
|
|
2
|
-
import { o as TextCursor, t as EditMark } from "./typewriter.js";
|
|
2
|
+
import { o as TextCursor, s as TextCursorProps, t as EditMark } from "./typewriter.js";
|
|
3
3
|
import { EaseSpec, Track } from "@glissade/core";
|
|
4
4
|
|
|
5
5
|
//#region src/type.d.ts
|
|
@@ -139,6 +139,20 @@ interface TypeOnOpts {
|
|
|
139
139
|
cursorWidth?: number;
|
|
140
140
|
/** Caret blink period seconds when `cursor: true` (passthrough to textCursor). */
|
|
141
141
|
blinkPeriod?: number;
|
|
142
|
+
/**
|
|
143
|
+
* Caret COLOR when `cursor: true` (passthrough to the textCursor sibling's `fill`).
|
|
144
|
+
* Default '' = follow the Text's own fill; set a hex/PropInit for a deliberately
|
|
145
|
+
* contrasting caret (bindable via the `<id>/cursor/fill` track). Ignored without `cursor`.
|
|
146
|
+
*/
|
|
147
|
+
cursorFill?: TextCursorProps['fill'];
|
|
148
|
+
/**
|
|
149
|
+
* Escape hatch: any other {@link TextCursor} construction prop (e.g. `blinkPeriod`,
|
|
150
|
+
* `width`, or a NodeProp) forwarded to the caret sibling when `cursor: true`. The
|
|
151
|
+
* explicit `cursorWidth`/`blinkPeriod`/`cursorFill` options win over the matching
|
|
152
|
+
* key here, and the caret's `id` (`<id>/cursor`) is always set by typeOn. Ignored
|
|
153
|
+
* without `cursor`.
|
|
154
|
+
*/
|
|
155
|
+
cursorProps?: Omit<TextCursorProps, 'text' | 'id'>;
|
|
142
156
|
}
|
|
143
157
|
interface TypeOnResult {
|
|
144
158
|
/** The Text to draw. In the DEFAULT (string-track) mode its `text` is driven by
|
package/dist/type.js
CHANGED
|
@@ -252,9 +252,11 @@ function typeOn(source, opts = {}) {
|
|
|
252
252
|
duration: tw.duration
|
|
253
253
|
};
|
|
254
254
|
if (opts.cursor) result.cursor = textCursor(node, {
|
|
255
|
+
...opts.cursorProps ?? {},
|
|
255
256
|
id: `${id}/cursor`,
|
|
256
257
|
...opts.cursorWidth !== void 0 ? { width: opts.cursorWidth } : {},
|
|
257
|
-
...opts.blinkPeriod !== void 0 ? { blinkPeriod: opts.blinkPeriod } : {}
|
|
258
|
+
...opts.blinkPeriod !== void 0 ? { blinkPeriod: opts.blinkPeriod } : {},
|
|
259
|
+
...opts.cursorFill !== void 0 ? { fill: opts.cursorFill } : {}
|
|
258
260
|
});
|
|
259
261
|
return result;
|
|
260
262
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glissade/scene",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.58.0-pre.0",
|
|
4
4
|
"description": "glissade scene graph: nodes, transforms, DisplayList emission. Renderer-agnostic; zero DOM/Node dependencies.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"engines": {
|
|
@@ -63,6 +63,10 @@
|
|
|
63
63
|
"types": "./dist/motion.d.ts",
|
|
64
64
|
"default": "./dist/motion.js"
|
|
65
65
|
},
|
|
66
|
+
"./gradient": {
|
|
67
|
+
"types": "./dist/gradient.d.ts",
|
|
68
|
+
"default": "./dist/gradient.js"
|
|
69
|
+
},
|
|
66
70
|
"./identity": {
|
|
67
71
|
"types": "./dist/identity.d.ts",
|
|
68
72
|
"default": "./dist/identity.js"
|
|
@@ -77,7 +81,7 @@
|
|
|
77
81
|
],
|
|
78
82
|
"dependencies": {
|
|
79
83
|
"yoga-layout": "^3.2.1",
|
|
80
|
-
"@glissade/core": "0.
|
|
84
|
+
"@glissade/core": "0.58.0-pre.0"
|
|
81
85
|
},
|
|
82
86
|
"repository": {
|
|
83
87
|
"type": "git",
|