@editframe/create 0.44.0 → 0.45.1
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/index.js +16 -28
- package/dist/index.js.map +1 -1
- package/dist/skills/editframe-brand-video-generator/README.md +155 -0
- package/dist/skills/editframe-brand-video-generator/SKILL.md +207 -0
- package/dist/skills/editframe-brand-video-generator/references/brand-examples.md +178 -0
- package/dist/skills/editframe-brand-video-generator/references/color-psychology.md +227 -0
- package/dist/skills/editframe-brand-video-generator/references/composition-patterns.md +383 -0
- package/dist/skills/editframe-brand-video-generator/references/editing.md +66 -0
- package/dist/skills/editframe-brand-video-generator/references/emotional-arcs.md +496 -0
- package/dist/skills/editframe-brand-video-generator/references/genre-selection.md +135 -0
- package/dist/skills/editframe-brand-video-generator/references/transition-styles.md +611 -0
- package/dist/skills/editframe-brand-video-generator/references/typography-personalities.md +326 -0
- package/dist/skills/editframe-brand-video-generator/references/video-archetypes.md +86 -0
- package/dist/skills/editframe-brand-video-generator/references/video-fundamentals.md +169 -0
- package/dist/skills/editframe-brand-video-generator/references/visual-metaphors.md +50 -0
- package/dist/skills/editframe-composition/SKILL.md +169 -0
- package/dist/skills/editframe-composition/references/audio.md +483 -0
- package/dist/skills/editframe-composition/references/captions.md +844 -0
- package/dist/skills/editframe-composition/references/composition-model.md +73 -0
- package/dist/skills/editframe-composition/references/configuration.md +403 -0
- package/dist/skills/editframe-composition/references/css-parts.md +105 -0
- package/dist/skills/editframe-composition/references/css-variables.md +640 -0
- package/dist/skills/editframe-composition/references/entry-points.md +810 -0
- package/dist/skills/editframe-composition/references/events.md +499 -0
- package/dist/skills/editframe-composition/references/getting-started.md +259 -0
- package/dist/skills/editframe-composition/references/hooks.md +234 -0
- package/dist/skills/editframe-composition/references/image.md +241 -0
- package/dist/skills/editframe-composition/references/r3f.md +580 -0
- package/dist/skills/editframe-composition/references/render-api.md +484 -0
- package/dist/skills/editframe-composition/references/render-strategies.md +119 -0
- package/dist/skills/editframe-composition/references/render-to-video.md +1101 -0
- package/dist/skills/editframe-composition/references/scripting.md +606 -0
- package/dist/skills/editframe-composition/references/sequencing.md +116 -0
- package/dist/skills/editframe-composition/references/server-rendering.md +753 -0
- package/dist/skills/editframe-composition/references/surface.md +329 -0
- package/dist/skills/editframe-composition/references/text.md +627 -0
- package/dist/skills/editframe-composition/references/time-model.md +99 -0
- package/dist/skills/editframe-composition/references/timegroup-modes.md +102 -0
- package/dist/skills/editframe-composition/references/timegroup.md +457 -0
- package/dist/skills/editframe-composition/references/timeline-root.md +398 -0
- package/dist/skills/editframe-composition/references/transcription.md +47 -0
- package/dist/skills/editframe-composition/references/transitions.md +608 -0
- package/dist/skills/editframe-composition/references/use-media-info.md +357 -0
- package/dist/skills/editframe-composition/references/video.md +506 -0
- package/dist/skills/editframe-composition/references/waveform.md +327 -0
- package/dist/skills/editframe-editor-gui/SKILL.md +152 -0
- package/dist/skills/editframe-editor-gui/references/active-root-temporal.md +657 -0
- package/dist/skills/editframe-editor-gui/references/canvas.md +947 -0
- package/dist/skills/editframe-editor-gui/references/controls.md +366 -0
- package/dist/skills/editframe-editor-gui/references/dial.md +756 -0
- package/dist/skills/editframe-editor-gui/references/editor-toolkit.md +587 -0
- package/dist/skills/editframe-editor-gui/references/filmstrip.md +460 -0
- package/dist/skills/editframe-editor-gui/references/fit-scale.md +772 -0
- package/dist/skills/editframe-editor-gui/references/focus-overlay.md +561 -0
- package/dist/skills/editframe-editor-gui/references/hierarchy.md +544 -0
- package/dist/skills/editframe-editor-gui/references/overlay-item.md +634 -0
- package/dist/skills/editframe-editor-gui/references/overlay-layer.md +429 -0
- package/dist/skills/editframe-editor-gui/references/pan-zoom.md +568 -0
- package/dist/skills/editframe-editor-gui/references/pause.md +397 -0
- package/dist/skills/editframe-editor-gui/references/play.md +370 -0
- package/dist/skills/editframe-editor-gui/references/preview.md +391 -0
- package/dist/skills/editframe-editor-gui/references/resizable-box.md +749 -0
- package/dist/skills/editframe-editor-gui/references/scrubber.md +588 -0
- package/dist/skills/editframe-editor-gui/references/thumbnail-strip.md +566 -0
- package/dist/skills/editframe-editor-gui/references/time-display.md +492 -0
- package/dist/skills/editframe-editor-gui/references/timeline-ruler.md +489 -0
- package/dist/skills/editframe-editor-gui/references/timeline.md +604 -0
- package/dist/skills/editframe-editor-gui/references/toggle-loop.md +618 -0
- package/dist/skills/editframe-editor-gui/references/toggle-play.md +526 -0
- package/dist/skills/editframe-editor-gui/references/transform-handles.md +924 -0
- package/dist/skills/editframe-editor-gui/references/trim-handles.md +725 -0
- package/dist/skills/editframe-editor-gui/references/workbench.md +453 -0
- package/dist/skills/editframe-motion-design/SKILL.md +101 -0
- package/dist/skills/editframe-motion-design/references/0-editframe.md +299 -0
- package/dist/skills/editframe-motion-design/references/1-intent.md +201 -0
- package/dist/skills/editframe-motion-design/references/2-physics-model.md +405 -0
- package/dist/skills/editframe-motion-design/references/3-attention.md +350 -0
- package/dist/skills/editframe-motion-design/references/4-process.md +418 -0
- package/dist/skills/editframe-vite-plugin/SKILL.md +75 -0
- package/dist/skills/editframe-vite-plugin/references/file-api.md +111 -0
- package/dist/skills/editframe-vite-plugin/references/getting-started.md +96 -0
- package/dist/skills/editframe-vite-plugin/references/jit-transcoding.md +91 -0
- package/dist/skills/editframe-vite-plugin/references/local-assets.md +75 -0
- package/dist/skills/editframe-vite-plugin/references/visual-testing.md +136 -0
- package/dist/skills/editframe-webhooks/SKILL.md +126 -0
- package/dist/skills/editframe-webhooks/references/events.md +382 -0
- package/dist/skills/editframe-webhooks/references/getting-started.md +232 -0
- package/dist/skills/editframe-webhooks/references/security.md +418 -0
- package/dist/skills/editframe-webhooks/references/testing.md +409 -0
- package/dist/skills/editframe-webhooks/references/troubleshooting.md +457 -0
- package/dist/templates/html/AGENTS.md +13 -0
- package/dist/templates/react/AGENTS.md +13 -0
- package/dist/utils.js +15 -16
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
- package/tsdown.config.ts +4 -0
- package/dist/detectAgent.js +0 -89
- package/dist/detectAgent.js.map +0 -1
|
@@ -0,0 +1,657 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Active Root Temporal Element
|
|
3
|
+
description: Component that displays the ID of whichever root temporal element is currently active based on canvas selection state.
|
|
4
|
+
type: reference
|
|
5
|
+
nav:
|
|
6
|
+
parent: "Editor Shells"
|
|
7
|
+
priority: 20
|
|
8
|
+
api:
|
|
9
|
+
attributes:
|
|
10
|
+
- name: canvas
|
|
11
|
+
type: string
|
|
12
|
+
description: Canvas element ID or selector to bind to
|
|
13
|
+
properties:
|
|
14
|
+
- name: activeRootTemporal
|
|
15
|
+
type: "TemporalMixinInterface & HTMLElement | null"
|
|
16
|
+
description: Currently active root temporal element
|
|
17
|
+
react:
|
|
18
|
+
generate: true
|
|
19
|
+
componentName: ActiveRootTemporal
|
|
20
|
+
importPath: "@editframe/react"
|
|
21
|
+
additionalProps:
|
|
22
|
+
- name: className
|
|
23
|
+
type: string
|
|
24
|
+
description: CSS classes for styling
|
|
25
|
+
- name: onRootChange
|
|
26
|
+
type: "(event: CustomEvent) => void"
|
|
27
|
+
description: Callback fired when active root temporal changes
|
|
28
|
+
nav:
|
|
29
|
+
parent: "Components / Editor UI"
|
|
30
|
+
priority: 62
|
|
31
|
+
related: ["hierarchy", "canvas", "timeline-root"]
|
|
32
|
+
status: not-yet-exported
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
<!-- html-only -->
|
|
36
|
+
# ef-active-root-temporal
|
|
37
|
+
<!-- /html-only -->
|
|
38
|
+
<!-- react-only -->
|
|
39
|
+
# ActiveRootTemporal
|
|
40
|
+
<!-- /react-only -->
|
|
41
|
+
|
|
42
|
+
Displays the ID of the active root temporal element from a canvas.
|
|
43
|
+
|
|
44
|
+
<!-- react-only -->
|
|
45
|
+
> **Note**: The ActiveRootTemporal component is currently not exported from `@editframe/react`. This documentation describes the underlying `ef-active-root-temporal` HTML element. To use it in React, you'll need to use the HTML element directly or wait for official React component export.
|
|
46
|
+
|
|
47
|
+
## Import
|
|
48
|
+
|
|
49
|
+
When officially exported, usage will be:
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { ActiveRootTemporal } from "@editframe/react";
|
|
53
|
+
```
|
|
54
|
+
<!-- /react-only -->
|
|
55
|
+
|
|
56
|
+
## Basic Usage
|
|
57
|
+
|
|
58
|
+
<!-- html-only -->
|
|
59
|
+
Show the active root temporal ID:
|
|
60
|
+
|
|
61
|
+
```html
|
|
62
|
+
<ef-active-root-temporal canvas="my-canvas">None</ef-active-root-temporal>
|
|
63
|
+
|
|
64
|
+
<ef-canvas id="my-canvas">
|
|
65
|
+
<ef-timegroup id="scene-1">
|
|
66
|
+
<!-- Content -->
|
|
67
|
+
</ef-timegroup>
|
|
68
|
+
<ef-timegroup id="scene-2">
|
|
69
|
+
<!-- Content -->
|
|
70
|
+
</ef-timegroup>
|
|
71
|
+
</ef-canvas>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
When you select an element in the canvas, the active root temporal ID displays.
|
|
75
|
+
<!-- /html-only -->
|
|
76
|
+
<!-- react-only -->
|
|
77
|
+
```tsx
|
|
78
|
+
export const App = () => {
|
|
79
|
+
return (
|
|
80
|
+
<div className="h-screen flex flex-col">
|
|
81
|
+
{/* Header showing active timegroup */}
|
|
82
|
+
<div className="p-4 bg-gray-800 text-white">
|
|
83
|
+
<span className="mr-2">Active Timegroup:</span>
|
|
84
|
+
<ef-active-root-temporal canvas="editor-canvas" />
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
{/* Canvas */}
|
|
88
|
+
<div className="flex-1">
|
|
89
|
+
<ef-canvas id="editor-canvas">
|
|
90
|
+
<ef-timegroup id="root-tg" mode="sequence" className="w-[1920px] h-[1080px]">
|
|
91
|
+
<ef-video src="/assets/video.mp4" />
|
|
92
|
+
</ef-timegroup>
|
|
93
|
+
</ef-canvas>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
```
|
|
99
|
+
<!-- /react-only -->
|
|
100
|
+
|
|
101
|
+
## Canvas Binding
|
|
102
|
+
|
|
103
|
+
<!-- html-only -->
|
|
104
|
+
Bind to a canvas by ID or selector:
|
|
105
|
+
|
|
106
|
+
### By ID
|
|
107
|
+
|
|
108
|
+
```html
|
|
109
|
+
<ef-active-root-temporal canvas="my-canvas"></ef-active-root-temporal>
|
|
110
|
+
<ef-canvas id="my-canvas"></ef-canvas>
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### By Selector
|
|
114
|
+
|
|
115
|
+
```html
|
|
116
|
+
<ef-active-root-temporal canvas=".editor-canvas"></ef-active-root-temporal>
|
|
117
|
+
<ef-canvas class="editor-canvas"></ef-canvas>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Nearest Ancestor
|
|
121
|
+
|
|
122
|
+
Omit canvas attribute to use nearest ancestor:
|
|
123
|
+
|
|
124
|
+
```html
|
|
125
|
+
<ef-canvas>
|
|
126
|
+
<ef-active-root-temporal></ef-active-root-temporal>
|
|
127
|
+
</ef-canvas>
|
|
128
|
+
```
|
|
129
|
+
<!-- /html-only -->
|
|
130
|
+
<!-- react-only -->
|
|
131
|
+
### Auto-Detection
|
|
132
|
+
|
|
133
|
+
```tsx
|
|
134
|
+
export const AutoDetect = () => {
|
|
135
|
+
return (
|
|
136
|
+
<div>
|
|
137
|
+
{/* Will find nearest ef-canvas ancestor */}
|
|
138
|
+
<ef-canvas>
|
|
139
|
+
<div className="p-2 bg-gray-100">
|
|
140
|
+
<span>Current Root: </span>
|
|
141
|
+
<ef-active-root-temporal />
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<ef-timegroup id="auto-detected-root" mode="sequence">
|
|
145
|
+
<ef-video src="/assets/video.mp4" />
|
|
146
|
+
</ef-timegroup>
|
|
147
|
+
</ef-canvas>
|
|
148
|
+
</div>
|
|
149
|
+
);
|
|
150
|
+
};
|
|
151
|
+
```
|
|
152
|
+
<!-- /react-only -->
|
|
153
|
+
|
|
154
|
+
## Active Root Temporal
|
|
155
|
+
|
|
156
|
+
The active root temporal is the topmost timegroup containing the selected element:
|
|
157
|
+
|
|
158
|
+
```html
|
|
159
|
+
<ef-canvas id="canvas">
|
|
160
|
+
<ef-timegroup id="root-1">
|
|
161
|
+
<ef-timegroup id="child-1">
|
|
162
|
+
<div id="element-1">Content</div>
|
|
163
|
+
</ef-timegroup>
|
|
164
|
+
</ef-timegroup>
|
|
165
|
+
</ef-canvas>
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
When `element-1` is selected, active root temporal is `root-1`.
|
|
169
|
+
|
|
170
|
+
## Display Content
|
|
171
|
+
|
|
172
|
+
<!-- html-only -->
|
|
173
|
+
### Default Content
|
|
174
|
+
|
|
175
|
+
Show ID of active root temporal:
|
|
176
|
+
|
|
177
|
+
```html
|
|
178
|
+
<ef-active-root-temporal canvas="canvas"></ef-active-root-temporal>
|
|
179
|
+
<!-- Displays: "root-1" when root-1 is active -->
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Fallback Content
|
|
183
|
+
|
|
184
|
+
Provide fallback text for when no root is active:
|
|
185
|
+
|
|
186
|
+
```html
|
|
187
|
+
<ef-active-root-temporal canvas="canvas">
|
|
188
|
+
No selection
|
|
189
|
+
</ef-active-root-temporal>
|
|
190
|
+
<!-- Displays: "No selection" when nothing is selected -->
|
|
191
|
+
```
|
|
192
|
+
<!-- /html-only -->
|
|
193
|
+
<!-- react-only -->
|
|
194
|
+
### With Hierarchy
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
export const EditorLayout = () => {
|
|
198
|
+
return (
|
|
199
|
+
<div className="h-screen flex flex-col">
|
|
200
|
+
{/* Top bar with active root display */}
|
|
201
|
+
<div className="p-2 bg-gray-800 text-white flex items-center gap-4">
|
|
202
|
+
<span className="text-sm">Active Root:</span>
|
|
203
|
+
<ef-active-root-temporal
|
|
204
|
+
canvas="canvas"
|
|
205
|
+
className="font-mono text-sm bg-gray-700 px-2 py-1 rounded"
|
|
206
|
+
/>
|
|
207
|
+
</div>
|
|
208
|
+
|
|
209
|
+
{/* Main editor area */}
|
|
210
|
+
<div className="flex-1 flex">
|
|
211
|
+
<div className="w-64 border-r bg-gray-50">
|
|
212
|
+
<ef-hierarchy target="canvas" />
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
<div className="flex-1">
|
|
216
|
+
<ef-canvas id="canvas">
|
|
217
|
+
<ef-timegroup id="scene-1" mode="contain" className="w-[1920px] h-[1080px]">
|
|
218
|
+
<ef-video src="/assets/video.mp4" />
|
|
219
|
+
</ef-timegroup>
|
|
220
|
+
</ef-canvas>
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
);
|
|
225
|
+
};
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### Styled Display
|
|
229
|
+
|
|
230
|
+
```tsx
|
|
231
|
+
export const StyledDisplay = () => {
|
|
232
|
+
return (
|
|
233
|
+
<div className="flex items-center gap-2 p-4 bg-gray-900 text-white">
|
|
234
|
+
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
|
|
235
|
+
<path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" />
|
|
236
|
+
</svg>
|
|
237
|
+
<span className="text-sm text-gray-400">Active Scene:</span>
|
|
238
|
+
<ef-active-root-temporal
|
|
239
|
+
canvas="canvas"
|
|
240
|
+
className="text-sm font-mono bg-gray-800 px-3 py-1 rounded border border-gray-700"
|
|
241
|
+
/>
|
|
242
|
+
</div>
|
|
243
|
+
);
|
|
244
|
+
};
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Breadcrumb Navigation
|
|
248
|
+
|
|
249
|
+
```tsx
|
|
250
|
+
export const BreadcrumbNav = () => {
|
|
251
|
+
return (
|
|
252
|
+
<div className="flex items-center gap-2 p-2 bg-white border-b text-sm">
|
|
253
|
+
<span className="text-gray-500">Project</span>
|
|
254
|
+
<span className="text-gray-400">/</span>
|
|
255
|
+
<span className="text-gray-500">Composition</span>
|
|
256
|
+
<span className="text-gray-400">/</span>
|
|
257
|
+
<ef-active-root-temporal
|
|
258
|
+
canvas="canvas"
|
|
259
|
+
className="font-medium text-blue-600"
|
|
260
|
+
/>
|
|
261
|
+
</div>
|
|
262
|
+
);
|
|
263
|
+
};
|
|
264
|
+
```
|
|
265
|
+
<!-- /react-only -->
|
|
266
|
+
|
|
267
|
+
## Events
|
|
268
|
+
|
|
269
|
+
<!-- html-only -->
|
|
270
|
+
Listen for changes:
|
|
271
|
+
|
|
272
|
+
```javascript
|
|
273
|
+
const canvas = document.querySelector('ef-canvas');
|
|
274
|
+
|
|
275
|
+
canvas.addEventListener('activeroottemporalchange', (e) => {
|
|
276
|
+
const { activeRootTemporal } = e.detail;
|
|
277
|
+
console.log('Active root:', activeRootTemporal?.id);
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
The canvas fires this event, not ef-active-root-temporal.
|
|
282
|
+
<!-- /html-only -->
|
|
283
|
+
<!-- react-only -->
|
|
284
|
+
The canvas fires `activeroottemporalchange` when the active root changes:
|
|
285
|
+
|
|
286
|
+
```typescript
|
|
287
|
+
interface ActiveRootTemporalChangeDetail {
|
|
288
|
+
id: string | null;
|
|
289
|
+
element: HTMLElement | null;
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
Listen to this event to track changes:
|
|
294
|
+
|
|
295
|
+
```tsx
|
|
296
|
+
useEffect(() => {
|
|
297
|
+
const canvas = document.getElementById("canvas");
|
|
298
|
+
if (!canvas) return;
|
|
299
|
+
|
|
300
|
+
const handleChange = (e: CustomEvent) => {
|
|
301
|
+
console.log("New active root:", e.detail.id);
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
canvas.addEventListener("activeroottemporalchange", handleChange);
|
|
305
|
+
return () => {
|
|
306
|
+
canvas.removeEventListener("activeroottemporalchange", handleChange);
|
|
307
|
+
};
|
|
308
|
+
}, []);
|
|
309
|
+
```
|
|
310
|
+
<!-- /react-only -->
|
|
311
|
+
|
|
312
|
+
## Use Cases
|
|
313
|
+
|
|
314
|
+
<!-- html-only -->
|
|
315
|
+
### Timeline Scrubbing
|
|
316
|
+
|
|
317
|
+
Use active root temporal to determine which timeline to scrub:
|
|
318
|
+
|
|
319
|
+
```javascript
|
|
320
|
+
const activeRootDisplay = document.querySelector('ef-active-root-temporal');
|
|
321
|
+
const canvas = document.querySelector('ef-canvas');
|
|
322
|
+
|
|
323
|
+
canvas.addEventListener('activeroottemporalchange', (e) => {
|
|
324
|
+
const rootTemporal = e.detail.activeRootTemporal;
|
|
325
|
+
|
|
326
|
+
if (rootTemporal) {
|
|
327
|
+
// Update scrubber to control this timegroup
|
|
328
|
+
scrubber.target = rootTemporal.id;
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Playback Controls
|
|
334
|
+
|
|
335
|
+
Connect playback controls to active root:
|
|
336
|
+
|
|
337
|
+
```javascript
|
|
338
|
+
const canvas = document.querySelector('ef-canvas');
|
|
339
|
+
const controls = document.querySelector('ef-controls');
|
|
340
|
+
|
|
341
|
+
canvas.addEventListener('activeroottemporalchange', (e) => {
|
|
342
|
+
if (e.detail.activeRootTemporal) {
|
|
343
|
+
controls.target = e.detail.activeRootTemporal.id;
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Context Display
|
|
349
|
+
|
|
350
|
+
Show which composition is active:
|
|
351
|
+
|
|
352
|
+
```html
|
|
353
|
+
<div class="toolbar">
|
|
354
|
+
<span class="label">Active Composition:</span>
|
|
355
|
+
<ef-active-root-temporal canvas="canvas" class="font-mono">
|
|
356
|
+
None
|
|
357
|
+
</ef-active-root-temporal>
|
|
358
|
+
</div>
|
|
359
|
+
```
|
|
360
|
+
<!-- /html-only -->
|
|
361
|
+
<!-- react-only -->
|
|
362
|
+
- **Editor breadcrumbs**: Show current timegroup in navigation
|
|
363
|
+
- **Scene indicator**: Display active scene in multi-scene compositions
|
|
364
|
+
- **Context display**: Show editing context to users
|
|
365
|
+
- **Debug info**: Display active root for development
|
|
366
|
+
- **Status bar**: Show current focus in status/toolbar
|
|
367
|
+
<!-- /react-only -->
|
|
368
|
+
|
|
369
|
+
## Multiple Canvases
|
|
370
|
+
|
|
371
|
+
<!-- html-only -->
|
|
372
|
+
Use separate instances for multiple canvases:
|
|
373
|
+
|
|
374
|
+
```html
|
|
375
|
+
<ef-active-root-temporal canvas="canvas-1">None</ef-active-root-temporal>
|
|
376
|
+
<ef-canvas id="canvas-1"></ef-canvas>
|
|
377
|
+
|
|
378
|
+
<ef-active-root-temporal canvas="canvas-2">None</ef-active-root-temporal>
|
|
379
|
+
<ef-canvas id="canvas-2"></ef-canvas>
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
Each instance tracks its own canvas independently.
|
|
383
|
+
<!-- /html-only -->
|
|
384
|
+
<!-- react-only -->
|
|
385
|
+
```tsx
|
|
386
|
+
export const MultiCanvas = () => {
|
|
387
|
+
return (
|
|
388
|
+
<div className="grid grid-cols-2 gap-4 p-4">
|
|
389
|
+
{/* Canvas 1 */}
|
|
390
|
+
<div className="space-y-2">
|
|
391
|
+
<div className="p-2 bg-blue-100">
|
|
392
|
+
Canvas 1 Root:
|
|
393
|
+
<ef-active-root-temporal canvas="canvas-1" />
|
|
394
|
+
</div>
|
|
395
|
+
<ef-canvas id="canvas-1">
|
|
396
|
+
<ef-timegroup id="canvas-1-root" mode="contain">
|
|
397
|
+
<ef-video src="/assets/video1.mp4" />
|
|
398
|
+
</ef-timegroup>
|
|
399
|
+
</ef-canvas>
|
|
400
|
+
</div>
|
|
401
|
+
|
|
402
|
+
{/* Canvas 2 */}
|
|
403
|
+
<div className="space-y-2">
|
|
404
|
+
<div className="p-2 bg-green-100">
|
|
405
|
+
Canvas 2 Root:
|
|
406
|
+
<ef-active-root-temporal canvas="canvas-2" />
|
|
407
|
+
</div>
|
|
408
|
+
<ef-canvas id="canvas-2">
|
|
409
|
+
<ef-timegroup id="canvas-2-root" mode="contain">
|
|
410
|
+
<ef-video src="/assets/video2.mp4" />
|
|
411
|
+
</ef-timegroup>
|
|
412
|
+
</ef-canvas>
|
|
413
|
+
</div>
|
|
414
|
+
</div>
|
|
415
|
+
);
|
|
416
|
+
};
|
|
417
|
+
```
|
|
418
|
+
<!-- /react-only -->
|
|
419
|
+
|
|
420
|
+
## Selection Behavior
|
|
421
|
+
|
|
422
|
+
Active root temporal updates when:
|
|
423
|
+
|
|
424
|
+
- Element is selected in canvas
|
|
425
|
+
- Selection changes to different element
|
|
426
|
+
- Selection is cleared
|
|
427
|
+
|
|
428
|
+
Selection of nested elements always resolves to their root temporal ancestor.
|
|
429
|
+
|
|
430
|
+
## Finding Root Temporal
|
|
431
|
+
|
|
432
|
+
The canvas walks up the DOM tree from selected element to find the topmost timegroup:
|
|
433
|
+
|
|
434
|
+
```javascript
|
|
435
|
+
// Simplified algorithm
|
|
436
|
+
let current = selectedElement;
|
|
437
|
+
let rootTemporal = null;
|
|
438
|
+
|
|
439
|
+
while (current && current !== canvas) {
|
|
440
|
+
if (current.tagName === 'EF-TIMEGROUP') {
|
|
441
|
+
rootTemporal = current;
|
|
442
|
+
}
|
|
443
|
+
current = current.parentElement;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
return rootTemporal;
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
<!-- html-only -->
|
|
450
|
+
## Null State
|
|
451
|
+
|
|
452
|
+
When no element is selected or selected element has no root temporal ancestor:
|
|
453
|
+
|
|
454
|
+
```javascript
|
|
455
|
+
const display = document.querySelector('ef-active-root-temporal');
|
|
456
|
+
console.log(display.activeRootTemporal); // null
|
|
457
|
+
|
|
458
|
+
// Text content shows fallback
|
|
459
|
+
console.log(display.textContent); // "None" (from slot content)
|
|
460
|
+
```
|
|
461
|
+
<!-- /html-only -->
|
|
462
|
+
|
|
463
|
+
## Temporal Mixin Interface
|
|
464
|
+
|
|
465
|
+
Active root temporal is typed as `TemporalMixinInterface`:
|
|
466
|
+
|
|
467
|
+
```typescript
|
|
468
|
+
interface TemporalMixinInterface {
|
|
469
|
+
id: string;
|
|
470
|
+
durationMs: number;
|
|
471
|
+
currentTimeMs: number;
|
|
472
|
+
play(): void;
|
|
473
|
+
pause(): void;
|
|
474
|
+
// ... other temporal properties and methods
|
|
475
|
+
}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
This ensures the element has timing capabilities.
|
|
479
|
+
|
|
480
|
+
<!-- html-only -->
|
|
481
|
+
## Canvas Property
|
|
482
|
+
|
|
483
|
+
Access the bound canvas element:
|
|
484
|
+
|
|
485
|
+
```javascript
|
|
486
|
+
const display = document.querySelector('ef-active-root-temporal');
|
|
487
|
+
|
|
488
|
+
// Canvas element reference (internal)
|
|
489
|
+
console.log(display.canvasElement); // EFCanvas instance
|
|
490
|
+
```
|
|
491
|
+
<!-- /html-only -->
|
|
492
|
+
|
|
493
|
+
<!-- react-only -->
|
|
494
|
+
## With Selection Context
|
|
495
|
+
|
|
496
|
+
```tsx
|
|
497
|
+
export const SelectionAware = () => {
|
|
498
|
+
const [activeRoot, setActiveRoot] = useState<string | null>(null);
|
|
499
|
+
|
|
500
|
+
useEffect(() => {
|
|
501
|
+
const canvas = document.getElementById("canvas");
|
|
502
|
+
if (!canvas) return;
|
|
503
|
+
|
|
504
|
+
const handleRootChange = (e: CustomEvent) => {
|
|
505
|
+
setActiveRoot(e.detail?.id || null);
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
canvas.addEventListener("activeroottemporalchange" as any, handleRootChange);
|
|
509
|
+
return () => {
|
|
510
|
+
canvas.removeEventListener("activeroottemporalchange" as any, handleRootChange);
|
|
511
|
+
};
|
|
512
|
+
}, []);
|
|
513
|
+
|
|
514
|
+
return (
|
|
515
|
+
<div className="space-y-4">
|
|
516
|
+
<div className="p-4 bg-gray-100">
|
|
517
|
+
<div className="text-sm text-gray-600">Active Root ID:</div>
|
|
518
|
+
<div className="font-mono">{activeRoot || "None"}</div>
|
|
519
|
+
</div>
|
|
520
|
+
|
|
521
|
+
<ef-canvas id="canvas">
|
|
522
|
+
<ef-timegroup id="main-sequence" mode="sequence">
|
|
523
|
+
<ef-timegroup id="scene-1" mode="contain">
|
|
524
|
+
<ef-video src="/assets/video1.mp4" />
|
|
525
|
+
</ef-timegroup>
|
|
526
|
+
<ef-timegroup id="scene-2" mode="contain">
|
|
527
|
+
<ef-video src="/assets/video2.mp4" />
|
|
528
|
+
</ef-timegroup>
|
|
529
|
+
</ef-timegroup>
|
|
530
|
+
</ef-canvas>
|
|
531
|
+
</div>
|
|
532
|
+
);
|
|
533
|
+
};
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
## Dynamic Root Display
|
|
537
|
+
|
|
538
|
+
```tsx
|
|
539
|
+
export const DynamicRootDisplay = () => {
|
|
540
|
+
const canvasRef = useRef<any>(null);
|
|
541
|
+
|
|
542
|
+
const selectRoot = (rootId: string) => {
|
|
543
|
+
if (canvasRef.current) {
|
|
544
|
+
canvasRef.current.selectElement(rootId);
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
|
|
548
|
+
return (
|
|
549
|
+
<div className="space-y-4">
|
|
550
|
+
{/* Root selector */}
|
|
551
|
+
<div className="p-4 bg-gray-100 space-x-2">
|
|
552
|
+
<button
|
|
553
|
+
onClick={() => selectRoot("scene-1")}
|
|
554
|
+
className="px-3 py-1 bg-blue-500 text-white rounded"
|
|
555
|
+
>
|
|
556
|
+
Scene 1
|
|
557
|
+
</button>
|
|
558
|
+
<button
|
|
559
|
+
onClick={() => selectRoot("scene-2")}
|
|
560
|
+
className="px-3 py-1 bg-blue-500 text-white rounded"
|
|
561
|
+
>
|
|
562
|
+
Scene 2
|
|
563
|
+
</button>
|
|
564
|
+
</div>
|
|
565
|
+
|
|
566
|
+
{/* Active root display */}
|
|
567
|
+
<div className="p-4 bg-white border rounded">
|
|
568
|
+
<span className="text-gray-600">Current: </span>
|
|
569
|
+
<ef-active-root-temporal canvas="canvas" className="font-semibold" />
|
|
570
|
+
</div>
|
|
571
|
+
|
|
572
|
+
{/* Canvas */}
|
|
573
|
+
<ef-canvas ref={canvasRef} id="canvas">
|
|
574
|
+
<ef-timegroup id="scene-1" mode="contain">
|
|
575
|
+
<ef-video src="/assets/video1.mp4" />
|
|
576
|
+
</ef-timegroup>
|
|
577
|
+
<ef-timegroup id="scene-2" mode="contain">
|
|
578
|
+
<ef-video src="/assets/video2.mp4" />
|
|
579
|
+
</ef-timegroup>
|
|
580
|
+
</ef-canvas>
|
|
581
|
+
</div>
|
|
582
|
+
);
|
|
583
|
+
};
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
## Future React Component
|
|
587
|
+
|
|
588
|
+
When officially exported, usage will be:
|
|
589
|
+
|
|
590
|
+
```tsx
|
|
591
|
+
import { ActiveRootTemporal } from "@editframe/react";
|
|
592
|
+
|
|
593
|
+
<ActiveRootTemporal
|
|
594
|
+
canvas="canvas-id"
|
|
595
|
+
className="font-mono"
|
|
596
|
+
onRootChange={(e) => console.log(e.detail)}
|
|
597
|
+
/>
|
|
598
|
+
```
|
|
599
|
+
<!-- /react-only -->
|
|
600
|
+
|
|
601
|
+
## Styling
|
|
602
|
+
|
|
603
|
+
Style the display element:
|
|
604
|
+
|
|
605
|
+
```css
|
|
606
|
+
ef-active-root-temporal {
|
|
607
|
+
display: inline-block;
|
|
608
|
+
font-family: monospace;
|
|
609
|
+
padding: 4px 8px;
|
|
610
|
+
background: #f5f5f5;
|
|
611
|
+
border: 1px solid #ddd;
|
|
612
|
+
border-radius: 4px;
|
|
613
|
+
}
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
## Reactive Updates
|
|
617
|
+
|
|
618
|
+
Display automatically updates when selection changes. No manual refresh needed.
|
|
619
|
+
|
|
620
|
+
<!-- html-only -->
|
|
621
|
+
## Disconnection
|
|
622
|
+
|
|
623
|
+
When disconnected, the element:
|
|
624
|
+
|
|
625
|
+
- Removes event listener from canvas
|
|
626
|
+
- Clears active root temporal reference
|
|
627
|
+
- Cleans up internal state
|
|
628
|
+
|
|
629
|
+
## Initialization
|
|
630
|
+
|
|
631
|
+
On connection, the element:
|
|
632
|
+
|
|
633
|
+
1. Finds canvas (by attribute, selector, or ancestor)
|
|
634
|
+
2. Reads initial active root temporal
|
|
635
|
+
3. Sets up event listener
|
|
636
|
+
4. Updates display
|
|
637
|
+
<!-- /html-only -->
|
|
638
|
+
|
|
639
|
+
## Important Notes
|
|
640
|
+
|
|
641
|
+
<!-- html-only -->
|
|
642
|
+
- Canvas attribute can be ID or CSS selector
|
|
643
|
+
- Falls back to nearest ancestor canvas if not specified
|
|
644
|
+
- Only displays root temporal elements (top-level timegroups)
|
|
645
|
+
- Updates automatically - no manual refresh needed
|
|
646
|
+
- Shows element ID, not a friendly name
|
|
647
|
+
- Returns null when no root temporal is active
|
|
648
|
+
<!-- /html-only -->
|
|
649
|
+
<!-- react-only -->
|
|
650
|
+
- Currently not exported from React package - use HTML element
|
|
651
|
+
- Canvas attribute can be ID or CSS selector
|
|
652
|
+
- Falls back to nearest ancestor canvas if not specified
|
|
653
|
+
- Only displays root temporal elements (top-level timegroups)
|
|
654
|
+
- Updates automatically - no manual refresh needed
|
|
655
|
+
- Shows element ID, not a friendly name
|
|
656
|
+
- Returns empty string when no root temporal is active
|
|
657
|
+
<!-- /react-only -->
|