@vosjs/cli 0.29.1 → 0.30.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/README.md CHANGED
@@ -161,7 +161,7 @@ Verified the flow in agent-browser already? `vos actions from-agent-browser step
161
161
 
162
162
  **Image and video overlays.** Media kinds on the same lane: `{ "id": "m0", "kind": "image" | "video", "start": 2, "duration": 4, "key": "/logo.png", "width": 0.35, "radius": 12, "opacity": 1, "loop": false, "transform": { … } }`. `key` is a file inside the take directory (`"/logo.png"`) or a URL; `width` is a fraction of the frame width, height follows the media's aspect; corners in design px. Video time is clip-local and muted by design; soundtracks belong to `doc.audio`.
163
163
 
164
- **HTML layers.** A UI component authored as DOM on the same lane, sharp at any export size because it is rasterized from source, not magnified from the footage: `{ "id": "h0", "kind": "html", "start": 2, "duration": 4, "html": "<div class=\"card\">Open Code</div>", "css": ".card{font-family:'Inter';background:#0b0b0d;border-radius:16px;box-shadow:0 24px 60px rgba(0,0,0,.45)}", "box": { "width": 452, "height": 132 }, "transform": { … } }`. The markup is well-formed XML (`<br />`, `&amp;`, quoted attributes; `vos validate` refuses the rest in words, because a malformed layer decodes to nothing and says nothing). `box` is the design box in 1080p px; `width` defaults to the design size. The CSS is the chrome (shadow, radius, border; `bleed` is derived from the shadows, or stated), a `font-family` it names resolves against the hosted catalog at every `font-weight` it names (a face outside the catalog rides `fonts: [{ family, url }]`), an image inside must be a `data:` URI, and an `animation` runs on the wall clock rather than the timeline, so animate the layer with `anim` and `motion`. It is never re-hosted and never an upload.
164
+ **HTML layers.** A UI component authored as DOM on the same lane, sharp at any export size because it is rasterized from source, not magnified from the footage: `{ "id": "h0", "kind": "html", "start": 2, "duration": 4, "html": "<div class=\"card\">Open Code</div>", "css": ".card{font-family:'Inter';background:#0b0b0d;border-radius:16px;box-shadow:0 24px 60px rgba(0,0,0,.45)}", "box": { "width": 452, "height": 132 }, "transform": { … } }`. The markup is well-formed XML (`<br />`, `&amp;`, quoted attributes; `vos validate` refuses the rest in words, because a malformed layer decodes to nothing and says nothing). `box` is the design box in 1080p px; `width` defaults to the design size. The CSS is the chrome (shadow, radius, border; `bleed` is derived from the shadows, or stated), a `font-family` it names resolves against the hosted catalog at every `font-weight` it names (a face outside the catalog rides `fonts: [{ family, url }]`), and an image inside is inlined for you when its URL is on `https://assets.vos.so/` (`vos asset upload` puts it there; any other host paints blank, so inline it as a `data:` URI). A still layer's `animation` runs on the wall clock rather than the timeline, so animate the layer with `anim` and `motion`; a LIVE layer (`"live": true`) is re-rasterized per frame at clip-local time: its `@keyframes` are scrubbed to `t` (paused, delayed by `-t`; fold any `animation-delay` into the keyframes) and `{{t}}` / `{{data.<name>}}` placeholders in the markup and CSS fill from the clock and the clip's `data`, so a counter, a progress bar or a typed line come out on the timeline's clock in the preview and in every export chunk alike. It is never re-hosted and never an upload.
165
165
 
166
166
  **3D props.** `doc.objects`: world-space props between the card and the overlays. `{ "id": "p0", "asset": { "kind": "primitive", "shape": "knot", "color": "#ffb03a" }, "span": { "start": 1, "duration": 3 }, "transform3d": { "x": 0.8, "y": 0.28, "z": 0.5, "rx": 0, "ry": 40, "rz": 0, "scale": 0.18 }, "animation": "spin" }`. Shapes `cube`, `sphere`, `torus`, `knot`; `kind: "gltf"` with `key` loads a GLB (bounding-box normalized so `scale` means the same for every model; a bad model fails open). `x`/`y` are frame fractions, `z` world units toward the camera from the card plane, `scale` a fraction of the frame height; `animation` is `spin` or `float`, deterministic.
167
167
 
@@ -1143,6 +1143,20 @@ function lintDoc(docIn) {
1143
1143
  `${name}.width must be a fraction of the frame width in (0..1] (got ${String(o.width)}; absent = the design size)`
1144
1144
  );
1145
1145
  }
1146
+ if (o.live !== void 0 && typeof o.live !== "boolean") {
1147
+ problems.push(
1148
+ `${name}.live must be true or absent: a live layer is re-rasterized per frame at clip-local t (its @keyframes scrubbed, its {{t}} and {{data.\u2026}} filled)`
1149
+ );
1150
+ }
1151
+ if (o.data !== void 0) {
1152
+ const bad = !isObj(o.data) || Object.values(o.data).some(
1153
+ (v) => !["string", "number", "boolean"].includes(typeof v)
1154
+ );
1155
+ if (bad)
1156
+ problems.push(
1157
+ `${name}.data must be a map of strings, numbers or booleans: the values a live layer's {{data.<name>}} placeholders read`
1158
+ );
1159
+ }
1146
1160
  if (o.opacity !== void 0 && (!isNum(o.opacity) || o.opacity < 0 || o.opacity > 1)) {
1147
1161
  problems.push(`${name}.opacity must be 0..1`);
1148
1162
  }
@@ -10601,4 +10615,4 @@ export {
10601
10615
  convertAgentBrowser,
10602
10616
  run
10603
10617
  };
10604
- //# sourceMappingURL=chunk-LST5JGI5.js.map
10618
+ //# sourceMappingURL=chunk-N5CNC3B7.js.map