@editframe/create 0.44.0 → 0.45.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.
Files changed (98) hide show
  1. package/dist/index.js +16 -28
  2. package/dist/index.js.map +1 -1
  3. package/dist/skills/editframe-brand-video-generator/README.md +155 -0
  4. package/dist/skills/editframe-brand-video-generator/SKILL.md +207 -0
  5. package/dist/skills/editframe-brand-video-generator/references/brand-examples.md +178 -0
  6. package/dist/skills/editframe-brand-video-generator/references/color-psychology.md +227 -0
  7. package/dist/skills/editframe-brand-video-generator/references/composition-patterns.md +383 -0
  8. package/dist/skills/editframe-brand-video-generator/references/editing.md +66 -0
  9. package/dist/skills/editframe-brand-video-generator/references/emotional-arcs.md +496 -0
  10. package/dist/skills/editframe-brand-video-generator/references/genre-selection.md +135 -0
  11. package/dist/skills/editframe-brand-video-generator/references/transition-styles.md +611 -0
  12. package/dist/skills/editframe-brand-video-generator/references/typography-personalities.md +326 -0
  13. package/dist/skills/editframe-brand-video-generator/references/video-archetypes.md +86 -0
  14. package/dist/skills/editframe-brand-video-generator/references/video-fundamentals.md +169 -0
  15. package/dist/skills/editframe-brand-video-generator/references/visual-metaphors.md +50 -0
  16. package/dist/skills/editframe-composition/SKILL.md +169 -0
  17. package/dist/skills/editframe-composition/references/audio.md +483 -0
  18. package/dist/skills/editframe-composition/references/captions.md +844 -0
  19. package/dist/skills/editframe-composition/references/composition-model.md +73 -0
  20. package/dist/skills/editframe-composition/references/configuration.md +403 -0
  21. package/dist/skills/editframe-composition/references/css-parts.md +105 -0
  22. package/dist/skills/editframe-composition/references/css-variables.md +640 -0
  23. package/dist/skills/editframe-composition/references/entry-points.md +810 -0
  24. package/dist/skills/editframe-composition/references/events.md +499 -0
  25. package/dist/skills/editframe-composition/references/getting-started.md +259 -0
  26. package/dist/skills/editframe-composition/references/hooks.md +234 -0
  27. package/dist/skills/editframe-composition/references/image.md +241 -0
  28. package/dist/skills/editframe-composition/references/r3f.md +580 -0
  29. package/dist/skills/editframe-composition/references/render-api.md +484 -0
  30. package/dist/skills/editframe-composition/references/render-strategies.md +119 -0
  31. package/dist/skills/editframe-composition/references/render-to-video.md +1101 -0
  32. package/dist/skills/editframe-composition/references/scripting.md +606 -0
  33. package/dist/skills/editframe-composition/references/sequencing.md +116 -0
  34. package/dist/skills/editframe-composition/references/server-rendering.md +753 -0
  35. package/dist/skills/editframe-composition/references/surface.md +329 -0
  36. package/dist/skills/editframe-composition/references/text.md +627 -0
  37. package/dist/skills/editframe-composition/references/time-model.md +99 -0
  38. package/dist/skills/editframe-composition/references/timegroup-modes.md +102 -0
  39. package/dist/skills/editframe-composition/references/timegroup.md +457 -0
  40. package/dist/skills/editframe-composition/references/timeline-root.md +398 -0
  41. package/dist/skills/editframe-composition/references/transcription.md +47 -0
  42. package/dist/skills/editframe-composition/references/transitions.md +608 -0
  43. package/dist/skills/editframe-composition/references/use-media-info.md +357 -0
  44. package/dist/skills/editframe-composition/references/video.md +506 -0
  45. package/dist/skills/editframe-composition/references/waveform.md +327 -0
  46. package/dist/skills/editframe-editor-gui/SKILL.md +152 -0
  47. package/dist/skills/editframe-editor-gui/references/active-root-temporal.md +657 -0
  48. package/dist/skills/editframe-editor-gui/references/canvas.md +947 -0
  49. package/dist/skills/editframe-editor-gui/references/controls.md +366 -0
  50. package/dist/skills/editframe-editor-gui/references/dial.md +756 -0
  51. package/dist/skills/editframe-editor-gui/references/editor-toolkit.md +587 -0
  52. package/dist/skills/editframe-editor-gui/references/filmstrip.md +460 -0
  53. package/dist/skills/editframe-editor-gui/references/fit-scale.md +772 -0
  54. package/dist/skills/editframe-editor-gui/references/focus-overlay.md +561 -0
  55. package/dist/skills/editframe-editor-gui/references/hierarchy.md +544 -0
  56. package/dist/skills/editframe-editor-gui/references/overlay-item.md +634 -0
  57. package/dist/skills/editframe-editor-gui/references/overlay-layer.md +429 -0
  58. package/dist/skills/editframe-editor-gui/references/pan-zoom.md +568 -0
  59. package/dist/skills/editframe-editor-gui/references/pause.md +397 -0
  60. package/dist/skills/editframe-editor-gui/references/play.md +370 -0
  61. package/dist/skills/editframe-editor-gui/references/preview.md +391 -0
  62. package/dist/skills/editframe-editor-gui/references/resizable-box.md +749 -0
  63. package/dist/skills/editframe-editor-gui/references/scrubber.md +588 -0
  64. package/dist/skills/editframe-editor-gui/references/thumbnail-strip.md +566 -0
  65. package/dist/skills/editframe-editor-gui/references/time-display.md +492 -0
  66. package/dist/skills/editframe-editor-gui/references/timeline-ruler.md +489 -0
  67. package/dist/skills/editframe-editor-gui/references/timeline.md +604 -0
  68. package/dist/skills/editframe-editor-gui/references/toggle-loop.md +618 -0
  69. package/dist/skills/editframe-editor-gui/references/toggle-play.md +526 -0
  70. package/dist/skills/editframe-editor-gui/references/transform-handles.md +924 -0
  71. package/dist/skills/editframe-editor-gui/references/trim-handles.md +725 -0
  72. package/dist/skills/editframe-editor-gui/references/workbench.md +453 -0
  73. package/dist/skills/editframe-motion-design/SKILL.md +101 -0
  74. package/dist/skills/editframe-motion-design/references/0-editframe.md +299 -0
  75. package/dist/skills/editframe-motion-design/references/1-intent.md +201 -0
  76. package/dist/skills/editframe-motion-design/references/2-physics-model.md +405 -0
  77. package/dist/skills/editframe-motion-design/references/3-attention.md +350 -0
  78. package/dist/skills/editframe-motion-design/references/4-process.md +418 -0
  79. package/dist/skills/editframe-vite-plugin/SKILL.md +75 -0
  80. package/dist/skills/editframe-vite-plugin/references/file-api.md +111 -0
  81. package/dist/skills/editframe-vite-plugin/references/getting-started.md +96 -0
  82. package/dist/skills/editframe-vite-plugin/references/jit-transcoding.md +91 -0
  83. package/dist/skills/editframe-vite-plugin/references/local-assets.md +75 -0
  84. package/dist/skills/editframe-vite-plugin/references/visual-testing.md +136 -0
  85. package/dist/skills/editframe-webhooks/SKILL.md +126 -0
  86. package/dist/skills/editframe-webhooks/references/events.md +382 -0
  87. package/dist/skills/editframe-webhooks/references/getting-started.md +232 -0
  88. package/dist/skills/editframe-webhooks/references/security.md +418 -0
  89. package/dist/skills/editframe-webhooks/references/testing.md +409 -0
  90. package/dist/skills/editframe-webhooks/references/troubleshooting.md +457 -0
  91. package/dist/templates/html/AGENTS.md +13 -0
  92. package/dist/templates/react/AGENTS.md +13 -0
  93. package/dist/utils.js +15 -16
  94. package/dist/utils.js.map +1 -1
  95. package/package.json +1 -1
  96. package/tsdown.config.ts +4 -0
  97. package/dist/detectAgent.js +0 -89
  98. package/dist/detectAgent.js.map +0 -1
@@ -0,0 +1,947 @@
1
+ ---
2
+ title: Canvas Elements
3
+ description: Interactive canvas area with element selection, drag-and-drop repositioning, and transform handle integration.
4
+ type: reference
5
+ nav:
6
+ parent: "Preview & Canvas"
7
+ priority: 11
8
+ api:
9
+ attributes:
10
+ - name: data-element-id-attribute
11
+ type: string
12
+ default: "data-element-id"
13
+ description: Attribute name for element identification
14
+ - name: enable-transform-handles
15
+ type: boolean
16
+ default: true
17
+ description: Show transform handles for selected elements
18
+ methods:
19
+ - name: registerElement(element, id)
20
+ signature: "registerElement(element: HTMLElement, id?: string): string"
21
+ description: Register an element for canvas management
22
+ returns: Element ID
23
+ - name: unregisterElement(element)
24
+ signature: "unregisterElement(element: HTMLElement | string): void"
25
+ description: Unregister an element
26
+ - name: tryRegisterElement(element)
27
+ signature: "tryRegisterElement(element: HTMLElement): void"
28
+ description: Try to register element, auto-generating ID if needed
29
+ - name: updateElementPosition(elementId, x, y)
30
+ signature: "updateElementPosition(elementId: string, x: number, y: number): void"
31
+ description: Update element position in canvas coordinates
32
+ - name: getElementData(elementId)
33
+ signature: "getElementData(elementId: string): CanvasElementData | null"
34
+ description: Get element metadata
35
+ returns: CanvasElementData | null
36
+ - name: getAllElementsData()
37
+ signature: "getAllElementsData(): CanvasElementData[]"
38
+ description: Get metadata for all elements
39
+ returns: CanvasElementData[]
40
+ - name: screenToCanvasCoords(screenX, screenY)
41
+ signature: "screenToCanvasCoords(screenX: number, screenY: number): { x: number, y: number }"
42
+ description: Convert screen coordinates to canvas coordinates
43
+ - name: canvasToScreenCoords(canvasX, canvasY)
44
+ signature: "canvasToScreenCoords(canvasX: number, canvasY: number): { x: number, y: number }"
45
+ description: Convert canvas coordinates to screen coordinates
46
+ - name: setHighlightedElement(element)
47
+ signature: "setHighlightedElement(element: HTMLElement | null): void"
48
+ description: Set the highlighted (hovered) element
49
+ properties:
50
+ - name: selectionContext
51
+ type: SelectionContext
52
+ description: Selection state and methods (provided via Lit context)
53
+ - name: highlightedElement
54
+ type: "HTMLElement | null"
55
+ description: Currently highlighted (hovered) element
56
+ - name: activeRootTemporal
57
+ type: "TemporalMixinInterface & HTMLElement | null"
58
+ description: Root temporal element containing current selection
59
+ events:
60
+ - name: activeroottemporalchange
61
+ detail: "{ activeRootTemporal: TemporalMixinInterface & HTMLElement | null }"
62
+ description: Fired when active root temporal changes
63
+ types:
64
+ - name: CanvasElementData
65
+ type: interface
66
+ definition: |
67
+ interface CanvasElementData {
68
+ id: string;
69
+ element: HTMLElement;
70
+ x: number; // Canvas x coordinate
71
+ y: number; // Canvas y coordinate
72
+ width: number; // Width in canvas units
73
+ height: number; // Height in canvas units
74
+ rotation?: number; // Rotation in degrees
75
+ }
76
+ - name: SelectionContext
77
+ type: interface
78
+ definition: |
79
+ interface SelectionContext extends EventTarget {
80
+ selectedIds: Set<string>;
81
+ select(id: string): void;
82
+ deselect(id: string): void;
83
+ toggle(id: string): void;
84
+ addToSelection(id: string): void;
85
+ clear(): void;
86
+ startBoxSelect(x: number, y: number): void;
87
+ updateBoxSelect(x: number, y: number): void;
88
+ endBoxSelect(hitTest: (bounds: DOMRect) => string[], additive: boolean): void;
89
+ }
90
+ react:
91
+ generate: true
92
+ componentName: Canvas
93
+ importPath: "@editframe/react"
94
+ propMapping:
95
+ data-element-id-attribute: elementIdAttribute
96
+ enable-transform-handles: enableTransformHandles
97
+ additionalProps:
98
+ - name: className
99
+ type: string
100
+ description: CSS classes for styling
101
+ - name: children
102
+ type: ReactNode
103
+ description: Canvas content elements
104
+ - name: ref
105
+ type: "Ref<HTMLElement>"
106
+ description: Ref to access underlying canvas element and methods
107
+ nav:
108
+ parent: "Components / Editor UI"
109
+ priority: 61
110
+ related: ["hierarchy", "overlay-layer", "transform-handles"]
111
+ ---
112
+
113
+ <!-- html-only -->
114
+ # ef-canvas
115
+ <!-- /html-only -->
116
+ <!-- react-only -->
117
+ # Canvas / CanvasItem
118
+ <!-- /react-only -->
119
+
120
+ Interactive canvas for managing, selecting, and manipulating elements with drag-and-drop and transform handles.
121
+
122
+ <!-- react-only -->
123
+ > **Note**: Canvas and CanvasItem components are currently not exported from `@editframe/react`. This documentation describes the underlying `ef-canvas` and `ef-canvas-item` HTML elements. To use them in React, you'll need to use the HTML elements directly or wait for official React component export.
124
+ <!-- /react-only -->
125
+
126
+ ## Basic Usage
127
+
128
+ <!-- html-only -->
129
+ Canvas automatically manages any child elements:
130
+
131
+ ```html live
132
+ <div class="relative w-full h-[400px] border border-gray-300 rounded overflow-hidden">
133
+ <ef-pan-zoom class="w-full h-full">
134
+ <ef-canvas class="w-[1200px] h-[800px] bg-gray-100">
135
+ <div id="box-1" class="absolute top-8 left-8 w-32 h-32 bg-blue-500 text-white flex items-center justify-center rounded">
136
+ Box 1
137
+ </div>
138
+ <div id="box-2" class="absolute top-48 left-48 w-32 h-32 bg-green-500 text-white flex items-center justify-center rounded">
139
+ Box 2
140
+ </div>
141
+ <div id="box-3" class="absolute top-8 left-48 w-32 h-32 bg-red-500 text-white flex items-center justify-center rounded">
142
+ Box 3
143
+ </div>
144
+ </ef-canvas>
145
+ </ef-pan-zoom>
146
+ </div>
147
+ ```
148
+
149
+ Click to select, drag to move, use handles to resize and rotate.
150
+ <!-- /html-only -->
151
+ <!-- react-only -->
152
+ ```tsx
153
+ import { useRef } from "react";
154
+
155
+ export const App = () => {
156
+ const canvasRef = useRef<HTMLElement>(null);
157
+
158
+ const handleSelect = (e: CustomEvent) => {
159
+ console.log("Selected:", e.detail);
160
+ };
161
+
162
+ return (
163
+ <div className="h-screen flex">
164
+ {/* Canvas with draggable items */}
165
+ <div className="flex-1">
166
+ <ef-canvas
167
+ ref={canvasRef as any}
168
+ onSelectionChange={handleSelect as any}
169
+ enable-transform-handles
170
+ >
171
+ <ef-timegroup mode="contain" className="w-[1920px] h-[1080px]">
172
+ <ef-canvas-item data-element-id="video-1">
173
+ <ef-video
174
+ src="/assets/video.mp4"
175
+ className="absolute"
176
+ style={{ left: "100px", top: "100px", width: "400px", height: "300px" }}
177
+ />
178
+ </ef-canvas-item>
179
+
180
+ <ef-canvas-item data-element-id="text-1">
181
+ <ef-text
182
+ duration="5s"
183
+ className="absolute text-white text-4xl"
184
+ style={{ left: "200px", top: "50px" }}
185
+ >
186
+ Draggable Text
187
+ </ef-text>
188
+ </ef-canvas-item>
189
+ </ef-timegroup>
190
+ </ef-canvas>
191
+ </div>
192
+ </div>
193
+ );
194
+ };
195
+ ```
196
+ <!-- /react-only -->
197
+
198
+ ## Selection
199
+
200
+ <!-- html-only -->
201
+ Canvas provides multiple selection modes:
202
+
203
+ ### Single Selection
204
+
205
+ Click an element to select it:
206
+
207
+ ```javascript
208
+ const canvas = document.querySelector('ef-canvas');
209
+
210
+ // Listen for selection changes
211
+ canvas.selectionContext.addEventListener('selectionchange', () => {
212
+ const selected = Array.from(canvas.selectionContext.selectedIds);
213
+ console.log('Selected:', selected);
214
+ });
215
+ ```
216
+
217
+ ### Multi-Selection
218
+
219
+ Hold **Shift** to add to selection:
220
+
221
+ - **Click**: Select single element (clear others)
222
+ - **Shift + Click**: Add element to selection
223
+ - **Ctrl/Cmd + Click**: Toggle element selection
224
+
225
+ ### Box Selection
226
+
227
+ Click and drag on empty space to select multiple elements:
228
+
229
+ ```html live
230
+ <div class="relative w-full h-[400px] border border-gray-300 rounded overflow-hidden">
231
+ <ef-pan-zoom class="w-full h-full">
232
+ <ef-canvas class="w-[1200px] h-[800px] bg-gray-100">
233
+ <div id="item-1" class="absolute top-12 left-12 w-24 h-24 bg-blue-500 rounded"></div>
234
+ <div id="item-2" class="absolute top-12 left-48 w-24 h-24 bg-green-500 rounded"></div>
235
+ <div id="item-3" class="absolute top-12 left-84 w-24 h-24 bg-red-500 rounded"></div>
236
+ <div id="item-4" class="absolute top-48 left-12 w-24 h-24 bg-purple-500 rounded"></div>
237
+ <div id="item-5" class="absolute top-48 left-48 w-24 h-24 bg-yellow-500 rounded"></div>
238
+ <div id="item-6" class="absolute top-48 left-84 w-24 h-24 bg-pink-500 rounded"></div>
239
+ </ef-canvas>
240
+ </ef-pan-zoom>
241
+ </div>
242
+ ```
243
+
244
+ Drag on empty space to draw selection box. Hold **Shift** to add to existing selection.
245
+ <!-- /html-only -->
246
+ <!-- react-only -->
247
+ ### Multi-Select
248
+
249
+ ```tsx
250
+ export const MultiSelectCanvas = () => {
251
+ const [selectedIds, setSelectedIds] = useState<string[]>([]);
252
+
253
+ useEffect(() => {
254
+ const canvas = document.getElementById("canvas");
255
+ if (!canvas) return;
256
+
257
+ const handleSelectionChange = (e: CustomEvent) => {
258
+ setSelectedIds(Array.from(e.detail.selectedIds || []));
259
+ };
260
+
261
+ canvas.addEventListener("selectionchange" as any, handleSelectionChange);
262
+ return () => {
263
+ canvas.removeEventListener("selectionchange" as any, handleSelectionChange);
264
+ };
265
+ }, []);
266
+
267
+ return (
268
+ <div>
269
+ <div className="p-4 bg-gray-100">
270
+ <div className="font-semibold mb-2">Selected Elements:</div>
271
+ {selectedIds.length === 0 ? (
272
+ <div className="text-gray-500">None</div>
273
+ ) : (
274
+ <ul className="list-disc list-inside">
275
+ {selectedIds.map(id => (
276
+ <li key={id}>{id}</li>
277
+ ))}
278
+ </ul>
279
+ )}
280
+ </div>
281
+
282
+ <ef-canvas id="canvas">
283
+ <ef-timegroup mode="contain" className="w-[1920px] h-[1080px]">
284
+ <ef-canvas-item data-element-id="video-1">
285
+ <ef-video src="/assets/video1.mp4" />
286
+ </ef-canvas-item>
287
+ <ef-canvas-item data-element-id="video-2">
288
+ <ef-video src="/assets/video2.mp4" />
289
+ </ef-canvas-item>
290
+ <ef-canvas-item data-element-id="text-1">
291
+ <ef-text duration="5s">Title</ef-text>
292
+ </ef-canvas-item>
293
+ </ef-timegroup>
294
+ </ef-canvas>
295
+ </div>
296
+ );
297
+ };
298
+ ```
299
+ <!-- /react-only -->
300
+
301
+ ## Drag and Drop
302
+
303
+ <!-- html-only -->
304
+ Canvas supports dragging selected elements:
305
+
306
+ ### Single Element Drag
307
+
308
+ Click and drag an element to move it:
309
+
310
+ ```javascript
311
+ // Element position updates automatically
312
+ // No event handlers needed
313
+ ```
314
+
315
+ ### Multi-Element Drag
316
+
317
+ Select multiple elements and drag any selected element to move all:
318
+
319
+ ```javascript
320
+ const canvas = document.querySelector('ef-canvas');
321
+
322
+ // Select multiple elements
323
+ canvas.selectionContext.select('box-1');
324
+ canvas.selectionContext.addToSelection('box-2');
325
+ canvas.selectionContext.addToSelection('box-3');
326
+
327
+ // Drag any selected element - all move together
328
+ ```
329
+
330
+ ### Drag Threshold
331
+
332
+ Canvas uses a 5-pixel drag threshold to distinguish clicks from drags.
333
+ <!-- /html-only -->
334
+
335
+ ## Transform Handles
336
+
337
+ <!-- html-only -->
338
+ Canvas shows transform handles for selected elements:
339
+
340
+ ### Single Selection
341
+
342
+ Handles for resize and rotate:
343
+
344
+ - **Corner handles**: Resize proportionally
345
+ - **Edge handles**: Resize in one dimension
346
+ - **Rotation handle**: Rotate around center
347
+
348
+ ### Multi-Selection
349
+
350
+ Handles for the bounding box:
351
+
352
+ - **Corner handles**: Scale all elements proportionally
353
+ - **Rotation handle**: Rotate all elements around group center
354
+
355
+ ### Disable Handles
356
+
357
+ ```html
358
+ <ef-canvas enable-transform-handles="false">
359
+ <!-- No transform handles shown -->
360
+ </ef-canvas>
361
+ ```
362
+ <!-- /html-only -->
363
+
364
+ ## Programmatic Control
365
+
366
+ <!-- html-only -->
367
+ Control canvas selection via JavaScript:
368
+
369
+ ```javascript
370
+ const canvas = document.querySelector('ef-canvas');
371
+ const { selectionContext } = canvas;
372
+
373
+ // Select single element
374
+ selectionContext.select('element-id');
375
+
376
+ // Add to selection
377
+ selectionContext.addToSelection('another-id');
378
+
379
+ // Toggle selection
380
+ selectionContext.toggle('element-id');
381
+
382
+ // Clear selection
383
+ selectionContext.clear();
384
+
385
+ // Get selected IDs
386
+ const selected = Array.from(selectionContext.selectedIds);
387
+ ```
388
+ <!-- /html-only -->
389
+ <!-- react-only -->
390
+ ```tsx
391
+ export const ProgrammaticCanvas = () => {
392
+ const canvasRef = useRef<any>(null);
393
+
394
+ const selectElement = (id: string) => {
395
+ if (canvasRef.current) {
396
+ canvasRef.current.selectElement(id);
397
+ }
398
+ };
399
+
400
+ const getSelection = () => {
401
+ if (canvasRef.current) {
402
+ const selected = canvasRef.current.getSelectedElements();
403
+ console.log("Selected elements:", selected);
404
+ }
405
+ };
406
+
407
+ return (
408
+ <div>
409
+ <div className="p-4 space-x-2">
410
+ <button onClick={() => selectElement("video-1")}>Select Video</button>
411
+ <button onClick={() => selectElement("text-1")}>Select Text</button>
412
+ <button onClick={getSelection}>Get Selection</button>
413
+ </div>
414
+
415
+ <ef-canvas ref={canvasRef} id="canvas">
416
+ <ef-timegroup mode="contain" className="w-[1920px] h-[1080px]">
417
+ <ef-canvas-item data-element-id="video-1">
418
+ <ef-video src="/assets/video.mp4" />
419
+ </ef-canvas-item>
420
+ <ef-canvas-item data-element-id="text-1">
421
+ <ef-text duration="5s">Text</ef-text>
422
+ </ef-canvas-item>
423
+ </ef-timegroup>
424
+ </ef-canvas>
425
+ </div>
426
+ );
427
+ };
428
+ ```
429
+ <!-- /react-only -->
430
+
431
+ <!-- react-only -->
432
+ ## Update Element Bounds
433
+
434
+ ```tsx
435
+ export const BoundsControl = () => {
436
+ const canvasRef = useRef<any>(null);
437
+
438
+ const updatePosition = (elementId: string, x: number, y: number) => {
439
+ if (canvasRef.current) {
440
+ canvasRef.current.updateElementBounds(elementId, {
441
+ x,
442
+ y,
443
+ width: 400,
444
+ height: 300
445
+ });
446
+ }
447
+ };
448
+
449
+ return (
450
+ <div>
451
+ <div className="p-4">
452
+ <button onClick={() => updatePosition("video-1", 100, 100)}>
453
+ Position 1
454
+ </button>
455
+ <button onClick={() => updatePosition("video-1", 500, 200)}>
456
+ Position 2
457
+ </button>
458
+ </div>
459
+
460
+ <ef-canvas ref={canvasRef}>
461
+ <ef-timegroup mode="contain" className="w-[1920px] h-[1080px]">
462
+ <ef-canvas-item data-element-id="video-1">
463
+ <ef-video src="/assets/video.mp4" />
464
+ </ef-canvas-item>
465
+ </ef-timegroup>
466
+ </ef-canvas>
467
+ </div>
468
+ );
469
+ };
470
+ ```
471
+
472
+ ## Editor with Canvas
473
+
474
+ ```tsx
475
+ export const CanvasEditor = () => {
476
+ return (
477
+ <div className="h-screen grid grid-cols-[250px_1fr]">
478
+ {/* Hierarchy panel */}
479
+ <div className="border-r bg-gray-50">
480
+ <ef-hierarchy target="editor-canvas" header="Layers" show-header />
481
+ </div>
482
+
483
+ {/* Canvas area */}
484
+ <div className="flex flex-col">
485
+ <div className="flex-1 p-4 bg-gray-900">
486
+ <ef-preview />
487
+ </div>
488
+
489
+ <ef-canvas id="editor-canvas" enable-transform-handles>
490
+ <ef-timegroup mode="sequence" className="w-[1920px] h-[1080px]">
491
+ <ef-canvas-item data-element-id="bg-video">
492
+ <ef-video
493
+ src="/assets/background.mp4"
494
+ className="absolute inset-0 size-full"
495
+ />
496
+ </ef-canvas-item>
497
+
498
+ <ef-canvas-item data-element-id="title">
499
+ <ef-text
500
+ duration="5s"
501
+ className="absolute top-20 left-20 text-white text-5xl"
502
+ >
503
+ Video Title
504
+ </ef-text>
505
+ </ef-canvas-item>
506
+ </ef-timegroup>
507
+ </ef-canvas>
508
+ </div>
509
+ </div>
510
+ );
511
+ };
512
+ ```
513
+ <!-- /react-only -->
514
+
515
+ ## Element Registration
516
+
517
+ <!-- html-only -->
518
+ Canvas automatically registers child elements:
519
+
520
+ ### Automatic Registration
521
+
522
+ All child elements are auto-registered with auto-generated IDs:
523
+
524
+ ```html
525
+ <ef-canvas>
526
+ <div>Auto-registered with generated ID</div>
527
+ </ef-canvas>
528
+ ```
529
+
530
+ ### Manual Registration
531
+
532
+ Provide explicit IDs for stable references:
533
+
534
+ ```html
535
+ <ef-canvas>
536
+ <div id="my-element">Registered as 'my-element'</div>
537
+ </ef-canvas>
538
+ ```
539
+
540
+ ### Programmatic Registration
541
+
542
+ Register elements via JavaScript:
543
+
544
+ ```javascript
545
+ const canvas = document.querySelector('ef-canvas');
546
+ const element = document.createElement('div');
547
+
548
+ // Register with auto-generated ID
549
+ canvas.tryRegisterElement(element);
550
+
551
+ // Register with explicit ID
552
+ const id = canvas.registerElement(element, 'my-custom-id');
553
+
554
+ // Unregister
555
+ canvas.unregisterElement('my-custom-id');
556
+ ```
557
+ <!-- /html-only -->
558
+ <!-- react-only -->
559
+ Canvas identifies elements using data attributes:
560
+
561
+ - `data-element-id` - Primary element identifier (default)
562
+ - `data-timegroup-id` - For timegroup elements
563
+ - Custom attribute via `element-id-attribute` prop
564
+ <!-- /react-only -->
565
+
566
+ <!-- html-only -->
567
+ ## Position Management
568
+
569
+ Update element positions in canvas coordinates:
570
+
571
+ ```javascript
572
+ const canvas = document.querySelector('ef-canvas');
573
+
574
+ // Update position (canvas coordinates)
575
+ canvas.updateElementPosition('element-id', 100, 200);
576
+
577
+ // Get element metadata
578
+ const data = canvas.getElementData('element-id');
579
+ console.log('Position:', data.x, data.y);
580
+ console.log('Size:', data.width, data.height);
581
+ console.log('Rotation:', data.rotation);
582
+
583
+ // Get all elements
584
+ const allElements = canvas.getAllElementsData();
585
+ ```
586
+
587
+ ## Coordinate Conversion
588
+
589
+ Convert between screen and canvas coordinates:
590
+
591
+ ```javascript
592
+ const canvas = document.querySelector('ef-canvas');
593
+
594
+ // Screen to canvas
595
+ const canvasPos = canvas.screenToCanvasCoords(clientX, clientY);
596
+
597
+ // Canvas to screen
598
+ const screenPos = canvas.canvasToScreenCoords(canvasX, canvasY);
599
+ ```
600
+
601
+ Coordinates account for pan/zoom transforms.
602
+
603
+ ## Hover Highlighting
604
+
605
+ Canvas tracks hovered elements:
606
+
607
+ ```javascript
608
+ const canvas = document.querySelector('ef-canvas');
609
+
610
+ // Get highlighted element
611
+ console.log(canvas.highlightedElement);
612
+
613
+ // Programmatically highlight
614
+ const element = document.getElementById('my-element');
615
+ canvas.setHighlightedElement(element);
616
+
617
+ // Clear highlight
618
+ canvas.setHighlightedElement(null);
619
+ ```
620
+
621
+ Highlighted elements get `data-highlighted` attribute for styling:
622
+
623
+ ```css
624
+ [data-highlighted] {
625
+ outline: 2px solid blue;
626
+ }
627
+ ```
628
+
629
+ ## Selection Styling
630
+
631
+ Selected elements get `data-selected` attribute:
632
+
633
+ ```css
634
+ [data-selected] {
635
+ outline: 2px solid #2196f3;
636
+ }
637
+ ```
638
+
639
+ ## Pan/Zoom Integration
640
+
641
+ Canvas works seamlessly with ef-pan-zoom:
642
+
643
+ ```html
644
+ <ef-pan-zoom>
645
+ <ef-canvas>
646
+ <!-- Elements stay correctly positioned during pan/zoom -->
647
+ </ef-canvas>
648
+ </ef-pan-zoom>
649
+ ```
650
+
651
+ Canvas automatically:
652
+
653
+ - Converts coordinates accounting for zoom
654
+ - Updates transform handles
655
+ - Maintains correct hit testing
656
+
657
+ ## Active Root Temporal
658
+
659
+ Canvas tracks the root temporal element containing selection:
660
+
661
+ ```javascript
662
+ const canvas = document.querySelector('ef-canvas');
663
+
664
+ // Get active root temporal
665
+ console.log(canvas.activeRootTemporal);
666
+
667
+ // Listen for changes
668
+ canvas.addEventListener('activeroottemporalchange', (e) => {
669
+ console.log('Active root:', e.detail.activeRootTemporal);
670
+ });
671
+ ```
672
+
673
+ Useful for timeline scrubbing and playback controls.
674
+
675
+ ## Nested Elements
676
+
677
+ Canvas supports nested element hierarchies:
678
+
679
+ ```html
680
+ <ef-canvas>
681
+ <div id="parent" class="absolute top-0 left-0 w-64 h-48">
682
+ <div id="child" class="absolute top-4 left-4 w-32 h-24">
683
+ <!-- Nested element -->
684
+ </div>
685
+ </div>
686
+ </ef-canvas>
687
+ ```
688
+
689
+ Both parent and child are selectable and draggable.
690
+
691
+ ## Element Metadata
692
+
693
+ Canvas tracks element bounds and transforms:
694
+
695
+ ```typescript
696
+ interface CanvasElementData {
697
+ id: string;
698
+ element: HTMLElement;
699
+ x: number; // Top-left x in canvas coordinates
700
+ y: number; // Top-left y in canvas coordinates
701
+ width: number; // Width in canvas units
702
+ height: number; // Height in canvas units
703
+ rotation?: number; // Rotation in degrees
704
+ }
705
+ ```
706
+
707
+ Metadata updates automatically when elements change.
708
+
709
+ ## Coordinate System
710
+
711
+ Canvas uses a unified coordinate calculation:
712
+
713
+ - **Dimensions**: From `offsetWidth`/`offsetHeight` (unaffected by transforms)
714
+ - **Center**: From `getBoundingClientRect()` center (rotation-invariant)
715
+ - **Top-left**: Calculated from center minus half dimensions
716
+
717
+ This approach works correctly for rotated, scaled, and nested elements.
718
+
719
+ ## Performance
720
+
721
+ Canvas optimizes for interactive editing:
722
+
723
+ - Single RAF loop for overlays and handles
724
+ - Pointer capture during drag operations
725
+ - Efficient hit testing with z-order respect
726
+ - No change detection overhead
727
+
728
+ ## Deprecated: ef-canvas-item
729
+
730
+ The `ef-canvas-item` wrapper is deprecated. Use plain HTML elements:
731
+
732
+ ```html
733
+ <!-- Old (deprecated) -->
734
+ <ef-canvas>
735
+ <ef-canvas-item id="item-1">
736
+ <div>Content</div>
737
+ </ef-canvas-item>
738
+ </ef-canvas>
739
+
740
+ <!-- New (recommended) -->
741
+ <ef-canvas>
742
+ <div id="item-1">Content</div>
743
+ </ef-canvas>
744
+ ```
745
+
746
+ All DOM nodes in canvas are now automatically selectable.
747
+ <!-- /html-only -->
748
+
749
+ ## Events
750
+
751
+ <!-- html-only -->
752
+ ### activeroottemporalchange
753
+
754
+ Fired when active root temporal changes. See the Active Root Temporal section above.
755
+ <!-- /html-only -->
756
+ <!-- react-only -->
757
+ ### selectionchange
758
+
759
+ Fired when selection changes:
760
+
761
+ ```typescript
762
+ interface SelectionChangeDetail {
763
+ selectedIds: Set<string>;
764
+ previousIds: Set<string>;
765
+ }
766
+ ```
767
+
768
+ ### elementmoved
769
+
770
+ Fired when element is dragged:
771
+
772
+ ```typescript
773
+ interface ElementMovedDetail {
774
+ elementId: string;
775
+ x: number;
776
+ y: number;
777
+ }
778
+ ```
779
+
780
+ ### elementresized
781
+
782
+ Fired when element is resized:
783
+
784
+ ```typescript
785
+ interface ElementResizedDetail {
786
+ elementId: string;
787
+ width: number;
788
+ height: number;
789
+ }
790
+ ```
791
+
792
+ ### elementrotated
793
+
794
+ Fired when element is rotated:
795
+
796
+ ```typescript
797
+ interface ElementRotatedDetail {
798
+ elementId: string;
799
+ rotation: number;
800
+ }
801
+ ```
802
+
803
+ ## Methods
804
+
805
+ ### selectElement()
806
+
807
+ Select an element by ID:
808
+
809
+ ```tsx
810
+ canvas.selectElement("element-id");
811
+ ```
812
+
813
+ ### getSelectedElements()
814
+
815
+ Get selected elements:
816
+
817
+ ```tsx
818
+ const elements = canvas.getSelectedElements();
819
+ // Returns: HTMLElement[]
820
+ ```
821
+
822
+ ### updateElementBounds()
823
+
824
+ Update element transform:
825
+
826
+ ```tsx
827
+ canvas.updateElementBounds("element-id", {
828
+ x: 100,
829
+ y: 100,
830
+ width: 400,
831
+ height: 300,
832
+ rotation: 45
833
+ });
834
+ ```
835
+
836
+ ### clearSelection()
837
+
838
+ Clear all selections:
839
+
840
+ ```tsx
841
+ canvas.clearSelection();
842
+ ```
843
+
844
+ ### deleteSelected()
845
+
846
+ Delete selected elements:
847
+
848
+ ```tsx
849
+ canvas.deleteSelected();
850
+ ```
851
+ <!-- /react-only -->
852
+
853
+ <!-- react-only -->
854
+ ## CSS Customization
855
+
856
+ ```css
857
+ ef-canvas {
858
+ --canvas-bg: #1f2937;
859
+ --canvas-grid-color: rgba(255, 255, 255, 0.1);
860
+ --canvas-selection-color: #3b82f6;
861
+ --canvas-highlight-color: #10b981;
862
+ }
863
+ ```
864
+
865
+ ## Canvas Features
866
+
867
+ - **Click to select**: Click elements to select them
868
+ - **Drag to move**: Drag selected elements to reposition
869
+ - **Transform handles**: Resize and rotate with handles
870
+ - **Multi-select**: Hold Cmd/Ctrl to select multiple elements
871
+ - **Keyboard shortcuts**: Arrow keys to nudge, Delete to remove
872
+ - **Selection box**: Click and drag background for box selection
873
+ - **Snap to grid**: Optional grid snapping for precise placement
874
+
875
+ ## CanvasItem Wrapper
876
+
877
+ `ef-canvas-item` is a wrapper that makes elements interactive:
878
+
879
+ - Registers element with canvas for selection
880
+ - Provides drag-and-drop behavior
881
+ - Manages transform handles display
882
+ - Tracks element bounds for manipulation
883
+ - Forwards pointer events to canvas
884
+
885
+ ## Keyboard Shortcuts
886
+
887
+ - **Arrow keys**: Nudge selected element (1px or 10px with Shift)
888
+ - **Delete/Backspace**: Delete selected elements
889
+ - **Cmd/Ctrl + A**: Select all
890
+ - **Cmd/Ctrl + D**: Duplicate selected
891
+ - **Escape**: Clear selection
892
+ - **Cmd/Ctrl + Z**: Undo (if implemented)
893
+
894
+ ## Integration Patterns
895
+
896
+ ### With Hierarchy
897
+
898
+ ```tsx
899
+ <div className="flex">
900
+ <ef-hierarchy target="canvas" />
901
+ <ef-canvas id="canvas">
902
+ {/* content */}
903
+ </ef-canvas>
904
+ </div>
905
+ ```
906
+
907
+ ### With OverlayLayer
908
+
909
+ ```tsx
910
+ <ef-canvas>
911
+ <ef-overlay-layer>
912
+ <ef-overlay-item element-id="selected">
913
+ <ef-transform-handles />
914
+ </ef-overlay-item>
915
+ </ef-overlay-layer>
916
+
917
+ {/* content */}
918
+ </ef-canvas>
919
+ ```
920
+
921
+ ## Important Notes
922
+
923
+ - Canvas and CanvasItem are not yet exported from React package
924
+ - Use HTML element syntax in React until official export
925
+ - Canvas provides selection context via Lit context system
926
+ - Transform handles require `enable-transform-handles` prop
927
+ - Elements must be wrapped in `ef-canvas-item` to be interactive
928
+ - Canvas automatically manages overlay positioning
929
+ - Supports nested timegroups and complex hierarchies
930
+ - Selection state syncs with Hierarchy component
931
+
932
+ ## Future React Components
933
+
934
+ When officially exported, usage will be:
935
+
936
+ ```tsx
937
+ import { Canvas, CanvasItem } from "@editframe/react";
938
+
939
+ <Canvas enableTransformHandles onSelectionChange={handleChange}>
940
+ <Timegroup mode="contain" className="w-[1920px] h-[1080px]">
941
+ <CanvasItem elementId="video-1">
942
+ <Video src="/assets/video.mp4" />
943
+ </CanvasItem>
944
+ </Timegroup>
945
+ </Canvas>
946
+ ```
947
+ <!-- /react-only -->