@vosjs/cli 0.53.4 → 0.53.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vosjs/cli",
3
- "version": "0.53.4",
3
+ "version": "0.53.5",
4
4
  "description": "The vos CLI: record the real product from a scripted browser flow, auto-zoom from the cursor track, cut as data in doc.json, render deterministic video and stills, deliver a release's media per destination spec, and sync with vos.so. One binary, every verb, MIT.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -49,10 +49,10 @@
49
49
  "dependencies": {
50
50
  "mediabunny": "^1.55.7",
51
51
  "playwright": "^1.49.0",
52
- "@vosjs/core": "^0.25.3",
53
52
  "@vosjs/editor": "^1.4.0",
54
53
  "@vosjs/elements": "^0.9.0",
55
54
  "@vosjs/render-core": "^0.3.9",
55
+ "@vosjs/core": "^0.25.3",
56
56
  "@vosjs/shared": "^0.5.0",
57
57
  "@vosjs/studio-core": "^0.33.1",
58
58
  "@vosjs/timeline": "^0.4.1",
package/skills/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.1
1
+ 0.10.0
@@ -43,10 +43,15 @@ not in `node_modules`.
43
43
  `font.family` and `font.color` take `{ "$data": "<key>" }` (they
44
44
  re-raster live on a data edit). Logos and shapes are `svg` or `image`
45
45
  elements, footage a `video` element. Elements are what the studio selects
46
- and moves.
46
+ and moves. **Every visible word is a bound element**, whatever animates
47
+ it: a word whose letters rise one by one is ONE `split` element bound to
48
+ its key, never a pool of per-letter elements filled from `onFrame` (a
49
+ person can retype the first in the studio and not the second).
47
50
  4. **Motion is the timeline.** `createTimeline` holds the tweens, on
48
51
  `ctx.elements.get(id).props` (whole) or `.segments` (`split: { type:
49
- 'chars' | 'words' | 'lines' }` units), in the GSAP dialect. Keep curves
52
+ 'chars' | 'words' | 'lines' }` units), in the GSAP dialect. Read
53
+ `el.segments` inside `createTimeline` and nowhere else: a data edit to a
54
+ bound split word rebuilds its units and the timeline over them. Keep curves
50
55
  exact: Remotion's `Easing.bezier(a, b, c, d)` is `ease: 'css-bezier(a, b,
51
56
  c, d)'`; GSAP eases keep their names.
52
57
  5. **Scenes are labels.** One `tl.addLabel('<scene>', t)` per scene or
@@ -185,7 +190,7 @@ stated approximation:
185
190
 
186
191
  | Source | In vos today |
187
192
  | --- | --- |
188
- | `overflow: hidden` masks, `clip-path` reveals | no element masks: approximate with opacity, or paint the item |
193
+ | `overflow: hidden` masks, `clip-path` reveals | no element masks: approximate a masked WORD with opacity (it stays a bound element); paint only a shape |
189
194
  | a colour per split unit (`charStyle` making one letter red) | segments carry x/y/opacity/scale/rotation only: a separate element, or paint it |
190
195
  | `mixBlendMode` | no blend modes on elements: paint it |
191
196
  | a shape's colour as a knob | an svg's colours are compiled in (static `colors`): paint the shape if its colour must change live |
@@ -1,4 +1,4 @@
1
- <!-- Generated by scripts/build-element-reference.mjs from @vosjs/core 0.25.2, @vosjs/elements 0.8.3 and @vosjs/timeline 0.4.1. Do not edit by hand: re-run the script. -->
1
+ <!-- Generated by scripts/build-element-reference.mjs from @vosjs/core 0.25.3, @vosjs/elements 0.9.0, @vosjs/timeline 0.4.1 and @vosjs/shared 0.5.0. Do not edit by hand: re-run the script. -->
2
2
 
3
3
  # Elements, the context and eases: the declarations
4
4
 
@@ -117,7 +117,16 @@ interface VosConfigJson {
117
117
 
118
118
  `content`, `font.family` and `font.color` of a text element are the three
119
119
  fields that take a `{ "$data": "<key>" }` binding, and the only ones that
120
- re-resolve on a data edit; every other field is read once at build.
120
+ re-resolve on a data edit; every other field is read once at build. The key
121
+ names a TOP-LEVEL key of `config.data` (no dotted path, no array index), so
122
+ a list of words that each need binding is one key per word; `content`
123
+ takes the value as a string. A bound `split` element follows a data edit
124
+ too: its units are rebuilt from the new words and the timeline is rebuilt
125
+ over them (`@vosjs/elements` 0.9.0 with core 0.25.3; before that the
126
+ studio reloaded the program for such a knob and other hosts kept the old
127
+ word). So a per-letter word that is a knob is ONE bound `split` element,
128
+ never a pool of per-letter elements written from `onFrame`: a person can
129
+ retype a bound element in the studio, and cannot retype a pool.
121
130
  `font.size`, `letterSpacing`, `transform.translateX/Y`, `stroke.width`
122
131
  and `shadow.blur` are design pixels (a 1080-high frame). There is no
123
132
  `mask`, `clip`, `blend` or group field on any element: SKILL.md's
@@ -318,9 +327,14 @@ The tween dialect animates numbers only: tween `fontSize` and
318
327
 
319
328
  Every such write queues a re-raster, even of an unchanged value, so guard
320
329
  a per-frame write: `if (el.props.content !== next) el.props.content = next`.
321
- A `split` text element does not re-raster at all: these writes are ignored
322
- on it, so text that changes and text that animates per letter are two
323
- elements.
330
+ These writes do nothing on a `split` element (its units are structure):
331
+ change a split element's words through its binding, never its props.
332
+
333
+ A text raster never fails for being long: its density drops until the
334
+ longest side fits the GPU's largest texture (4096 px when the GPU does
335
+ not say), so a line past about 4096 design px at 1080p, or half that at
336
+ 2160p, renders softer. Only then is a long marquee worth cutting into
337
+ elements, and each piece stays bound.
324
338
 
325
339
  ```ts
326
340
  /**
@@ -381,9 +395,14 @@ interface ElementInstance {
381
395
  props: ElementProps;
382
396
  /**
383
397
  * Split text segments (only available when split config is defined).
384
- * Each segment has its own ElementProps for individual animation.
398
+ * Each segment has its own ElementProps for individual animation. A data
399
+ * edit to a BOUND split text rebuilds them from the new words: the array
400
+ * and its objects are replaced (and the host rebuilds the timeline), so
401
+ * read `el.segments` inside createTimeline, never cache it elsewhere.
385
402
  */
386
403
  segments?: ElementProps[];
404
+ /** Set when a data edit rebuilt this element's units; the host clears it. */
405
+ structural?: boolean;
387
406
  /** Update element content (text or image src) */
388
407
  setContent: (content: string) => void;
389
408
  /**
@@ -409,6 +428,83 @@ interface ElementInstance {
409
428
  }
410
429
  ```
411
430
 
431
+ ## Knobs (`config.params` and `config.presets`)
432
+
433
+ A knob is a `ParamSpec` over one top-level `data` key, and a Look a named
434
+ set of values. vos.so keeps at most 12 knobs and 8 Looks, the first valid
435
+ ones, and `vos check` names every one it would drop before a push. Every
436
+ bound word stays a `data` key whether or not it has a knob: the studio's
437
+ element panel retypes a bound element directly, so the 12 knobs go to what
438
+ a person reaches for first (the palette, the headline), not to every word.
439
+ A `text` knob with `multiline: true` suits a list a painter draws line by
440
+ line; a list of elements is one key per element.
441
+
442
+ ```ts
443
+ /**
444
+ * Config params: `config.params`
445
+ * declares the `ctx.data` keys a program reads as its creative knobs — key,
446
+ * kind, range, default. THE one params module, shared by the web Remix
447
+ * panel, the API, and scripts (the knob honesty lint): edits commit by
448
+ * baking BOTH `params[i].default` and `data[key]` into the config, so
449
+ * saves/exports/server renders pick the values up through the existing
450
+ * `config.data` machinery with zero new plumbing.
451
+ *
452
+ * The engine schema does not know `params` yet (upstream addition pending) —
453
+ * `vosConfigJsonSchema` STRIPS unknown fields on parse, so the API re-attaches
454
+ * validated params at the storage boundary (the platform's server-side copy;
455
+ * change both together) and
456
+ * this module validates defensively.
457
+ */
458
+ type ParamValue = number | string | boolean;
459
+
460
+ interface ParamSpec {
461
+ /** The ctx.data key the program reads. */
462
+ key: string;
463
+ /** Human label; falls back to the key. */
464
+ label?: string;
465
+ /** One sentence on what the knob changes (U3b — knobs carry meaning). */
466
+ hint?: string;
467
+ /** Unit shown inside the number field: px, %, s, ×, °. */
468
+ unit?: string;
469
+ /** Optional card grouping; ungrouped knobs land on the Remix card. */
470
+ group?: string;
471
+ /** Sort order within a group (falls back to declaration order). */
472
+ order?: number;
473
+ kind: 'number' | 'color' | 'select' | 'toggle' | 'text' | 'font';
474
+ /** number kind */
475
+ min?: number;
476
+ max?: number;
477
+ step?: number;
478
+ /**
479
+ * select kind: the enumerated choices (REQUIRED, ≥2). font kind: an
480
+ * OPTIONAL curation — the families the knob offers; absent = the whole
481
+ * hosted catalog. Faces travel with the value: `applyParamValue` writes
482
+ * the chosen family's hosted faces into `data.fonts`, which the engine
483
+ * (core ≥0.17) registers at boot and on SET_DATA — no `config.fonts`
484
+ * declaration needed, no recompile.
485
+ */
486
+ options?: string[];
487
+ /** text kind: render a multiline editor (content knobs, e.g. a headline). */
488
+ multiline?: boolean;
489
+ default: ParamValue;
490
+ }
491
+
492
+ /**
493
+ * A Look (U3b): a named set of param values — the feel-the-range layer.
494
+ * Tap a look, then fine-tune; applying is ONE undoable multi-value commit.
495
+ */
496
+ interface LookPreset {
497
+ name: string;
498
+ values: Record<string, ParamValue>;
499
+ }
500
+
501
+ /**
502
+ * Text params carry URLs (modelUrl knobs) and bound content
503
+ * (headline knobs) — longer than other string kinds.
504
+ */
505
+ const TEXT_PARAM_MAX = 280;
506
+ ```
507
+
412
508
  ## The context (`ctx`)
413
509
 
414
510
  `setup(ctx)` gets a `SetupContext` and may return assets;
@@ -24,7 +24,7 @@ units (render pixels, y down, degrees counter-clockwise).
24
24
  | a CSS `cubic-bezier(a, b, c, d)` timing | `ease: 'css-bezier(a, b, c, d)'` (exact; spelled `cubic-bezier` it plays linear) |
25
25
  | CSS `--chrome` set by the timeline | a `data` value read in `onFrame`, or a tween on the element that shows it |
26
26
  | faces resolved by the runtime from CSS families | `fonts: [{ family, weight, url }]` from the catalog |
27
- | `mix-blend-mode`, `clip-path`, `overflow: hidden` reveals | GAPS: the painter, or an opacity approximation, said |
27
+ | `mix-blend-mode`, `clip-path`, `overflow: hidden` reveals | GAPS: a revealed word keeps its bound element with an opacity approximation; the painter only for a shape; said in the push note |
28
28
 
29
29
  Two traps specific to HyperFrames sources:
30
30