@vosjs/cli 0.65.0 → 0.65.1

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.65.0",
3
+ "version": "0.65.1",
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",
@@ -52,12 +52,12 @@
52
52
  "mediabunny": "^1.55.7",
53
53
  "playwright": "^1.49.0",
54
54
  "@vosjs/core": "^0.27.0",
55
- "@vosjs/editor": "^1.4.0",
56
55
  "@vosjs/elements": "^0.10.2",
56
+ "@vosjs/studio-core": "^0.35.3",
57
57
  "@vosjs/render-core": "^0.3.17",
58
- "@vosjs/shared": "^0.7.0",
58
+ "@vosjs/editor": "^1.4.0",
59
59
  "@vosjs/timeline": "^0.5.0",
60
- "@vosjs/studio-core": "^0.35.3",
60
+ "@vosjs/shared": "^0.7.0",
61
61
  "@vosjs/tween": "^0.8.3"
62
62
  },
63
63
  "devDependencies": {
package/skills/VERSION CHANGED
@@ -1 +1 @@
1
- 0.20.1
1
+ 0.21.0
@@ -159,6 +159,9 @@ documents a `ctx.data` key the program reads:
159
159
  ```
160
160
 
161
161
  - kinds: `number` (min/max/step) | `color` | `select` (options) | `toggle`
162
+ | `text` | `font` | `asset` (a FILE knob: its `key` is a name in
163
+ `config.assets`, it has no `default`, and the person swaps the declared
164
+ file from the editor; see the vos-remix skill's `params-knobs.md`)
162
165
  - `hint`: ONE sentence on what visibly changes — write it
163
166
  - the program reads it where it animates:
164
167
  `const d = ctx.data || {}; if (typeof d.hue === 'number') u.uHue.value = d.hue`
@@ -268,7 +268,7 @@ A file the program uses (a picture, a video, a model, a font file) is named in `
268
268
 
269
269
  **Never type a file's URL or path inside a function string.** It renders on your machine and then fails where it matters: a server render of a private vos cannot fetch it, and a remix does not bring it along. `vos check` reports a `"$assets.<name>"` that names nothing, a declared path that is not a file, and a hosted file typed in code.
270
270
 
271
- A file a knob swaps (a `modelUrl` text param) is the one exception: it lives in `data` as a URL, because a person changes it.
271
+ A file a person should be able to swap is still declared here, with a FILE KNOB over its name: `"params": [{ "key": "cover", "label": "Cover", "kind": "asset" }]` (`@vosjs/cli` 0.65 or later). The knob's value is the declared file's `ref`, so it has no `default` and nothing in `data`; `accept` lists the kinds it takes and defaults to the file's own `kind`. Older programs spell this as a text knob holding a URL in `data` (a `modelUrl` param); that still plays, but write new ones with a file knob.
272
272
 
273
273
  ---
274
274
 
@@ -1,4 +1,4 @@
1
- <!-- Generated by scripts/build-element-reference.mjs from @vosjs/core 0.25.5, @vosjs/elements 0.10.0, @vosjs/timeline 0.4.1 and @vosjs/shared 0.6.0. Do not edit by hand: re-run the script. -->
1
+ <!-- Generated by scripts/build-element-reference.mjs from @vosjs/core 0.27.0, @vosjs/elements 0.10.2, @vosjs/timeline 0.5.0 and @vosjs/shared 0.7.0. Do not edit by hand: re-run the script. -->
2
2
 
3
3
  # Elements, the context and eases: the declarations
4
4
 
@@ -46,6 +46,16 @@ interface VosConfigJson {
46
46
  * Total duration of one animation cycle in seconds.
47
47
  */
48
48
  duration: number;
49
+ /**
50
+ * The canvas the program is designed for, in pixels. Its ratio is the
51
+ * program's aspect (any shape: 1080x1920, 1080x1080, 2560x1080); its pixels
52
+ * are the default output size of a render or still. Absent, a host picks
53
+ * (16:9 by convention). Design units stay 1080-high at every size.
54
+ */
55
+ size?: {
56
+ width: number;
57
+ height: number;
58
+ };
49
59
  /** Scene configuration (background, fog) */
50
60
  scene?: SceneConfig;
51
61
  /** Camera configuration */
@@ -77,6 +87,25 @@ interface VosConfigJson {
77
87
  * @example { cursor: [{ t: 0, x: 10, y: 20, type: 'down' }] }
78
88
  */
79
89
  data?: Record<string, unknown>;
90
+ /**
91
+ * The files this program uses, declared by name: its manifest.
92
+ *
93
+ * A program reads `ctx.assets.<name>` and gets a URL (or an array of
94
+ * them) that the HOST resolved for the surface it is running on. An
95
+ * element, object or font may name one as the string `"$assets.<name>"`
96
+ * (or `"$assets.<name>[2]"`), which is replaced the same way.
97
+ *
98
+ * Declaring a file here instead of typing its URL inside a function is
99
+ * what lets a host see it: it can serve a private file to a render page,
100
+ * bring it along when the program is copied, and refuse to collect it
101
+ * while the program still plays.
102
+ *
103
+ * A `ref` is whatever the host understands: a URL or path is used as it
104
+ * is; any other scheme is mapped by the compile option `resolveAssetRef`
105
+ * and, per surface, by `deps.assets`.
106
+ * @example { logo: { ref: './logo.png', kind: 'image' } }
107
+ */
108
+ assets?: Record<string, AssetDecl>;
80
109
  /**
81
110
  * Async setup hook as a string.
82
111
  * @example "(ctx) => { const loader = new ctx.loaders.FontLoader(); ... }"
@@ -434,8 +463,13 @@ interface ElementProps {
434
463
  interface ElementInstance {
435
464
  /** Original configuration */
436
465
  config: ElementConfig;
437
- /** Three.js mesh (textured plane) */
466
+ /** Three.js mesh (textured plane); a split text's FIRST unit only */
438
467
  mesh: THREE.Mesh;
468
+ /**
469
+ * Every mesh the element draws (a split text's units), for picking and
470
+ * the editor's box. Absent on instances from @vosjs/elements < 0.10.1.
471
+ */
472
+ meshes?: () => THREE.Mesh[];
439
473
  /** DOM node for SplitText (text elements only) - typed as unknown for portability */
440
474
  node: unknown;
441
475
  /** GSAP-animatable properties */
@@ -477,7 +511,8 @@ interface ElementInstance {
477
511
 
478
512
  ## Knobs (`config.params` and `config.presets`)
479
513
 
480
- A knob is a `ParamSpec` over one top-level `data` key, and a Look a named
514
+ A knob is a `ParamSpec` over one top-level `data` key (a file knob, kind
515
+ `asset`, is over a name in `assets` instead), and a Look a named
481
516
  set of values. vos.so keeps at most 12 knobs and 8 Looks, the first valid
482
517
  ones, and `vos check` names every one it would drop before a push. Every
483
518
  bound word stays a `data` key whether or not it has a knob: the studio's
@@ -501,9 +536,22 @@ line; a list of elements is one key per element.
501
536
  * validated params at the storage boundary (the platform's server-side copy;
502
537
  * change both together) and
503
538
  * this module validates defensively.
539
+ *
540
+ * ONE kind is not a `ctx.data` key. An `asset` knob swaps a FILE, and a
541
+ * program's files live in `config.assets`, declared by name and read as
542
+ * `ctx.assets.<name>` or `"$assets.<name>"`. So an asset knob's `key` is a
543
+ * manifest name, its value is that entry's `ref`, and a commit writes the
544
+ * manifest, never `data`. That is what lets a swapped file get everything
545
+ * a declared file gets (a local path served by the CLI, uploaded by a push,
546
+ * resolved for every surface) instead of being a URL typed into data that
547
+ * nothing downstream knows is a file.
504
548
  */
505
549
  type ParamValue = number | string | boolean;
506
550
 
551
+ const ASSET_PARAM_KINDS: readonly ["image", "video", "audio", "model", "font", "hdr"];
552
+
553
+ type AssetParamKind = (typeof ASSET_PARAM_KINDS)[number];
554
+
507
555
  interface ParamSpec {
508
556
  /** The ctx.data key the program reads. */
509
557
  key: string;
@@ -517,7 +565,13 @@ interface ParamSpec {
517
565
  group?: string;
518
566
  /** Sort order within a group (falls back to declaration order). */
519
567
  order?: number;
520
- kind: 'number' | 'color' | 'select' | 'toggle' | 'text' | 'font';
568
+ kind: 'number' | 'color' | 'select' | 'toggle' | 'text' | 'font' | 'asset';
569
+ /**
570
+ * asset kind: the kinds of file the knob takes (a picker offers only
571
+ * these). Absent = the declared file's own `kind` hint, and when that is
572
+ * absent too, any file.
573
+ */
574
+ accept?: AssetParamKind[];
521
575
  /** number kind */
522
576
  min?: number;
523
577
  max?: number;
@@ -18,7 +18,9 @@ Reveal: https://vos.so/gallery?tag=3d) are built to take a model swap.
18
18
  POINT** in these programs — with the loaded `setupData.model`,
19
19
  bbox-normalized to ~1.7 units and grounded at `y = 0` (the templates
20
20
  ship the normalization snippet; keep it so `scale` knobs stay
21
- model-independent).
21
+ model-independent). To let the person swap the model later from the
22
+ editor, add a file knob over it (`params-knobs.md`, File knobs):
23
+ `{ "key": "product", "label": "Model", "kind": "asset" }`.
22
24
  - Or keep the template's own product and only retune params.
23
25
  3. **Never type the model's URL or path inside a function string.**
24
26
  `vos render` and `vos preview` serve the declared file to the page;
@@ -17,6 +17,7 @@ just an artifact.**
17
17
  ```
18
18
 
19
19
  - kinds: `number` (min/max/step) | `color` | `select` (options) | `toggle`
20
+ | `text` | `font` | `asset` (a file knob, below)
20
21
  - `hint`: ONE sentence on what visibly changes — always write it
21
22
  - `unit` shows inside the number field (`px` `%` `s` `×` `°`);
22
23
  `group`/`order` cluster related knobs into their own panel card
@@ -38,6 +39,41 @@ Values must reference declared param keys with matching types (anything
38
39
  else is dropped on save; max 8 Looks, names ≤24 chars). Ship 2–3 Looks
39
40
  whenever the program has 4+ params.
40
41
 
42
+ ## File knobs
43
+
44
+ A file a person should be able to swap (the logo, the product shot, the
45
+ model) is a knob of kind `asset` over a DECLARED file. Its `key` is the
46
+ file's name in `config.assets`; it has no `default` and nothing in `data`,
47
+ because its value is that file's `ref`. Needs `@vosjs/cli` 0.65 or later.
48
+
49
+ ```json
50
+ "assets": { "logo": { "ref": "./logo.png", "kind": "image" } },
51
+ "params": [{ "key": "logo", "label": "Logo", "kind": "asset",
52
+ "hint": "The mark in the corner" }]
53
+ ```
54
+
55
+ - The program reads it like any declared file: `ctx.assets.logo`, or
56
+ `"src": "$assets.logo"` on an element. No `onFrame` read is needed: a
57
+ swap recompiles the program once, it is never a live data edit.
58
+ - `accept` lists the kinds it takes (`image`, `video`, `audio`, `model`,
59
+ `font`, `hdr`), e.g. `"accept": ["image", "video"]`. Without it the knob
60
+ takes the declared file's own `kind`, so write `kind` on the file.
61
+ - One knob, one file: a name declared as a list cannot be a file knob.
62
+ - In the editor the person sees the file with a **Replace** control and
63
+ picks from their own files or their device. The swap rewrites the
64
+ manifest entry, so the new file is declared like the old one: `vos push`
65
+ uploads it, and a server render of a private vos can fetch it.
66
+ - To swap it yourself, change the file's `ref` in `assets` and push. A
67
+ Look can swap it too: `"values": { "logo": "asset:<id>" }`.
68
+ - `vos check` warns when a file knob would do nothing: the name is not
69
+ declared, it is a list, nothing reads `ctx.assets.<name>`, or no kind is
70
+ said anywhere.
71
+
72
+ A `text` knob holding a URL in `data` (a `modelUrl` param) is the older
73
+ spelling. It still plays, but the person gets a box to paste an address
74
+ into, and `vos push` does not upload a local file named there. Write new
75
+ programs with a file knob.
76
+
41
77
  ## The five rules
42
78
 
43
79
  1. **The knob budget is a negotiation, not an accumulation.** Curate 2–4