@cueframe/kernel 0.2.57 → 0.2.58
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/dist/THIRD_PARTY_NOTICES.md +111 -0
- package/dist/_members/component-runtime/template/bind.d.ts +22 -0
- package/dist/_members/component-runtime/template/bind.d.ts.map +1 -0
- package/dist/_members/component-runtime/template/extract.d.ts +31 -0
- package/dist/_members/component-runtime/template/extract.d.ts.map +1 -0
- package/dist/_members/component-runtime/template/index.d.ts +5 -0
- package/dist/_members/component-runtime/template/index.d.ts.map +1 -0
- package/dist/_members/component-runtime/template/schema.d.ts +1580 -0
- package/dist/_members/component-runtime/template/schema.d.ts.map +1 -0
- package/dist/_members/component-runtime/template/testing/fixtures.d.ts +33 -0
- package/dist/_members/component-runtime/template/testing/fixtures.d.ts.map +1 -0
- package/dist/_members/component-runtime/template/testing/index.d.ts +3 -0
- package/dist/_members/component-runtime/template/testing/index.d.ts.map +1 -0
- package/dist/_members/component-runtime/template/testing/templateApplyContract.d.ts +54 -0
- package/dist/_members/component-runtime/template/testing/templateApplyContract.d.ts.map +1 -0
- package/dist/_members/composition/primitive-catalog/index.d.ts +2 -1
- package/dist/_members/composition/primitive-catalog/types.d.ts +3 -1
- package/dist/_members/composition/validators/brandKit.d.ts +7 -0
- package/dist/_members/composition/validators/brandKitBody.d.ts +543 -0
- package/dist/_members/errors/registry.d.ts +36 -0
- package/dist/_members/mcp/server.d.ts +5 -2
- package/dist/_members/primitives/backgrounds/dynamic-grid/config.d.ts +1 -1
- package/dist/_members/primitives/effects/blur/config.d.ts +1 -1
- package/dist/_members/primitives/effects/color-grade/config.d.ts +2 -2
- package/dist/_members/primitives/effects/grain/config.d.ts +3 -3
- package/dist/_members/primitives/effects/particles/config.d.ts +2 -2
- package/dist/_members/primitives/effects/stage-camera/config.d.ts +6 -6
- package/dist/_members/primitives/effects/vignette/config.d.ts +1 -1
- package/dist/_members/primitives/layouts/flex-layout/config.d.ts +3 -3
- package/dist/_members/primitives/layouts/picture-in-picture/config.d.ts +2 -2
- package/dist/_members/primitives/lib/types.d.ts +1 -1
- package/dist/_members/primitives/scenes/device-showcase/config.d.ts +7 -7
- package/dist/_members/primitives/text/cinematic-title/config.d.ts +3 -3
- package/dist/_members/primitives/text/karaoke/config.d.ts +1 -1
- package/dist/_members/primitives/text/kinetic-type/config.d.ts +3 -3
- package/dist/_members/primitives/text/stat-counter/config.d.ts +1 -1
- package/dist/_members/primitives/text/text-effect/config.d.ts +2 -2
- package/dist/_members/primitives/transitions/grid-pixelate-wipe/config.d.ts +1 -1
- package/dist/_members/primitives/ui-blocks/badge-pop/config.d.ts +3 -3
- package/dist/_members/primitives/ui-blocks/terminal-simulator/config.d.ts +2 -2
- package/dist/_members/primitives/ui-blocks/toast-notification/config.d.ts +2 -2
- package/dist/authoring/build-tools.js +5 -4
- package/dist/authoring/context.js +2 -1
- package/dist/authoring/tools.js +4 -3
- package/dist/authoring.js +7 -6
- package/dist/{chunk-R7G2PNEZ.js → chunk-2L33CKIY.js} +11 -13
- package/dist/{chunk-N54EGUVM.js → chunk-3VLDQE26.js} +1 -1
- package/dist/{chunk-7AZLFN26.js → chunk-4NIJWK45.js} +20 -12
- package/dist/{chunk-KSRFYFUZ.js → chunk-5T655LYZ.js} +1 -1
- package/dist/{chunk-RERR5JLM.js → chunk-6UZYUWBX.js} +1 -1
- package/dist/{chunk-LBN5KQC6.js → chunk-7EDLPIUN.js} +3 -3
- package/dist/{chunk-MZB4ZXYW.js → chunk-7NIOFHMH.js} +1 -1
- package/dist/{chunk-E63UEO5C.js → chunk-AK5QBHOB.js} +6 -0
- package/dist/{chunk-BDFAA747.js → chunk-GQ6XGAFB.js} +1 -1
- package/dist/chunk-IG3YAOUZ.js +418 -0
- package/dist/{chunk-Z4G3VM3H.js → chunk-JN3GF36B.js} +1 -1
- package/dist/{chunk-DV7ZFVL4.js → chunk-MFMR3LHO.js} +1 -1
- package/dist/{chunk-JPMVNMF3.js → chunk-MNO6AO2J.js} +1 -1
- package/dist/{chunk-VXGA7LQQ.js → chunk-NVXSKKRN.js} +2 -2
- package/dist/chunk-PWWZTY3G.js +254 -0
- package/dist/chunk-REST55RC.js +366 -0
- package/dist/chunk-TR53N6HB.js +196 -0
- package/dist/{chunk-4PV3UYJF.js → chunk-UXRSEMJJ.js} +201 -201
- package/dist/component-runtime/template/testing.d.ts +1 -0
- package/dist/component-runtime/template/testing.js +380 -0
- package/dist/component-runtime/template.d.ts +1 -0
- package/dist/component-runtime/template.js +99 -0
- package/dist/compose.js +20 -20
- package/dist/composition/floors.js +1 -1
- package/dist/composition/ops.js +2 -1
- package/dist/composition/primitive-catalog.js +3 -1
- package/dist/composition/projection.js +2 -2
- package/dist/composition/validators/brand-kit-body.d.ts +1 -0
- package/dist/composition/validators/brand-kit-body.js +17 -0
- package/dist/composition/validators.js +10 -6
- package/dist/composition-ops.js +7 -6
- package/dist/composition.js +12 -8
- package/dist/{context-6HPUO36M.js → context-4WSFPRLX.js} +2 -1
- package/dist/core/render.js +4 -4
- package/dist/core/select.js +2 -2
- package/dist/core.js +4 -4
- package/dist/director/ai-sdk.js +3 -3
- package/dist/director/domain.js +2 -2
- package/dist/director.js +3 -3
- package/dist/errors.js +1 -1
- package/dist/mcp/adapter.js +3 -3
- package/dist/mcp/server.js +3 -26
- package/dist/mcp.js +3 -26
- package/dist/nle-export.js +1 -1
- package/dist/primitives/captions.js +3 -3
- package/dist/primitives.js +18 -18
- package/dist/render-harness/cardAssetAdmission.js +2 -2
- package/dist/render-harness/cardFonts.js +2 -2
- package/dist/render-harness/renderInputAssets.js +2 -2
- package/dist/render-harness.js +8 -8
- package/dist/src-ZP6727AA.js +70 -0
- package/package.json +22 -10
- package/dist/chunk-AXRSCHQX.js +0 -661
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MotifMotionPreset
|
|
3
|
+
} from "./chunk-PWWZTY3G.js";
|
|
4
|
+
import {
|
|
5
|
+
GraphicRole
|
|
6
|
+
} from "./chunk-UFD4EZHM.js";
|
|
7
|
+
|
|
8
|
+
// ../composition/src/validators/brandKitBody.ts
|
|
9
|
+
import { z } from "zod";
|
|
10
|
+
var BrandFontField = z.object({
|
|
11
|
+
fontFamily: z.string().min(1, "fontFamily: non-empty string"),
|
|
12
|
+
fontWeight: z.number()
|
|
13
|
+
});
|
|
14
|
+
var BrandMotifBody = z.discriminatedUnion("kind", [
|
|
15
|
+
z.object({
|
|
16
|
+
kind: z.literal("card"),
|
|
17
|
+
html: z.string().min(1, "motifs[].body.html: non-empty string"),
|
|
18
|
+
tokens: z.record(z.string(), z.string()).optional()
|
|
19
|
+
}),
|
|
20
|
+
z.object({
|
|
21
|
+
kind: z.literal("overlay"),
|
|
22
|
+
primitiveId: z.string().min(1),
|
|
23
|
+
params: z.record(z.string(), z.unknown()).optional()
|
|
24
|
+
}),
|
|
25
|
+
z.object({
|
|
26
|
+
kind: z.literal("component"),
|
|
27
|
+
componentId: z.string().min(1),
|
|
28
|
+
props: z.record(z.string(), z.unknown()).optional()
|
|
29
|
+
})
|
|
30
|
+
]);
|
|
31
|
+
var BrandMotif = z.object({
|
|
32
|
+
id: z.string().min(1).max(40),
|
|
33
|
+
observed: z.string().min(1).max(500),
|
|
34
|
+
body: BrandMotifBody,
|
|
35
|
+
motion: z.object({
|
|
36
|
+
preset: MotifMotionPreset,
|
|
37
|
+
enterMs: z.number().int().min(0).max(5e3).optional(),
|
|
38
|
+
exitMs: z.number().int().min(0).max(5e3).optional(),
|
|
39
|
+
staggerMs: z.number().int().min(0).max(2e3).optional(),
|
|
40
|
+
confidence: z.enum(["high", "low"]).optional()
|
|
41
|
+
}).optional(),
|
|
42
|
+
role: z.enum(GraphicRole.options),
|
|
43
|
+
zone: z.object({ x: z.number(), y: z.number(), w: z.number(), h: z.number() }).optional(),
|
|
44
|
+
evidence: z.array(z.number().int().min(0)).max(24).optional(),
|
|
45
|
+
diffScore: z.number().min(0).max(1).optional(),
|
|
46
|
+
coverage: z.enum(["reproduced", "approximated", "skipped"]),
|
|
47
|
+
skipReason: z.string().max(300).optional()
|
|
48
|
+
});
|
|
49
|
+
var BrandAudioPaletteRef = z.string().min(1);
|
|
50
|
+
var BrandAudioSchema = z.object({
|
|
51
|
+
sfxIntensity: z.enum(["off", "light", "standard", "dense"]).optional(),
|
|
52
|
+
musicEnabled: z.boolean().optional(),
|
|
53
|
+
musicMood: z.string().max(300).optional(),
|
|
54
|
+
sonicLogo: z.object({
|
|
55
|
+
ref: BrandAudioPaletteRef,
|
|
56
|
+
placement: z.enum(["intro", "outro", "both"]),
|
|
57
|
+
offsetMs: z.number().int().min(0).max(1e4).optional()
|
|
58
|
+
}).optional().describe(
|
|
59
|
+
"A brand sound signature bound to the intro/outro bookend. `ref` = a palette reference; bound only when the kit carries the matching bumper (intro/outro), else a non-blocking advisory."
|
|
60
|
+
),
|
|
61
|
+
uiSoundSet: z.object({
|
|
62
|
+
tick: BrandAudioPaletteRef.optional(),
|
|
63
|
+
pop: BrandAudioPaletteRef.optional(),
|
|
64
|
+
impact: BrandAudioPaletteRef.optional(),
|
|
65
|
+
confirm: BrandAudioPaletteRef.optional(),
|
|
66
|
+
error: BrandAudioPaletteRef.optional(),
|
|
67
|
+
whoosh: BrandAudioPaletteRef.optional(),
|
|
68
|
+
riser: BrandAudioPaletteRef.optional()
|
|
69
|
+
}).optional().describe(
|
|
70
|
+
"Per-family SFX overrides (the brand's own tick/pop/\u2026). Highest-priority tier over the org palette + pack default in the compose SFX draw."
|
|
71
|
+
),
|
|
72
|
+
bedStyle: z.object({
|
|
73
|
+
bedId: BrandAudioPaletteRef.optional(),
|
|
74
|
+
genre: z.string().max(120).optional(),
|
|
75
|
+
bpmRange: z.object({ min: z.number(), max: z.number() }).optional()
|
|
76
|
+
}).optional().describe(
|
|
77
|
+
"Preferred music bed (`bedId`) or a style hint (`genre` / `bpmRange`). Surfaced for driving agents; compose does not auto-select a pack bed."
|
|
78
|
+
),
|
|
79
|
+
ambiencePreference: z.object({ ref: BrandAudioPaletteRef }).nullable().optional().describe(
|
|
80
|
+
"Preferred ambience bed (`{ref}`) or explicit null (opt-out). Surfaced for driving agents; compose has no ambience auto-placement."
|
|
81
|
+
)
|
|
82
|
+
});
|
|
83
|
+
var BrandIntroOutroBody = (field) => z.object({
|
|
84
|
+
kind: z.enum(["card", "video"]),
|
|
85
|
+
src: z.string().min(1, `${field}.src: non-empty string`).optional(),
|
|
86
|
+
title: z.string().optional(),
|
|
87
|
+
subtitle: z.string().optional(),
|
|
88
|
+
durationMs: z.number().optional()
|
|
89
|
+
});
|
|
90
|
+
var BrandKitBodyShape = {
|
|
91
|
+
kitId: z.string().min(1, "kitId: non-empty string required").max(200, "kitId: exceeds max length of 200").refine((v) => v.trim().length > 0, "kitId: non-empty string required"),
|
|
92
|
+
name: z.string().min(1, "name: non-empty string required").max(200, "name: exceeds max length of 200").refine((v) => v.trim().length > 0, "name: non-empty string required"),
|
|
93
|
+
description: z.string().max(2e3).optional(),
|
|
94
|
+
tagline: z.string().max(500).optional(),
|
|
95
|
+
secondaryTagline: z.string().max(500).optional(),
|
|
96
|
+
colors: z.object({
|
|
97
|
+
primary: z.string().min(1, "colors.primary: non-empty string"),
|
|
98
|
+
secondary: z.string().min(1, "colors.secondary: non-empty string"),
|
|
99
|
+
accent: z.string().min(1, "colors.accent: non-empty string"),
|
|
100
|
+
background: z.string().min(1, "colors.background: non-empty string"),
|
|
101
|
+
text: z.string().min(1, "colors.text: non-empty string")
|
|
102
|
+
}),
|
|
103
|
+
extraColors: z.array(z.object({
|
|
104
|
+
hex: z.string().min(1, "extraColors[].hex: non-empty string"),
|
|
105
|
+
label: z.string().min(1, "extraColors[].label: non-empty string"),
|
|
106
|
+
usage: z.string().optional()
|
|
107
|
+
})).optional(),
|
|
108
|
+
headingFont: BrandFontField,
|
|
109
|
+
bodyFont: BrandFontField,
|
|
110
|
+
voiceGuidelines: z.string().max(5e3).optional(),
|
|
111
|
+
syncCaptions: z.boolean().optional(),
|
|
112
|
+
captionProfile: z.object({
|
|
113
|
+
fontFamily: z.string().optional(),
|
|
114
|
+
fontSize: z.number().optional(),
|
|
115
|
+
fontWeight: z.number().optional(),
|
|
116
|
+
color: z.string().optional(),
|
|
117
|
+
highlightColor: z.string().optional(),
|
|
118
|
+
backgroundColor: z.string().optional(),
|
|
119
|
+
plate: z.enum(["glass", "solid", "none"]).optional(),
|
|
120
|
+
position: z.enum(["top", "center", "bottom"]).optional(),
|
|
121
|
+
textTransform: z.enum(["none", "uppercase"]).optional(),
|
|
122
|
+
entrance: z.enum(["none", "fade", "word-pop", "stagger-up"]).optional(),
|
|
123
|
+
entranceMs: z.number().optional(),
|
|
124
|
+
entranceStaggerMs: z.number().optional(),
|
|
125
|
+
exitMs: z.number().optional(),
|
|
126
|
+
emphasisColor: z.string().optional(),
|
|
127
|
+
emphasisScale: z.number().optional(),
|
|
128
|
+
emphasisFontFamily: z.string().optional(),
|
|
129
|
+
emphasisFontWeight: z.number().optional(),
|
|
130
|
+
emphasisFontStyle: z.enum(["normal", "italic"]).optional(),
|
|
131
|
+
emphasisTextTransform: z.enum(["none", "uppercase"]).optional(),
|
|
132
|
+
emphasisLetterSpacing: z.number().optional(),
|
|
133
|
+
emphasisPlate: z.boolean().optional(),
|
|
134
|
+
emphasisPlateColor: z.string().optional(),
|
|
135
|
+
emphasisPlateTextColor: z.string().optional()
|
|
136
|
+
}).optional(),
|
|
137
|
+
motion: z.object({
|
|
138
|
+
duration: z.number().optional(),
|
|
139
|
+
easing: z.union([
|
|
140
|
+
z.enum(["linear", "ease", "ease-in", "ease-out", "ease-in-out"]),
|
|
141
|
+
z.object({
|
|
142
|
+
kind: z.literal("cubic-bezier"),
|
|
143
|
+
x1: z.number(),
|
|
144
|
+
y1: z.number(),
|
|
145
|
+
x2: z.number(),
|
|
146
|
+
y2: z.number()
|
|
147
|
+
})
|
|
148
|
+
]).optional(),
|
|
149
|
+
entrance: z.enum(["none", "fade", "word-pop", "stagger-up"]).optional(),
|
|
150
|
+
staggerMs: z.number().optional(),
|
|
151
|
+
exitMs: z.number().optional()
|
|
152
|
+
}).optional(),
|
|
153
|
+
logo: z.object({
|
|
154
|
+
src: z.string().min(1, "logo.src: non-empty string"),
|
|
155
|
+
alt: z.string().optional(),
|
|
156
|
+
placement: z.enum(["tl", "tr", "bl", "br"]).optional(),
|
|
157
|
+
sizePct: z.number().optional()
|
|
158
|
+
}).optional(),
|
|
159
|
+
intro: BrandIntroOutroBody("intro").optional(),
|
|
160
|
+
outro: BrandIntroOutroBody("outro").optional(),
|
|
161
|
+
watermark: z.object({
|
|
162
|
+
src: z.string().min(1, "watermark.src: non-empty string"),
|
|
163
|
+
opacity: z.number().min(0).max(1).optional(),
|
|
164
|
+
placement: z.enum(["tl", "tr", "bl", "br"]).optional()
|
|
165
|
+
}).optional(),
|
|
166
|
+
spacing: z.object({
|
|
167
|
+
base: z.number().optional(),
|
|
168
|
+
lg: z.number().optional(),
|
|
169
|
+
sm: z.number().optional()
|
|
170
|
+
}).optional(),
|
|
171
|
+
sizing: z.object({
|
|
172
|
+
fontSizeHeading: z.number().optional(),
|
|
173
|
+
fontSizeBody: z.number().optional(),
|
|
174
|
+
fontSizeLabel: z.number().optional(),
|
|
175
|
+
borderRadius: z.number().optional()
|
|
176
|
+
}).optional(),
|
|
177
|
+
audio: BrandAudioSchema.optional(),
|
|
178
|
+
motifs: z.array(BrandMotif).max(24).optional(),
|
|
179
|
+
styleRubric: z.string().max(4e3).optional(),
|
|
180
|
+
density: z.object({
|
|
181
|
+
graphicsPerMin: z.number().min(0).max(60),
|
|
182
|
+
maxSimultaneous: z.number().int().min(1).max(6)
|
|
183
|
+
}).optional(),
|
|
184
|
+
inspiration: z.object({
|
|
185
|
+
sources: z.array(z.string()).min(1).max(24),
|
|
186
|
+
extractedAt: z.number(),
|
|
187
|
+
extractionVersion: z.string().min(1).max(60)
|
|
188
|
+
}).optional()
|
|
189
|
+
};
|
|
190
|
+
var BrandKitBodySchema = z.strictObject(BrandKitBodyShape);
|
|
191
|
+
|
|
192
|
+
export {
|
|
193
|
+
BrandAudioSchema,
|
|
194
|
+
BrandKitBodyShape,
|
|
195
|
+
BrandKitBodySchema
|
|
196
|
+
};
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
projectMediaPlaybackSpans,
|
|
4
4
|
sliceTranscriptWords,
|
|
5
5
|
splitIntoSentences
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-NVXSKKRN.js";
|
|
7
7
|
import {
|
|
8
8
|
createHeadlessStore,
|
|
9
9
|
findClipById,
|
|
@@ -40,6 +40,206 @@ import {
|
|
|
40
40
|
// ../composition-ops/src/index.ts
|
|
41
41
|
import { z } from "zod";
|
|
42
42
|
|
|
43
|
+
// ../composition-ops/src/opRecorder.ts
|
|
44
|
+
var genTrackId = (kind) => `track-${kind}-${crypto.randomUUID().slice(0, 8)}`;
|
|
45
|
+
function wrapWithOpRecorder(base, opts) {
|
|
46
|
+
const { record, getComposition } = opts;
|
|
47
|
+
const captionTarget = {
|
|
48
|
+
getState: () => ({ composition: getComposition() }),
|
|
49
|
+
setCaptionStyle: (style) => base.setCaptionStyle(style),
|
|
50
|
+
setCaptions: (segments, style) => base.setCaptions(segments, style)
|
|
51
|
+
};
|
|
52
|
+
const wrapped = {
|
|
53
|
+
addClip: (clip, options) => {
|
|
54
|
+
const before = getComposition();
|
|
55
|
+
const c = clip.kind ? clip : { ...clip, kind: "video" };
|
|
56
|
+
if (options?.newTrack) {
|
|
57
|
+
const newTrackId = options.newTrackId ?? genTrackId("video");
|
|
58
|
+
record({ type: "clip.add", clip: c, newTrack: true, newTrackId }, before);
|
|
59
|
+
base.addClip(c, { newTrack: true, newTrackId });
|
|
60
|
+
} else {
|
|
61
|
+
record({ type: "clip.add", clip: c }, before);
|
|
62
|
+
base.addClip(c);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
removeClip: (id) => {
|
|
66
|
+
record({ type: "clip.remove", clipId: id }, getComposition());
|
|
67
|
+
base.removeClip(id);
|
|
68
|
+
},
|
|
69
|
+
updateClip: (id, updates) => {
|
|
70
|
+
record({ type: "clip.update", clipId: id, patch: updates }, getComposition());
|
|
71
|
+
base.updateClip(id, updates);
|
|
72
|
+
},
|
|
73
|
+
removeClipsByMediaId: (mediaId) => {
|
|
74
|
+
record({ type: "removeClipsByMediaId", mediaId }, getComposition());
|
|
75
|
+
base.removeClipsByMediaId(mediaId);
|
|
76
|
+
},
|
|
77
|
+
setClipProperties: (id, props) => {
|
|
78
|
+
const { playbackRate, ...patch } = props;
|
|
79
|
+
if (playbackRate !== void 0) {
|
|
80
|
+
if (opts.onUnjournalable) {
|
|
81
|
+
const result = base.setClipProperties(id, props);
|
|
82
|
+
opts.onUnjournalable("setClipProperties.playbackRate");
|
|
83
|
+
return result;
|
|
84
|
+
}
|
|
85
|
+
throw new Error(
|
|
86
|
+
"opRecorder.setClipProperties: playbackRate is not serializable as a clip.update op (source.playbackRate triggers a cross-field ripple). Use the server-authoritative ripple path."
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
record({ type: "clip.update", clipId: id, patch }, getComposition());
|
|
90
|
+
return base.setClipProperties(id, props);
|
|
91
|
+
},
|
|
92
|
+
addOverlay: (clip) => {
|
|
93
|
+
const before = getComposition();
|
|
94
|
+
const track = before.tracks.find((t) => t.kind === "overlay");
|
|
95
|
+
let trackId = track?.id;
|
|
96
|
+
if (!trackId) {
|
|
97
|
+
trackId = genTrackId("overlay");
|
|
98
|
+
record({ type: "addTrack", kind: "overlay", id: trackId }, before);
|
|
99
|
+
base.addTrack("overlay", void 0, trackId);
|
|
100
|
+
}
|
|
101
|
+
record({ type: "clip.add", clip, trackId }, getComposition());
|
|
102
|
+
base.addOverlay(clip);
|
|
103
|
+
},
|
|
104
|
+
removeOverlay: (id) => {
|
|
105
|
+
record({ type: "clip.remove", clipId: id }, getComposition());
|
|
106
|
+
base.removeOverlay(id);
|
|
107
|
+
},
|
|
108
|
+
updateOverlay: (id, updates) => {
|
|
109
|
+
record({ type: "clip.update", clipId: id, patch: updates }, getComposition());
|
|
110
|
+
base.updateOverlay(id, updates);
|
|
111
|
+
},
|
|
112
|
+
loadOverlays: (clips) => {
|
|
113
|
+
record({ type: "loadOverlays", clips }, getComposition());
|
|
114
|
+
base.loadOverlays(clips);
|
|
115
|
+
},
|
|
116
|
+
addAudioClip: (clip) => {
|
|
117
|
+
const before = getComposition();
|
|
118
|
+
const track = before.tracks.find((t) => t.kind === "audio");
|
|
119
|
+
let trackId = track?.id;
|
|
120
|
+
if (!trackId) {
|
|
121
|
+
trackId = genTrackId("audio");
|
|
122
|
+
record({ type: "addTrack", kind: "audio", id: trackId }, before);
|
|
123
|
+
base.addTrack("audio", void 0, trackId);
|
|
124
|
+
}
|
|
125
|
+
record({ type: "clip.add", clip, trackId }, getComposition());
|
|
126
|
+
base.addAudioClip(clip);
|
|
127
|
+
},
|
|
128
|
+
removeAudioClip: (id) => {
|
|
129
|
+
record({ type: "clip.remove", clipId: id }, getComposition());
|
|
130
|
+
base.removeAudioClip(id);
|
|
131
|
+
},
|
|
132
|
+
updateAudioClip: (id, updates) => {
|
|
133
|
+
record({ type: "clip.update", clipId: id, patch: updates }, getComposition());
|
|
134
|
+
base.updateAudioClip(id, updates);
|
|
135
|
+
},
|
|
136
|
+
addMarker: (marker) => {
|
|
137
|
+
record({ type: "addMarker", marker }, getComposition());
|
|
138
|
+
base.addMarker(marker);
|
|
139
|
+
},
|
|
140
|
+
removeMarker: (id) => {
|
|
141
|
+
record({ type: "removeMarker", markerId: id }, getComposition());
|
|
142
|
+
base.removeMarker(id);
|
|
143
|
+
},
|
|
144
|
+
updateMarker: (id, updates) => {
|
|
145
|
+
record({ type: "updateMarker", markerId: id, updates }, getComposition());
|
|
146
|
+
base.updateMarker(id, updates);
|
|
147
|
+
},
|
|
148
|
+
setCropIntents: (clipId, segments) => {
|
|
149
|
+
record({ type: "setCropIntents", clipId, segments }, getComposition());
|
|
150
|
+
base.setCropIntents(clipId, segments);
|
|
151
|
+
},
|
|
152
|
+
setEffects: (clipId, effects) => {
|
|
153
|
+
record({ type: "setEffects", clipId, effects }, getComposition());
|
|
154
|
+
base.setEffects(clipId, effects);
|
|
155
|
+
},
|
|
156
|
+
// The two caption writes go through the same function `applyOpToStore` uses, so the op this
|
|
157
|
+
// journals is exactly the op a replay applies. Calling the store's setter directly left this
|
|
158
|
+
// lane — Studio's composition store and the in-app agent capability are built on it — able to
|
|
159
|
+
// write a face the op gate refuses and to journal an op `applyOp` would refuse on replay.
|
|
160
|
+
// The op is applied FIRST: a refusal must leave nothing in the journal.
|
|
161
|
+
setCaptionStyle: (style) => {
|
|
162
|
+
const before = getComposition();
|
|
163
|
+
const op = { type: "setCaptionStyle", style };
|
|
164
|
+
applyCaptionOpToStore(captionTarget, op);
|
|
165
|
+
record(op, before);
|
|
166
|
+
},
|
|
167
|
+
setCaptions: (segments, style) => {
|
|
168
|
+
const before = getComposition();
|
|
169
|
+
const op = {
|
|
170
|
+
type: "setCaptions",
|
|
171
|
+
segments,
|
|
172
|
+
...style !== void 0 ? { style } : {}
|
|
173
|
+
};
|
|
174
|
+
applyCaptionOpToStore(captionTarget, op);
|
|
175
|
+
record(op, before);
|
|
176
|
+
},
|
|
177
|
+
setFormat: (format) => {
|
|
178
|
+
record({ type: "setFormat", format }, getComposition());
|
|
179
|
+
base.setFormat(format);
|
|
180
|
+
},
|
|
181
|
+
addTrack: (kind, name, id) => {
|
|
182
|
+
const useId = id ?? genTrackId(kind);
|
|
183
|
+
record({ type: "addTrack", kind, ...name !== void 0 ? { name } : {}, id: useId }, getComposition());
|
|
184
|
+
base.addTrack(kind, name, useId);
|
|
185
|
+
},
|
|
186
|
+
removeTrack: (trackId) => {
|
|
187
|
+
record({ type: "removeTrack", trackId }, getComposition());
|
|
188
|
+
base.removeTrack(trackId);
|
|
189
|
+
},
|
|
190
|
+
updateTrack: (trackId, updates) => {
|
|
191
|
+
record({ type: "updateTrack", trackId, updates }, getComposition());
|
|
192
|
+
base.updateTrack(trackId, updates);
|
|
193
|
+
},
|
|
194
|
+
reorderTracks: (fromIndex, toIndex) => {
|
|
195
|
+
record({ type: "reorderTracks", fromIndex, toIndex }, getComposition());
|
|
196
|
+
base.reorderTracks(fromIndex, toIndex);
|
|
197
|
+
},
|
|
198
|
+
moveClipToTrack: (clipId, targetTrackId, newStartTime) => {
|
|
199
|
+
record(
|
|
200
|
+
{
|
|
201
|
+
type: "moveClipToTrack",
|
|
202
|
+
clipId,
|
|
203
|
+
targetTrackId,
|
|
204
|
+
...newStartTime !== void 0 ? { newStartTime } : {}
|
|
205
|
+
},
|
|
206
|
+
getComposition()
|
|
207
|
+
);
|
|
208
|
+
base.moveClipToTrack(clipId, targetTrackId, newStartTime);
|
|
209
|
+
},
|
|
210
|
+
duplicateClip: (id) => {
|
|
211
|
+
record({ type: "duplicateClip", clipId: id }, getComposition());
|
|
212
|
+
return base.duplicateClip(id);
|
|
213
|
+
},
|
|
214
|
+
cutAndRipple: (start, end) => {
|
|
215
|
+
record({ type: "cutAndRipple", start, end }, getComposition());
|
|
216
|
+
base.cutAndRipple(start, end);
|
|
217
|
+
},
|
|
218
|
+
ripple: (time, amount) => {
|
|
219
|
+
record({ type: "ripple", time, amount }, getComposition());
|
|
220
|
+
base.ripple(time, amount);
|
|
221
|
+
},
|
|
222
|
+
addExcludedRange: (clipId, sourceStart, sourceEnd, reason) => {
|
|
223
|
+
record(
|
|
224
|
+
{
|
|
225
|
+
type: "addExcludedRange",
|
|
226
|
+
clipId,
|
|
227
|
+
sourceStart,
|
|
228
|
+
sourceEnd,
|
|
229
|
+
...reason !== void 0 ? { reason } : {}
|
|
230
|
+
},
|
|
231
|
+
getComposition()
|
|
232
|
+
);
|
|
233
|
+
base.addExcludedRange(clipId, sourceStart, sourceEnd, reason);
|
|
234
|
+
},
|
|
235
|
+
removeExcludedRange: (clipId, rangeIdx) => {
|
|
236
|
+
record({ type: "removeExcludedRange", clipId, rangeIdx }, getComposition());
|
|
237
|
+
base.removeExcludedRange(clipId, rangeIdx);
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
return { ...base, ...wrapped };
|
|
241
|
+
}
|
|
242
|
+
|
|
43
243
|
// ../composition-ops/src/recordingStore.ts
|
|
44
244
|
function createRecordingStore(initial) {
|
|
45
245
|
const base = createHeadlessStore(initial);
|
|
@@ -892,206 +1092,6 @@ function invertOp(before, op) {
|
|
|
892
1092
|
}
|
|
893
1093
|
}
|
|
894
1094
|
|
|
895
|
-
// ../composition-ops/src/opRecorder.ts
|
|
896
|
-
var genTrackId = (kind) => `track-${kind}-${crypto.randomUUID().slice(0, 8)}`;
|
|
897
|
-
function wrapWithOpRecorder(base, opts) {
|
|
898
|
-
const { record, getComposition } = opts;
|
|
899
|
-
const captionTarget = {
|
|
900
|
-
getState: () => ({ composition: getComposition() }),
|
|
901
|
-
setCaptionStyle: (style) => base.setCaptionStyle(style),
|
|
902
|
-
setCaptions: (segments, style) => base.setCaptions(segments, style)
|
|
903
|
-
};
|
|
904
|
-
const wrapped = {
|
|
905
|
-
addClip: (clip, options) => {
|
|
906
|
-
const before = getComposition();
|
|
907
|
-
const c = clip.kind ? clip : { ...clip, kind: "video" };
|
|
908
|
-
if (options?.newTrack) {
|
|
909
|
-
const newTrackId = options.newTrackId ?? genTrackId("video");
|
|
910
|
-
record({ type: "clip.add", clip: c, newTrack: true, newTrackId }, before);
|
|
911
|
-
base.addClip(c, { newTrack: true, newTrackId });
|
|
912
|
-
} else {
|
|
913
|
-
record({ type: "clip.add", clip: c }, before);
|
|
914
|
-
base.addClip(c);
|
|
915
|
-
}
|
|
916
|
-
},
|
|
917
|
-
removeClip: (id) => {
|
|
918
|
-
record({ type: "clip.remove", clipId: id }, getComposition());
|
|
919
|
-
base.removeClip(id);
|
|
920
|
-
},
|
|
921
|
-
updateClip: (id, updates) => {
|
|
922
|
-
record({ type: "clip.update", clipId: id, patch: updates }, getComposition());
|
|
923
|
-
base.updateClip(id, updates);
|
|
924
|
-
},
|
|
925
|
-
removeClipsByMediaId: (mediaId) => {
|
|
926
|
-
record({ type: "removeClipsByMediaId", mediaId }, getComposition());
|
|
927
|
-
base.removeClipsByMediaId(mediaId);
|
|
928
|
-
},
|
|
929
|
-
setClipProperties: (id, props) => {
|
|
930
|
-
const { playbackRate, ...patch } = props;
|
|
931
|
-
if (playbackRate !== void 0) {
|
|
932
|
-
if (opts.onUnjournalable) {
|
|
933
|
-
const result = base.setClipProperties(id, props);
|
|
934
|
-
opts.onUnjournalable("setClipProperties.playbackRate");
|
|
935
|
-
return result;
|
|
936
|
-
}
|
|
937
|
-
throw new Error(
|
|
938
|
-
"opRecorder.setClipProperties: playbackRate is not serializable as a clip.update op (source.playbackRate triggers a cross-field ripple). Use the server-authoritative ripple path."
|
|
939
|
-
);
|
|
940
|
-
}
|
|
941
|
-
record({ type: "clip.update", clipId: id, patch }, getComposition());
|
|
942
|
-
return base.setClipProperties(id, props);
|
|
943
|
-
},
|
|
944
|
-
addOverlay: (clip) => {
|
|
945
|
-
const before = getComposition();
|
|
946
|
-
const track = before.tracks.find((t) => t.kind === "overlay");
|
|
947
|
-
let trackId = track?.id;
|
|
948
|
-
if (!trackId) {
|
|
949
|
-
trackId = genTrackId("overlay");
|
|
950
|
-
record({ type: "addTrack", kind: "overlay", id: trackId }, before);
|
|
951
|
-
base.addTrack("overlay", void 0, trackId);
|
|
952
|
-
}
|
|
953
|
-
record({ type: "clip.add", clip, trackId }, getComposition());
|
|
954
|
-
base.addOverlay(clip);
|
|
955
|
-
},
|
|
956
|
-
removeOverlay: (id) => {
|
|
957
|
-
record({ type: "clip.remove", clipId: id }, getComposition());
|
|
958
|
-
base.removeOverlay(id);
|
|
959
|
-
},
|
|
960
|
-
updateOverlay: (id, updates) => {
|
|
961
|
-
record({ type: "clip.update", clipId: id, patch: updates }, getComposition());
|
|
962
|
-
base.updateOverlay(id, updates);
|
|
963
|
-
},
|
|
964
|
-
loadOverlays: (clips) => {
|
|
965
|
-
record({ type: "loadOverlays", clips }, getComposition());
|
|
966
|
-
base.loadOverlays(clips);
|
|
967
|
-
},
|
|
968
|
-
addAudioClip: (clip) => {
|
|
969
|
-
const before = getComposition();
|
|
970
|
-
const track = before.tracks.find((t) => t.kind === "audio");
|
|
971
|
-
let trackId = track?.id;
|
|
972
|
-
if (!trackId) {
|
|
973
|
-
trackId = genTrackId("audio");
|
|
974
|
-
record({ type: "addTrack", kind: "audio", id: trackId }, before);
|
|
975
|
-
base.addTrack("audio", void 0, trackId);
|
|
976
|
-
}
|
|
977
|
-
record({ type: "clip.add", clip, trackId }, getComposition());
|
|
978
|
-
base.addAudioClip(clip);
|
|
979
|
-
},
|
|
980
|
-
removeAudioClip: (id) => {
|
|
981
|
-
record({ type: "clip.remove", clipId: id }, getComposition());
|
|
982
|
-
base.removeAudioClip(id);
|
|
983
|
-
},
|
|
984
|
-
updateAudioClip: (id, updates) => {
|
|
985
|
-
record({ type: "clip.update", clipId: id, patch: updates }, getComposition());
|
|
986
|
-
base.updateAudioClip(id, updates);
|
|
987
|
-
},
|
|
988
|
-
addMarker: (marker) => {
|
|
989
|
-
record({ type: "addMarker", marker }, getComposition());
|
|
990
|
-
base.addMarker(marker);
|
|
991
|
-
},
|
|
992
|
-
removeMarker: (id) => {
|
|
993
|
-
record({ type: "removeMarker", markerId: id }, getComposition());
|
|
994
|
-
base.removeMarker(id);
|
|
995
|
-
},
|
|
996
|
-
updateMarker: (id, updates) => {
|
|
997
|
-
record({ type: "updateMarker", markerId: id, updates }, getComposition());
|
|
998
|
-
base.updateMarker(id, updates);
|
|
999
|
-
},
|
|
1000
|
-
setCropIntents: (clipId, segments) => {
|
|
1001
|
-
record({ type: "setCropIntents", clipId, segments }, getComposition());
|
|
1002
|
-
base.setCropIntents(clipId, segments);
|
|
1003
|
-
},
|
|
1004
|
-
setEffects: (clipId, effects) => {
|
|
1005
|
-
record({ type: "setEffects", clipId, effects }, getComposition());
|
|
1006
|
-
base.setEffects(clipId, effects);
|
|
1007
|
-
},
|
|
1008
|
-
// The two caption writes go through the same function `applyOpToStore` uses, so the op this
|
|
1009
|
-
// journals is exactly the op a replay applies. Calling the store's setter directly left this
|
|
1010
|
-
// lane — Studio's composition store and the in-app agent capability are built on it — able to
|
|
1011
|
-
// write a face the op gate refuses and to journal an op `applyOp` would refuse on replay.
|
|
1012
|
-
// The op is applied FIRST: a refusal must leave nothing in the journal.
|
|
1013
|
-
setCaptionStyle: (style) => {
|
|
1014
|
-
const before = getComposition();
|
|
1015
|
-
const op = { type: "setCaptionStyle", style };
|
|
1016
|
-
applyCaptionOpToStore(captionTarget, op);
|
|
1017
|
-
record(op, before);
|
|
1018
|
-
},
|
|
1019
|
-
setCaptions: (segments, style) => {
|
|
1020
|
-
const before = getComposition();
|
|
1021
|
-
const op = {
|
|
1022
|
-
type: "setCaptions",
|
|
1023
|
-
segments,
|
|
1024
|
-
...style !== void 0 ? { style } : {}
|
|
1025
|
-
};
|
|
1026
|
-
applyCaptionOpToStore(captionTarget, op);
|
|
1027
|
-
record(op, before);
|
|
1028
|
-
},
|
|
1029
|
-
setFormat: (format) => {
|
|
1030
|
-
record({ type: "setFormat", format }, getComposition());
|
|
1031
|
-
base.setFormat(format);
|
|
1032
|
-
},
|
|
1033
|
-
addTrack: (kind, name, id) => {
|
|
1034
|
-
const useId = id ?? genTrackId(kind);
|
|
1035
|
-
record({ type: "addTrack", kind, ...name !== void 0 ? { name } : {}, id: useId }, getComposition());
|
|
1036
|
-
base.addTrack(kind, name, useId);
|
|
1037
|
-
},
|
|
1038
|
-
removeTrack: (trackId) => {
|
|
1039
|
-
record({ type: "removeTrack", trackId }, getComposition());
|
|
1040
|
-
base.removeTrack(trackId);
|
|
1041
|
-
},
|
|
1042
|
-
updateTrack: (trackId, updates) => {
|
|
1043
|
-
record({ type: "updateTrack", trackId, updates }, getComposition());
|
|
1044
|
-
base.updateTrack(trackId, updates);
|
|
1045
|
-
},
|
|
1046
|
-
reorderTracks: (fromIndex, toIndex) => {
|
|
1047
|
-
record({ type: "reorderTracks", fromIndex, toIndex }, getComposition());
|
|
1048
|
-
base.reorderTracks(fromIndex, toIndex);
|
|
1049
|
-
},
|
|
1050
|
-
moveClipToTrack: (clipId, targetTrackId, newStartTime) => {
|
|
1051
|
-
record(
|
|
1052
|
-
{
|
|
1053
|
-
type: "moveClipToTrack",
|
|
1054
|
-
clipId,
|
|
1055
|
-
targetTrackId,
|
|
1056
|
-
...newStartTime !== void 0 ? { newStartTime } : {}
|
|
1057
|
-
},
|
|
1058
|
-
getComposition()
|
|
1059
|
-
);
|
|
1060
|
-
base.moveClipToTrack(clipId, targetTrackId, newStartTime);
|
|
1061
|
-
},
|
|
1062
|
-
duplicateClip: (id) => {
|
|
1063
|
-
record({ type: "duplicateClip", clipId: id }, getComposition());
|
|
1064
|
-
return base.duplicateClip(id);
|
|
1065
|
-
},
|
|
1066
|
-
cutAndRipple: (start, end) => {
|
|
1067
|
-
record({ type: "cutAndRipple", start, end }, getComposition());
|
|
1068
|
-
base.cutAndRipple(start, end);
|
|
1069
|
-
},
|
|
1070
|
-
ripple: (time, amount) => {
|
|
1071
|
-
record({ type: "ripple", time, amount }, getComposition());
|
|
1072
|
-
base.ripple(time, amount);
|
|
1073
|
-
},
|
|
1074
|
-
addExcludedRange: (clipId, sourceStart, sourceEnd, reason) => {
|
|
1075
|
-
record(
|
|
1076
|
-
{
|
|
1077
|
-
type: "addExcludedRange",
|
|
1078
|
-
clipId,
|
|
1079
|
-
sourceStart,
|
|
1080
|
-
sourceEnd,
|
|
1081
|
-
...reason !== void 0 ? { reason } : {}
|
|
1082
|
-
},
|
|
1083
|
-
getComposition()
|
|
1084
|
-
);
|
|
1085
|
-
base.addExcludedRange(clipId, sourceStart, sourceEnd, reason);
|
|
1086
|
-
},
|
|
1087
|
-
removeExcludedRange: (clipId, rangeIdx) => {
|
|
1088
|
-
record({ type: "removeExcludedRange", clipId, rangeIdx }, getComposition());
|
|
1089
|
-
base.removeExcludedRange(clipId, rangeIdx);
|
|
1090
|
-
}
|
|
1091
|
-
};
|
|
1092
|
-
return { ...base, ...wrapped };
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
1095
|
export {
|
|
1096
1096
|
wrapWithOpRecorder,
|
|
1097
1097
|
createRecordingStore,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "../../_members/component-runtime/template/testing/index.js";
|