@editframe/elements 0.6.0-beta.9 → 0.7.0-beta.10

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/lib/av/EncodedAsset.cjs +577 -0
  2. package/dist/lib/av/EncodedAsset.js +560 -0
  3. package/dist/lib/av/MP4File.cjs +187 -0
  4. package/dist/lib/av/MP4File.js +170 -0
  5. package/dist/lib/av/msToTimeCode.cjs +15 -0
  6. package/dist/lib/av/msToTimeCode.js +15 -0
  7. package/dist/lib/util/awaitMicrotask.cjs +4 -0
  8. package/dist/lib/util/awaitMicrotask.js +4 -0
  9. package/dist/lib/util/memoize.cjs +14 -0
  10. package/dist/lib/util/memoize.js +14 -0
  11. package/dist/packages/elements/src/EF_FRAMEGEN.cjs +197 -0
  12. package/dist/packages/elements/src/EF_FRAMEGEN.d.ts +44 -0
  13. package/dist/packages/elements/src/EF_FRAMEGEN.js +197 -0
  14. package/dist/packages/elements/src/EF_INTERACTIVE.cjs +4 -0
  15. package/dist/packages/elements/src/EF_INTERACTIVE.d.ts +1 -0
  16. package/dist/packages/elements/src/EF_INTERACTIVE.js +4 -0
  17. package/dist/packages/elements/src/elements/CrossUpdateController.cjs +16 -0
  18. package/dist/packages/elements/src/elements/CrossUpdateController.d.ts +9 -0
  19. package/dist/packages/elements/src/elements/CrossUpdateController.js +16 -0
  20. package/dist/packages/elements/src/elements/EFAudio.cjs +53 -0
  21. package/dist/packages/elements/src/elements/EFAudio.d.ts +10 -0
  22. package/dist/packages/elements/src/elements/EFAudio.js +54 -0
  23. package/dist/packages/elements/src/elements/EFCaptions.cjs +164 -0
  24. package/dist/packages/elements/src/elements/EFCaptions.d.ts +38 -0
  25. package/dist/packages/elements/src/elements/EFCaptions.js +166 -0
  26. package/dist/packages/elements/src/elements/EFImage.cjs +79 -0
  27. package/dist/packages/elements/src/elements/EFImage.d.ts +14 -0
  28. package/dist/packages/elements/src/elements/EFImage.js +80 -0
  29. package/dist/packages/elements/src/elements/EFMedia.cjs +336 -0
  30. package/dist/packages/elements/src/elements/EFMedia.d.ts +61 -0
  31. package/dist/packages/elements/src/elements/EFMedia.js +336 -0
  32. package/dist/packages/elements/src/elements/EFSourceMixin.cjs +55 -0
  33. package/dist/packages/elements/src/elements/EFSourceMixin.d.ts +12 -0
  34. package/dist/packages/elements/src/elements/EFSourceMixin.js +55 -0
  35. package/dist/packages/elements/src/elements/EFTemporal.cjs +199 -0
  36. package/dist/packages/elements/src/elements/EFTemporal.d.ts +38 -0
  37. package/dist/packages/elements/src/elements/EFTemporal.js +199 -0
  38. package/dist/packages/elements/src/elements/EFTimegroup.browsertest.d.ts +12 -0
  39. package/dist/packages/elements/src/elements/EFTimegroup.cjs +352 -0
  40. package/dist/packages/elements/src/elements/EFTimegroup.d.ts +39 -0
  41. package/dist/packages/elements/src/elements/EFTimegroup.js +353 -0
  42. package/dist/packages/elements/src/elements/EFVideo.cjs +109 -0
  43. package/dist/packages/elements/src/elements/EFVideo.d.ts +14 -0
  44. package/dist/packages/elements/src/elements/EFVideo.js +110 -0
  45. package/dist/packages/elements/src/elements/EFWaveform.cjs +242 -0
  46. package/dist/packages/elements/src/elements/EFWaveform.d.ts +30 -0
  47. package/dist/packages/elements/src/elements/EFWaveform.js +226 -0
  48. package/dist/packages/elements/src/elements/FetchMixin.cjs +28 -0
  49. package/dist/packages/elements/src/elements/FetchMixin.d.ts +8 -0
  50. package/dist/packages/elements/src/elements/FetchMixin.js +28 -0
  51. package/dist/packages/elements/src/elements/TimegroupController.cjs +20 -0
  52. package/dist/packages/elements/src/elements/TimegroupController.d.ts +14 -0
  53. package/dist/packages/elements/src/elements/TimegroupController.js +20 -0
  54. package/dist/packages/elements/src/elements/durationConverter.cjs +8 -0
  55. package/dist/packages/elements/src/elements/durationConverter.d.ts +4 -0
  56. package/dist/packages/elements/src/elements/durationConverter.js +8 -0
  57. package/dist/packages/elements/src/elements/parseTimeToMs.cjs +12 -0
  58. package/dist/packages/elements/src/elements/parseTimeToMs.d.ts +1 -0
  59. package/dist/packages/elements/src/elements/parseTimeToMs.js +12 -0
  60. package/dist/packages/elements/src/elements/util.cjs +11 -0
  61. package/dist/packages/elements/src/elements/util.d.ts +4 -0
  62. package/dist/packages/elements/src/elements/util.js +11 -0
  63. package/dist/packages/elements/src/gui/EFFilmstrip.cjs +825 -0
  64. package/dist/packages/elements/src/gui/EFFilmstrip.d.ts +147 -0
  65. package/dist/packages/elements/src/gui/EFFilmstrip.js +833 -0
  66. package/dist/packages/elements/src/gui/EFWorkbench.cjs +214 -0
  67. package/dist/packages/elements/src/gui/EFWorkbench.d.ts +45 -0
  68. package/dist/packages/elements/src/gui/EFWorkbench.js +215 -0
  69. package/dist/packages/elements/src/gui/TWMixin.cjs +28 -0
  70. package/dist/packages/elements/src/gui/TWMixin.css.cjs +3 -0
  71. package/dist/packages/elements/src/gui/TWMixin.css.js +4 -0
  72. package/dist/packages/elements/src/gui/TWMixin.d.ts +3 -0
  73. package/dist/packages/elements/src/gui/TWMixin.js +28 -0
  74. package/dist/packages/elements/src/index.cjs +50 -0
  75. package/dist/packages/elements/src/index.d.ts +10 -0
  76. package/dist/packages/elements/src/index.js +23 -0
  77. package/dist/style.css +791 -0
  78. package/package.json +14 -8
  79. package/src/elements/CrossUpdateController.ts +22 -0
  80. package/src/elements/EFAudio.ts +40 -0
  81. package/src/elements/EFCaptions.ts +188 -0
  82. package/src/elements/EFImage.ts +68 -0
  83. package/src/elements/EFMedia.ts +389 -0
  84. package/src/elements/EFSourceMixin.ts +57 -0
  85. package/src/elements/EFTemporal.ts +234 -0
  86. package/src/elements/EFTimegroup.browsertest.ts +333 -0
  87. package/src/elements/EFTimegroup.ts +393 -0
  88. package/src/elements/EFVideo.ts +103 -0
  89. package/src/elements/EFWaveform.ts +417 -0
  90. package/src/elements/FetchMixin.ts +19 -0
  91. package/src/elements/TimegroupController.ts +25 -0
  92. package/src/elements/durationConverter.ts +6 -0
  93. package/src/elements/parseTimeToMs.ts +9 -0
  94. package/src/elements/util.ts +24 -0
  95. package/src/gui/EFFilmstrip.ts +884 -0
  96. package/src/gui/EFWorkbench.ts +233 -0
  97. package/src/gui/TWMixin.css +3 -0
  98. package/src/gui/TWMixin.ts +30 -0
@@ -0,0 +1,233 @@
1
+ import { createContext, provide } from "@lit/context";
2
+ import { LitElement, html, css, type PropertyValueMap } from "lit";
3
+ import { TaskStatus } from "@lit/task";
4
+ import {
5
+ customElement,
6
+ eventOptions,
7
+ property,
8
+ state,
9
+ } from "lit/decorators.js";
10
+ import { ref, createRef } from "lit/directives/ref.js";
11
+
12
+ import { awaitMicrotask } from "@/util/awaitMicrotask";
13
+ import { deepGetTemporalElements } from "../elements/EFTemporal";
14
+ import { TWMixin } from "./TWMixin";
15
+ import { shallowGetTimegroups } from "../elements/EFTimegroup";
16
+
17
+ export interface FocusContext {
18
+ focusedElement: HTMLElement | null;
19
+ }
20
+ export const focusContext = createContext<FocusContext>(Symbol("focusContext"));
21
+
22
+ export const focusedElement = createContext<HTMLElement | undefined>(
23
+ Symbol("focusedElement"),
24
+ );
25
+
26
+ export const fetchContext = createContext<typeof fetch>(Symbol("fetchContext"));
27
+
28
+ export const apiHostContext = createContext<string>(Symbol("apiHostContext"));
29
+
30
+ @customElement("ef-workbench")
31
+ export class EFWorkbench extends TWMixin(LitElement) {
32
+ static styles = [
33
+ css`
34
+ :host {
35
+ display: block;
36
+ width: 100%;
37
+ height: 100%;
38
+ }
39
+ `,
40
+ ];
41
+ stageRef = createRef<HTMLDivElement>();
42
+ canvasRef = createRef<HTMLSlotElement>();
43
+
44
+ @state()
45
+ stageScale = 1;
46
+
47
+ setStageScale = () => {
48
+ if (this.isConnected && !this.rendering) {
49
+ const canvasElement = this.canvasRef.value;
50
+ const stageElement = this.stageRef.value;
51
+ if (stageElement && canvasElement) {
52
+ // Determine the appropriate scale factor to make the canvas fit into
53
+ // it's parent element.
54
+ const stageWidth = stageElement.clientWidth;
55
+ const stageHeight = stageElement.clientHeight;
56
+ const canvasWidth = canvasElement.clientWidth;
57
+ const canvasHeight = canvasElement.clientHeight;
58
+ const stageRatio = stageWidth / stageHeight;
59
+ const canvasRatio = canvasWidth / canvasHeight;
60
+ if (stageRatio > canvasRatio) {
61
+ const scale = stageHeight / canvasHeight;
62
+ if (this.stageScale !== scale) {
63
+ canvasElement.style.transform = `scale(${scale})`;
64
+ }
65
+ this.stageScale = scale;
66
+ } else {
67
+ const scale = stageWidth / canvasWidth;
68
+ if (this.stageScale !== scale) {
69
+ canvasElement.style.transform = `scale(${scale})`;
70
+ }
71
+ this.stageScale = scale;
72
+ }
73
+ }
74
+ }
75
+ if (this.isConnected) {
76
+ requestAnimationFrame(this.setStageScale);
77
+ }
78
+ };
79
+
80
+ connectedCallback(): void {
81
+ super.connectedCallback();
82
+ // Preferrably we would use a resizeObserver, but it is difficult to get the first resize
83
+ // timed correctl. So we use requestAnimationFrame as a stop-gap.
84
+ requestAnimationFrame(this.setStageScale);
85
+ }
86
+
87
+ disconnectedCallback(): void {
88
+ super.disconnectedCallback();
89
+ }
90
+
91
+ @eventOptions({ passive: false, capture: true })
92
+ handleStageWheel(event: WheelEvent) {
93
+ event.preventDefault();
94
+ }
95
+
96
+ @provide({ context: focusContext })
97
+ focusContext = this as FocusContext;
98
+
99
+ @provide({ context: focusedElement })
100
+ @state()
101
+ focusedElement?: HTMLElement;
102
+
103
+ @provide({ context: fetchContext })
104
+ fetch = (path: URL | RequestInfo, init: RequestInit = {}) => {
105
+ init.headers ||= {};
106
+ Object.assign(init.headers, {
107
+ "Content-Type": "application/json",
108
+ });
109
+
110
+ const bearerToken = this.apiToken;
111
+ if (bearerToken) {
112
+ Object.assign(init.headers, {
113
+ Authorization: `Bearer ${bearerToken}`,
114
+ });
115
+ }
116
+
117
+ return fetch(path, init);
118
+ };
119
+
120
+ @property({ type: String })
121
+ apiToken?: string;
122
+
123
+ @provide({ context: apiHostContext })
124
+ @property({ type: String })
125
+ apiHost = "";
126
+
127
+ @property({ type: Boolean })
128
+ rendering = false;
129
+
130
+ focusOverlay = createRef<HTMLDivElement>();
131
+
132
+ update(
133
+ changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,
134
+ ): void {
135
+ super.update(changedProperties);
136
+
137
+ if (changedProperties.has("focusedElement")) {
138
+ this.drawOverlays();
139
+ }
140
+ }
141
+
142
+ drawOverlays = () => {
143
+ const focusOverlay = this.focusOverlay.value;
144
+ if (focusOverlay) {
145
+ if (this.focusedElement) {
146
+ focusOverlay.style.display = "block";
147
+ const rect = this.focusedElement.getBoundingClientRect();
148
+ Object.assign(focusOverlay.style, {
149
+ position: "absolute",
150
+ top: `${rect.top}px`,
151
+ left: `${rect.left}px`,
152
+ width: `${rect.width}px`,
153
+ height: `${rect.height}px`,
154
+ });
155
+ requestAnimationFrame(this.drawOverlays);
156
+ } else {
157
+ focusOverlay.style.display = "none";
158
+ }
159
+ }
160
+ };
161
+
162
+ render() {
163
+ if (this.rendering) {
164
+ return html`
165
+ <slot
166
+ ${ref(this.canvasRef)}
167
+ class="fixed inset-0 h-full w-full"
168
+ name="canvas"
169
+ ></slot>
170
+ `;
171
+ }
172
+ return html`
173
+ <div
174
+ class="grid h-full w-full"
175
+ style="grid-template-rows: 1fr 300px; grid-template-columns: 100%;"
176
+ >
177
+ <div
178
+ ${ref(this.stageRef)}
179
+ class="relative grid h-full w-full place-content-center place-items-center overflow-hidden"
180
+ @wheel=${this.handleStageWheel}
181
+ >
182
+ <slot
183
+ ${ref(this.canvasRef)}
184
+ class="inline-block"
185
+ name="canvas"
186
+ ></slot>
187
+ <div
188
+ class="border border-blue-500 bg-blue-200 bg-opacity-20"
189
+ ${ref(this.focusOverlay)}
190
+ ></div>
191
+ </div>
192
+
193
+ <slot class="overflow" name="timeline"></slot>
194
+ </div>
195
+ `;
196
+ }
197
+
198
+ async stepThrough() {
199
+ const stepDurationMs = 1000 / 30;
200
+ const timegroups = shallowGetTimegroups(this);
201
+ const firstGroup = timegroups[0];
202
+ if (!firstGroup) {
203
+ throw new Error("No temporal elements found");
204
+ }
205
+ firstGroup.currentTimeMs = 0;
206
+
207
+ const temporals = deepGetTemporalElements(this);
208
+ const frameCount = Math.ceil(firstGroup.durationMs / stepDurationMs);
209
+
210
+ const busyTasks = temporals
211
+ .filter((temporal) => temporal.frameTask.status < TaskStatus.COMPLETE)
212
+ .map((temporal) => temporal.frameTask);
213
+
214
+ await Promise.all(busyTasks.map((task) => task.taskComplete));
215
+
216
+ for (let i = 0; i < frameCount; i++) {
217
+ firstGroup.currentTimeMs = i * stepDurationMs;
218
+ await awaitMicrotask();
219
+ const busyTasks = temporals
220
+ .filter((temporal) => temporal.frameTask.status < TaskStatus.COMPLETE)
221
+ .map((temporal) => temporal.frameTask);
222
+
223
+ await Promise.all(busyTasks.map((task) => task.taskComplete));
224
+ await new Promise((resolve) => requestAnimationFrame(resolve));
225
+ }
226
+ }
227
+ }
228
+
229
+ declare global {
230
+ interface HTMLElementTagNameMap {
231
+ "ef-workbench": EFWorkbench;
232
+ }
233
+ }
@@ -0,0 +1,3 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
@@ -0,0 +1,30 @@
1
+ import type { LitElement } from "lit";
2
+ // @ts-expect-error cannot figure out how to declare this module as a string
3
+ import twStyle from "./TWMixin.css?inline";
4
+
5
+ const twSheet = new CSSStyleSheet();
6
+ twSheet.replaceSync(twStyle);
7
+ export function TWMixin<T extends new (...args: any[]) => LitElement>(Base: T) {
8
+ class TWElement extends Base {
9
+ createRenderRoot() {
10
+ const renderRoot = super.createRenderRoot();
11
+ if (!(renderRoot instanceof ShadowRoot)) {
12
+ throw new Error(
13
+ "TWMixin can only be applied to elements with shadow roots",
14
+ );
15
+ }
16
+
17
+ if (renderRoot?.adoptedStyleSheets) {
18
+ renderRoot.adoptedStyleSheets = [
19
+ twSheet,
20
+ ...renderRoot.adoptedStyleSheets,
21
+ ];
22
+ } else {
23
+ renderRoot.adoptedStyleSheets = [twSheet];
24
+ }
25
+ return renderRoot;
26
+ }
27
+ }
28
+
29
+ return TWElement as T;
30
+ }