Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
| [`@vosjs/core`](./packages/core) | [![npm](https://img.shields.io/npm/v/%40vosjs%2Fcore)](https://www.npmjs.com/package/@vosjs/core) | The engine: config compiler, validation schema (Zod), runtime template generator, addon registry, and types. |
| [`@vosjs/elements`](./packages/elements) | [![npm](https://img.shields.io/npm/v/%40vosjs%2Felements)](https://www.npmjs.com/package/@vosjs/elements) | The element system: text / image / SVG / video / audio renderers for Three.js overlays, shipped as a typed ESM factory **and** an injectable IIFE bundle. |
| [`@vosjs/timeline`](./packages/timeline) | [![npm](https://img.shields.io/npm/v/%40vosjs%2Ftimeline)](https://www.npmjs.com/package/@vosjs/timeline) | Deterministic timeline math for video editing: keyframe sampling, GSAP-compatible pure easings, source-time remapping (trim/split). |
| [`@vosjs/tween`](./packages/tween) | [![npm](https://img.shields.io/npm/v/%40vosjs%2Ftween)](https://www.npmjs.com/package/@vosjs/tween) | Records a GSAP-dialect timeline into a per-element tween IR (extract / edit / deterministically sample), delegating 1:1 to a real backend for live playback. |
| [`@vosjs/editor`](./packages/editor) | [![npm](https://img.shields.io/npm/v/%40vosjs%2Feditor)](https://www.npmjs.com/package/@vosjs/editor) | Headless video-editor infrastructure: patch-based document store (undo/redo), live-edit classifier, editor bridge client, timeline view-model math. |
| [`@vosjs/cli`](./packages/cli) | [![npm](https://img.shields.io/npm/v/%40vosjs%2Fcli)](https://www.npmjs.com/package/@vosjs/cli) | Command line: render deterministic videos and stills from vos configs, headlessly — for your terminal, CI, or an AI agent. |

> `three` and `gsap` are **optional peer dependencies** — you bring your own versions, and the engine never bundles them.

Expand All @@ -34,7 +36,7 @@ import { compileVosConfig, vosConfigJsonSchema } from '@vosjs/core'
const config = {
version: 2,
scene: { background: '#000' },
camera: { type: 'perspective', position: [0, 0, 5] },
camera: { preset: 'perspective', position: [0, 0, 5] },
// functions are authored as strings, compiled into executable code
createContent: '(ctx) => { /* build your Three.js scene with ctx.THREE */ }',
}
Expand All @@ -56,6 +58,7 @@ The compiled template is an HTML/JS document you can render in an iframe, captur
| `@vosjs/core/schema` | Zod schemas, validators, config migrations |
| `@vosjs/core/addons` | Three.js addon / post-processing registry |
| `@vosjs/core/extract` | Config extraction from LLM/text output |
| `@vosjs/core/lint` | Determinism + GSAP-dialect linters for configs |
| `@vosjs/core/types` | Pure type definitions |

## Development
Expand All @@ -76,7 +79,7 @@ Releases are managed with [Changesets](https://github.com/changesets/changesets)

- **Plugin SDK** (`@vosjs/plugin-sdk`) — a unified `definePlugin()` contract so addons, element renderers, schema extensions, and codegen hooks can be contributed by third-party packages.
- **Browser adapter** (`@vosjs/web`) — a Vite-friendly dynamic addon loader whose import map is plugin-contributed.
- **CLI & scaffolding** (`@vosjs/cli`, `create-vos`).
- **Scaffolding** (`create-vos`) — one-command project starters on top of [`@vosjs/cli`](./packages/cli).

## License

Expand Down
16 changes: 15 additions & 1 deletion packages/core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,20 @@ vosConfigJsonSchema.parse(config) // validate
const template = compileVosConfig(config) // → runnable template string
```

The compiled template is an HTML/JS document you can render in an iframe, capture to video, or snapshot to an image.
The compiled template is a single HTML/JS document. One template powers all three modes — `generateRenderTemplate({ mode })` builds it for `playback` (interactive iframe), `capture-video` (frame-by-frame WebCodecs encode), or `capture-thumbnail` (single-frame snapshot) — so what you preview is exactly what you export.

## Determinism & linting

The engine owns a single master clock and every render is a pure function of time, so the same config produces the same frames anywhere. `@vosjs/core/lint` guards that contract before you render:

```ts
import { lintVosConfig, hasDeterminismErrors } from '@vosjs/core/lint'

const issues = lintVosConfig(config)
if (hasDeterminismErrors(issues)) throw new Error('non-deterministic config')
```

`lintVosConfig` flags non-deterministic patterns (`Date.now()`, `Math.random()`, wall-clock reads), and `lintVosDialect` checks the GSAP authoring dialect.

## Subpath exports

Expand All @@ -49,6 +62,7 @@ The compiled template is an HTML/JS document you can render in an iframe, captur
| `@vosjs/core/schema` | Zod schemas, validators, config migrations |
| `@vosjs/core/addons` | Three.js addon / post-processing registry |
| `@vosjs/core/extract` | Config extraction from LLM/text output |
| `@vosjs/core/lint` | Determinism + GSAP-dialect linters for configs |
| `@vosjs/core/types` | Pure type definitions |

## License
Expand Down
41 changes: 41 additions & 0 deletions packages/editor/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# @vosjs/editor

> Headless editing infrastructure for vos compositions — a patch-based document store, the live-edit classifier, the editor-mode playback bridge, element-edit commit helpers, and timeline view-model math.

[![npm](https://img.shields.io/npm/v/@vosjs/editor.svg)](https://www.npmjs.com/package/@vosjs/editor)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/vosjs/vos/blob/main/LICENSE)

Part of [vos](https://github.com/vosjs/vos), the open visual operating system behind [vosso](https://vos.so). These are the shared mechanisms every vos editor needs, with **zero UI opinion**. Apps own their document schemas, lowerings, and all rendering; this package owns only the mechanics. Pairs with [`@vosjs/timeline`](../timeline) for the underlying time math and with the `@vosjs/core` playback bridge.

## Install

```bash
pnpm add @vosjs/editor
```

## What it gives you

- **`createProjectStore`** — a patch-based document store (Immer) with undo/redo, drag coalescing, and a forward patch log. The app's document is the source of truth; lowered compositions are derived from it.
- **`classifyEdit`** — the live-edit tier classifier that keeps editing fast: a program-string change → warm `LOAD`, a data change → `SET_DATA`, a duration change → `SET_DURATION` (with `LOAD` fallback). Program-string equality is the structural hash.
- **`createEditorBridgeClient`** — the host-side client for the engine's editor-mode playback bridge: element hit-testing, bounds, and ephemeral property overrides for drag previews.
- **Element-edit commit helpers** — turn on-canvas drags into durable, undoable config patches (`nudgeElementRecipe`, `scaleElementRecipe`, `rotateElementRecipe`, `cssDeltaToDesign`, …).
- **Timeline view-model math** — px↔time mapping (`toPx`/`toTime`), ruler ticks, magnetic snapping, plus the `LaneAdapter` contract so apps can define their own timeline lanes.

## Example

```ts
import { createProjectStore, classifyEdit } from '@vosjs/editor'

const store = createProjectStore({ doc: initialDoc })

store.apply((draft) => {
draft.duration = 12
})

// decide how the running player should apply the change — no full reload for a data edit
const command = classifyEdit(prevLowered, nextLowered)
```

## License

[MIT](https://github.com/vosjs/vos/blob/main/LICENSE) © vosso
10 changes: 10 additions & 0 deletions packages/elements/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@ Part of [vos](https://github.com/vosjs/vos), the open visual operating system be
pnpm add @vosjs/elements three
```

## Element types

| Type | Renders as |
| --- | --- |
| `text` | A text mesh, with optional per-character `split` for staggered animation |
| `image` | An image plane (`src` loaded through the shared asset cache) |
| `svg` | A rasterized SVG plane |
| `video` | A video plane driven by the master clock |
| `audio` | A non-visual audio element, synced to the master clock (no mesh) |

## Two entry points

### `@vosjs/elements` — typed ESM factory
Expand Down
43 changes: 43 additions & 0 deletions packages/timeline/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# @vosjs/timeline

> Deterministic time math for editable vos compositions — keyframe sampling, GSAP-compatible pure easings, and source-time remapping (trim / split / speed).

[![npm](https://img.shields.io/npm/v/@vosjs/timeline.svg)](https://www.npmjs.com/package/@vosjs/timeline)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/vosjs/vos/blob/main/LICENSE)

Part of [vos](https://github.com/vosjs/vos), the open visual operating system behind [vosso](https://vos.so). This is a pure evaluation **library**, not a document format: apps embed its value types (keyframes, segments, speed spans) inside their own project documents and evaluate them with the same functions on both sides of the player bridge. No DOM, no engine coupling, no RNG or wall-clock — every function is a pure function of its arguments, so `seek(t)` renders identically on the host and inside a running program.

## Install

```bash
pnpm add @vosjs/timeline
```

## What it does

- **Keyframe sampling** — `sample()` interpolates a `KeyframeTrack` at any time with a resolved easing; `lerpArray` and `sortKeyframes` are the primitives underneath.
- **GSAP-compatible easings** — `EASINGS` / `resolveEase()` provide pure easing functions matching GSAP's names (including `css-bezier(…)` dialect eases), so a recorded animation samples the same curve the author saw.
- **Source-time remapping** — `mapTime`, `sourceToTimeline`, `totalDuration`, `rateAt`, `segmentRate`, and `splitBySpeed` remap between output time and source (footage) time across trims and speed changes. Editors keep spans anchored in source; the remap projects them into output.
- **Segment edits** — `trimSegment`, `splitSegments`, `removeSegment`, `normalizeSegments` operate on segment lists with a `MIN_SEGMENT_LENGTH` floor.

## Two evaluation contexts

The same math runs host-side (import from `@vosjs/timeline`) and inside a compiled program (inline the runtime string from `@vosjs/timeline/bundle`), so a timeline you edit in an app evaluates bit-identically when the program plays back.

```ts
// host
import { sample, mapTime, resolveEase } from '@vosjs/timeline'

const value = sample(track, t, resolveEase)
const sourceTime = mapTime(segments, outputTime)
```

```ts
// inside a program template
import { timelineRuntimeCode } from '@vosjs/timeline/bundle'
// inline timelineRuntimeCode into the render template; it exposes the same functions
```

## License

[MIT](https://github.com/vosjs/vos/blob/main/LICENSE) © vosso
44 changes: 44 additions & 0 deletions packages/tween/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# @vosjs/tween

> Record a GSAP-dialect timeline into a structured, per-element tween IR — a recording facade that delegates 1:1 to a real tween backend while capturing the animation as data you can extract, edit, and deterministically sample.

[![npm](https://img.shields.io/npm/v/@vosjs/tween.svg)](https://www.npmjs.com/package/@vosjs/tween)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/vosjs/vos/blob/main/LICENSE)

Part of [vos](https://github.com/vosjs/vos), the open visual operating system behind [vosso](https://vos.so). vos configs author animation as GSAP-dialect `createTimeline` functions. This package lets that same authoring surface become **data**: the recorder is shaped like the slice of `gsap` those functions use, captures every tween as a `TweenSpec` (with GSAP position parameters resolved to absolute time), and — given a real `gsap` backend — delegates 1:1 so live playback is unchanged.

## Install

```bash
pnpm add @vosjs/tween
```

## The pieces

- **Recorder** (`createTweenRecorder`, `RecordingTimeline`) — a `gsap`-shaped facade that records tweens as `TweenSpec`s. Pass a real `gsap` backend to delegate playback 1:1, or none to record only.
- **Extraction** (`extractTimeline`, `buildTracks`) — fold the recorded specs into per-target keyframe tracks (`TargetTrack` / `TimelineDoc`): the neutral model a per-element timeline editor edits.
- **Deterministic sampler** (`createSampler`) — evaluate a recorded timeline with no GSAP present. `seek(t)` becomes a pure function, which is what makes server rendering and frame-accurate export reproducible.
- **Spec player** (`createSpecPlayer`, `contextResolver`) — play a `TweenSpec[]` that lives in a document's data, resolving targets against a live context each frame (the timeline-as-data path).
- **Helpers** — `staggerOffsets`, `parseVars`, target tagging (`tagTarget`/`readTag`), and extraction-scope stubs (`makeElement`, `runCreateTimeline`, …).

## Example

```ts
import gsap from 'gsap'
import { createTweenRecorder, extractTimeline, createSampler } from '@vosjs/tween'

// record a config's createTimeline against the facade (delegating to real gsap)
const recorder = createTweenRecorder({ backend: gsap })
createTimeline(ctx, content, duration) // uses recorder as ctx.gsap

// fold into per-element tracks, then sample deterministically — no gsap needed
const doc = extractTimeline(recorder.specs)
const sampler = createSampler(doc)
const frame = sampler.seek(1.5)
```

A subpath `@vosjs/tween/bundle` provides the sampler/spec-player runtime as an inlinable string for injection into a compiled program template.

## License

[MIT](https://github.com/vosjs/vos/blob/main/LICENSE) © vosso
Loading