@cutcraft/kit 0.1.0 → 0.2.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
@@ -1,16 +1,16 @@
1
- <p align="center"><img src="../../docs/public/logo.svg" width="64" alt="cutcut logo"></p>
1
+ <p align="center"><img src="https://raw.githubusercontent.com/prefix-tree/cutcraft/main/docs/public/logo.svg" width="64" alt="CutCraft"></p>
2
2
 
3
3
  # @cutcraft/kit
4
4
 
5
- The shared core of the cutcut editor: the JSX vocabulary a model writes, the
6
- resolver that turns a file into absolute placements, the invertible action
7
- system the editor dispatches, and the source tools that write those actions
8
- back into the file.
5
+ The core of [CutCraft](https://prefix-tree.github.io/cutcraft/): the elements a video file is written in, the resolver
6
+ that turns a file into exact placements, the actions an editor runs on it, and the tools that write those edits back
7
+ into the file's text. It has no DOM and runs anywhere.
9
8
 
10
- The design is in [`docs/spec.md`](docs/spec.md). The mapping to OpenReel's action
11
- set is in [`docs/parity.md`](docs/parity.md) (`pnpm parity` regenerates it).
9
+ ```sh
10
+ npm install @cutcraft/kit react zod
11
+ ```
12
12
 
13
- ## The file
13
+ ## A file
14
14
 
15
15
  ```tsx
16
16
  import { z } from "zod";
@@ -35,56 +35,40 @@ export default function Video({ title, accent }: z.infer<typeof schema>) {
35
35
  }
36
36
  ```
37
37
 
38
- Conventions the lint enforces: every element has a literal `id`; values a
39
- human may edit are literals or `schema` props; helpers are pure; a sequence
40
- track derives `start` from order (use `layout="free"` for absolute starts);
41
- `in`/`out` may reference the asset manifest (`word:N`, `shot:N.end`,
42
- `silence:N`, `marker:ID`).
38
+ `in` and `out` can point into the asset manifest (`word:N`, `shot:N.end`, `silence:N`, `marker:ID`), so a cut stays on
39
+ its word when the clip moves. Each timeline element has a literal `id`. A track is a magnetic sequence unless it says
40
+ `layout="free"`. A `<Layer>` holds any React you like.
43
41
 
44
- ## The pipeline
42
+ ## Using it
45
43
 
46
- ```
47
- file.tsx ──evaluate──▶ element tree ──collect──▶ CollectedTree ──resolve(manifest, patches)──▶ ResolvedState
48
- ▲ │
49
- └── fold(patch log) ◀── Executor.execute(action) ◀── timeline / inspector / preview gestures ◀──┘
50
- ```
44
+ ```ts
45
+ import { collectModule, resolve, Executor } from "@cutcraft/kit";
46
+ import { lint, foldToSource } from "@cutcraft/kit/source";
47
+ import * as file from "./video";
51
48
 
52
- - `collect(element)` walks the React element tree, expands pure helpers, and
53
- indexes every vocabulary element by id. `collectModule(mod)` does it for an
54
- imported file.
55
- - `resolve(tree, manifest, log?)` places everything: sequence cursors, gaps,
56
- transitions (overlap by their duration), anchors, `fill` and `match`
57
- durations, transcript references, multicam cuts. Errors are typed and
58
- attached to the element that caused them.
59
- - Cost: a resolve is linear in the number of elements, about 2 µs per node
60
- (1,000 nodes in ~2 ms). Parsed props are cached per raw props object and the
61
- overlay keeps every node a patch did not touch, so a drag step re-parses one
62
- element and re-derives one trim; every placement whose timing, props and
63
- errors did not change is returned as the same object, so consumers can
64
- memoise on `Placement` identity.
65
- `pnpm bench` prints per-step costs on the sample fixture and a synthetic
66
- 500-clip project.
67
- - `new Executor({ tree, manifest })` runs actions. Each handler has four faces:
68
- `validate`, `apply` (appends patches), `invert` (never null), `fold`. History
69
- groups gestures and auto-groups rapid same-target updates. `undo()` and
70
- `redo()` re-run inverses and originals through the same path.
71
- - `buildSourceIndex(text)` maps ids to source ranges. `foldToSource(text, log, state)`
72
- turns the patch log's net effect into text edits: a trim becomes one changed
73
- token, an inserted element is printed in place, a generated element is baked
74
- into literals first.
75
- - `lint(text, { manifest })` returns the file-contract diagnostics.
76
-
77
- ## Status
78
-
79
- Every action in the spec is registered, applies, and round-trips through
80
- undo/redo against `fixtures/sample.tsx` (which uses every element).
81
- There is
82
- no renderer: `useT()` and `useLayer()` throw until a Player installs one.
83
- `interpolate()`, `spring()` and `random()` are pure and work anywhere.
49
+ const state = resolve(collectModule(file), manifest); // every element placed in time, by id
50
+ const diagnostics = lint(text, { manifest }); // problems in the file, at their line
84
51
 
52
+ const exec = new Executor({ tree: collectModule(file), manifest });
53
+ exec.execute({ type: "clip/trim", params: { id: "c1", edge: "out", value: 9.5 } });
54
+ exec.undo();
55
+ const { text: edited } = foldToSource(text, exec.log(), exec.state()); // the edit as a text change
85
56
  ```
86
- pnpm typecheck
87
- pnpm lint
88
- pnpm test # vitest, node and jsdom
89
- pnpm parity # regenerate docs/parity.md
90
- ```
57
+
58
+ | | |
59
+ |---|---|
60
+ | `collectModule(mod)`, `resolve(tree, manifest, log?)` | Read a file and place everything in it: sequences, gaps, transitions, anchors, `fill` and `match` durations, transcript references and multicam cuts. Errors are typed and point at the element that caused them. A change costs about 2 µs per element, and placements that did not change keep their identity, so a UI can memoise on them. |
61
+ | `Executor` | Runs 131 editor actions (trim, split, move, ripple, keyframes, captions and more). Each one validates, applies and undoes; history groups a drag into one step. |
62
+ | `@cutcraft/kit/source` | `loadModule(source, { imports })` evaluates a file's text in the browser or in Node; the file may import `react`, `zod` and the kit, plus the modules you pass in `imports`. `buildSourceIndex` maps ids to their place in the text, `foldToSource` writes edits back as small token changes, and `lint` checks the file. |
63
+ | `interpolate`, `spring`, `random` | Pure animation helpers for free code. `useT()` and `useLayer()` give the current time once a player is mounted. |
64
+
65
+ The kit doesn't draw anything. [`@cutcraft/player`](https://www.npmjs.com/package/@cutcraft/player) plays a resolved
66
+ file in the browser, and [`cutcraft`](https://www.npmjs.com/package/cutcraft) exports it.
67
+
68
+ ## Docs
69
+
70
+ - [The file](https://prefix-tree.github.io/cutcraft/guide/the-file) and [Time by meaning](https://prefix-tree.github.io/cutcraft/guide/time)
71
+ - [Editing](https://prefix-tree.github.io/cutcraft/guide/editing)
72
+ - [Elements](https://prefix-tree.github.io/cutcraft/reference/elements/) and [actions](https://prefix-tree.github.io/cutcraft/reference/actions)
73
+
74
+ MIT licensed.