@glissade/scene 0.5.0-pre.3 → 0.5.0-pre.5

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/index.d.ts CHANGED
@@ -80,11 +80,25 @@ interface EditMark {
80
80
  /** the full visible string AFTER this keystroke */
81
81
  value: string;
82
82
  }
83
+ /** One edit step's phrase boundary — for driving sibling UI (a counter chip, a
84
+ * progress dot) off the same source instead of recomputing wall-clock spans. */
85
+ interface StepMark {
86
+ /** index of the step in the edit script */
87
+ index: number;
88
+ /** time this step began (before its first keystroke) */
89
+ start: number;
90
+ /** time this step completed (after its last keystroke and its hold) */
91
+ end: number;
92
+ /** the full visible string after this step */
93
+ value: string;
94
+ }
83
95
  interface TypewriterResult {
84
96
  /** hold-key string track for the Text node's `<id>/text` target */
85
97
  track: Track<string>;
86
98
  /** every keystroke (insert + delete), for keystroke SFX */
87
99
  marks: EditMark[];
100
+ /** one entry per edit step, with its start/end times — phrase boundaries */
101
+ steps: StepMark[];
88
102
  /** time of the last keystroke or hold — the performance's end */
89
103
  duration: number;
90
104
  }
@@ -133,7 +147,8 @@ declare function pointAtLength(path: PathValue, s: number): Vec2;
133
147
  interface FollowPathProps extends NodeProps {
134
148
  /** the node to move along the path; its position (and rotation, if orient) is owned by this */
135
149
  target: Node;
136
- path: PathValue;
150
+ /** a static PathValue, or a Path node followed LIVE (re-sampled as its `data` morphs) */
151
+ path: PathValue | Path;
137
152
  /** 0→1 position along the path's arc length; default 1 (the end). Track `<id>/progress`. */
138
153
  progress?: PropInit<number>;
139
154
  /** rotate the target to the path tangent — a cursor that points where it heads; default false */
@@ -154,7 +169,8 @@ declare class FollowPath extends Node {
154
169
  constructor(props: FollowPathProps);
155
170
  protected draw(): void;
156
171
  }
157
- /** `children: [route, cursor, followPath(cursor, route, { orient: true })]` — cursor traces the route. */
172
+ /** `children: [route, cursor, followPath(cursor, route, { orient: true })]` — cursor traces the route.
173
+ * Pass the Path *node* to follow it as it morphs; pass a PathValue for a fixed route. */
158
174
  declare function followPath(target: Node, path: PathValue | Path, props?: Omit<FollowPathProps, 'target' | 'path'>): FollowPath;
159
175
  //#endregion
160
176
  //#region src/tokenHighlight.d.ts
@@ -399,4 +415,4 @@ declare function bindScene(scene: Scene, doc: Timeline): BindingCacheEntry;
399
415
  */
400
416
  declare function evaluate(scene: Scene, doc: Timeline, t: number): DisplayList;
401
417
  //#endregion
402
- export { type AnchorSpec, type BindablePropTarget, type BlendMode, type CanvasLike, Circle, ColdAssetError, type Ctx2DLike, type DisplayList, type DisplayListBuilder, type DrawCommand, DuplicateNodeIdError, type EditMark, type EvalContext, type FilterSpec, FilterValidationError, FollowPath, type FollowPathProps, type FontSpec, Group, Highlight, type HighlightProps, type HitArea, IDENTITY, type ImageHandle, ImageNode, type ImageProps, type LayoutBox, type LayoutChildSpec, type LayoutContainerSpec, type LayoutEngine, LayoutEngineMissingError, type LineBox, type Mat2x3, Node, type NodeProps, type Paint, Path, type PathLike, type PathProps, type PathSampler, type PathSeg, type PropInit, Raster2D, type Raster2DHost, Rect, type Rect$1 as RectShape, type Resource, type ResourceId, type RevealMark, type Scene, type SceneInit, type SceneModule, type ShaderCaps, ShaderEffect, type ShaderEffectProps, type ShaderRef, type ShapeProps, type StrokeStyle, Text, TextCursor, type TextCursorProps, type TextMeasurer, type TextMetricsLite, type TextProps, TokenHighlight, type TokenHighlightProps, TokenMatchError, type TokenRange, type TypeEdit, type TypewriterResult, Video, type VideoFrameSource, type VideoProps, type WordBox, applyToPoint, bindScene, breakLines, createDisplayListBuilder, createScene, estimatingMeasurer, evaluate, filtersToCanvasFilter, followPath, fontString, fromTRS, getLayoutEngine, glow, highlight, invert, matEquals, matchTokenRun, motionPath, multiply, pathLength, pointAtLength, quantize, requireLayoutEngine, resolveAnchor, revealSchedule, roundedRectSegs, segmentGraphemes, segmentWords, setDefaultMeasurer, setLayoutEngine, textCursor, tokenHighlight, typewriter, validateFilters };
418
+ export { type AnchorSpec, type BindablePropTarget, type BlendMode, type CanvasLike, Circle, ColdAssetError, type Ctx2DLike, type DisplayList, type DisplayListBuilder, type DrawCommand, DuplicateNodeIdError, type EditMark, type EvalContext, type FilterSpec, FilterValidationError, FollowPath, type FollowPathProps, type FontSpec, Group, Highlight, type HighlightProps, type HitArea, IDENTITY, type ImageHandle, ImageNode, type ImageProps, type LayoutBox, type LayoutChildSpec, type LayoutContainerSpec, type LayoutEngine, LayoutEngineMissingError, type LineBox, type Mat2x3, Node, type NodeProps, type Paint, Path, type PathLike, type PathProps, type PathSampler, type PathSeg, type PropInit, Raster2D, type Raster2DHost, Rect, type Rect$1 as RectShape, type Resource, type ResourceId, type RevealMark, type Scene, type SceneInit, type SceneModule, type ShaderCaps, ShaderEffect, type ShaderEffectProps, type ShaderRef, type ShapeProps, type StepMark, type StrokeStyle, Text, TextCursor, type TextCursorProps, type TextMeasurer, type TextMetricsLite, type TextProps, TokenHighlight, type TokenHighlightProps, TokenMatchError, type TokenRange, type TypeEdit, type TypewriterResult, Video, type VideoFrameSource, type VideoProps, type WordBox, applyToPoint, bindScene, breakLines, createDisplayListBuilder, createScene, estimatingMeasurer, evaluate, filtersToCanvasFilter, followPath, fontString, fromTRS, getLayoutEngine, glow, highlight, invert, matEquals, matchTokenRun, motionPath, multiply, pathLength, pointAtLength, quantize, requireLayoutEngine, resolveAnchor, revealSchedule, roundedRectSegs, segmentGraphemes, segmentWords, setDefaultMeasurer, setLayoutEngine, textCursor, tokenHighlight, typewriter, validateFilters };
package/dist/index.js CHANGED
@@ -185,7 +185,10 @@ function typewriter(target, edits, opts = {}) {
185
185
  const shown = [];
186
186
  const keys = [key(start, "", { interp: "hold" })];
187
187
  const marks = [];
188
- for (const edit of edits) {
188
+ const steps = [];
189
+ for (let ei = 0; ei < edits.length; ei++) {
190
+ const edit = edits[ei];
191
+ const stepStart = t;
189
192
  const per = edit.perChar ?? globalPer;
190
193
  if (edit.type !== void 0) for (const g of segmentGraphemes(edit.type)) {
191
194
  t += per;
@@ -212,10 +215,17 @@ function typewriter(target, edits, opts = {}) {
212
215
  });
213
216
  }
214
217
  if (edit.hold !== void 0) t += edit.hold;
218
+ steps.push({
219
+ index: ei,
220
+ start: stepStart,
221
+ end: t,
222
+ value: shown.join("")
223
+ });
215
224
  }
216
225
  return {
217
226
  track: track(target, "string", keys),
218
227
  marks,
228
+ steps,
219
229
  duration: t
220
230
  };
221
231
  }
@@ -355,25 +365,36 @@ var FollowPath = class extends Node {
355
365
  if (typeof props.progress === "function") this.progress.bindSource(props.progress);
356
366
  else if (props.progress !== void 0) this.progress.set(props.progress);
357
367
  this.registerTarget("progress", this.progress);
358
- const sampler = motionPath(props.path, props.samplesPerSegment !== void 0 ? { samplesPerSegment: props.samplesPerSegment } : {});
359
- props.target.position.bindSource(() => sampler.atProgress(this.progress()));
368
+ const sOpts = props.samplesPerSegment !== void 0 ? { samplesPerSegment: props.samplesPerSegment } : {};
369
+ const getPath = props.path instanceof Path ? () => props.path.data() : () => props.path;
370
+ let cachedPath = getPath();
371
+ let cachedSampler = motionPath(cachedPath, sOpts);
372
+ const sampler = () => {
373
+ const pv = getPath();
374
+ if (pv !== cachedPath) {
375
+ cachedPath = pv;
376
+ cachedSampler = motionPath(pv, sOpts);
377
+ }
378
+ return cachedSampler;
379
+ };
380
+ props.target.position.bindSource(() => sampler().atProgress(this.progress()));
360
381
  if (props.orient) {
361
382
  const offset = props.orientOffset ?? 0;
362
383
  props.target.rotation.bindSource(() => {
363
- const t = sampler.tangentAtProgress(this.progress());
384
+ const t = sampler().tangentAtProgress(this.progress());
364
385
  return Math.atan2(t[1], t[0]) * 180 / Math.PI + offset;
365
386
  });
366
387
  }
367
388
  }
368
389
  draw() {}
369
390
  };
370
- /** `children: [route, cursor, followPath(cursor, route, { orient: true })]` — cursor traces the route. */
391
+ /** `children: [route, cursor, followPath(cursor, route, { orient: true })]` — cursor traces the route.
392
+ * Pass the Path *node* to follow it as it morphs; pass a PathValue for a fixed route. */
371
393
  function followPath(target, path, props = {}) {
372
- const pv = path instanceof Path ? path.data() : path;
373
394
  return new FollowPath({
374
395
  ...props,
375
396
  target,
376
- path: pv
397
+ path
377
398
  });
378
399
  }
379
400
  //#endregion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glissade/scene",
3
- "version": "0.5.0-pre.3",
3
+ "version": "0.5.0-pre.5",
4
4
  "description": "glissade scene graph: nodes, transforms, DisplayList emission. Renderer-agnostic; zero DOM/Node dependencies.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -20,7 +20,7 @@
20
20
  ],
21
21
  "dependencies": {
22
22
  "yoga-layout": "^3.2.1",
23
- "@glissade/core": "0.5.0-pre.3"
23
+ "@glissade/core": "0.5.0-pre.5"
24
24
  },
25
25
  "repository": {
26
26
  "type": "git",