@cutcraft/kit 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +89 -2
- package/dist/index-CLhXqOpF.d.mts +1281 -0
- package/dist/index.d.mts +48103 -0
- package/dist/index.mjs +1 -0
- package/dist/source/index-public.d.mts +236 -0
- package/dist/source/index-public.mjs +1768 -0
- package/dist/src-BsBU2JLf.mjs +5101 -0
- package/package.json +60 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bohdan Snisar
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,90 @@
|
|
|
1
|
-
|
|
1
|
+
<p align="center"><img src="../../docs/public/logo.svg" width="64" alt="cutcut logo"></p>
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# @cutcraft/kit
|
|
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.
|
|
9
|
+
|
|
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).
|
|
12
|
+
|
|
13
|
+
## The file
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { z } from "zod";
|
|
17
|
+
import { Clip, Composition, Title, Track, Transition } from "@cutcraft/kit";
|
|
18
|
+
|
|
19
|
+
export const schema = z.object({ title: z.string(), accent: z.string() });
|
|
20
|
+
export const defaults = { title: "Why we built it", accent: "#ff5a1f" };
|
|
21
|
+
|
|
22
|
+
export default function Video({ title, accent }: z.infer<typeof schema>) {
|
|
23
|
+
return (
|
|
24
|
+
<Composition fps={30} width={1920} height={1080}>
|
|
25
|
+
<Track id="main">
|
|
26
|
+
<Clip id="c1" src="asset:interview" in="word:3" out="word:18" />
|
|
27
|
+
<Transition id="x1" type="crossfade" duration={0.5} />
|
|
28
|
+
<Clip id="c2" src="asset:city" duration={4} fit="cover" />
|
|
29
|
+
</Track>
|
|
30
|
+
<Track id="overlays">
|
|
31
|
+
<Title id="t1" anchor="c1" offset={1} duration={3} color={accent}>{title}</Title>
|
|
32
|
+
</Track>
|
|
33
|
+
</Composition>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
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`).
|
|
43
|
+
|
|
44
|
+
## The pipeline
|
|
45
|
+
|
|
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
|
+
```
|
|
51
|
+
|
|
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.
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
pnpm typecheck
|
|
87
|
+
pnpm lint
|
|
88
|
+
pnpm test # vitest, node and jsdom
|
|
89
|
+
pnpm parity # regenerate docs/parity.md
|
|
90
|
+
```
|