@editframe/elements 0.7.0-beta.9 → 0.8.0-beta.2

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 (97) hide show
  1. package/dist/EF_FRAMEGEN.d.ts +44 -0
  2. package/dist/EF_INTERACTIVE.d.ts +1 -0
  3. package/dist/assets/dist/EncodedAsset.js +560 -0
  4. package/dist/assets/dist/MP4File.js +170 -0
  5. package/dist/assets/dist/memoize.js +14 -0
  6. package/dist/elements/CrossUpdateController.d.ts +9 -0
  7. package/dist/elements/EFAudio.d.ts +10 -0
  8. package/dist/elements/EFCaptions.d.ts +38 -0
  9. package/dist/elements/EFImage.d.ts +14 -0
  10. package/dist/elements/EFMedia.d.ts +64 -0
  11. package/dist/elements/EFSourceMixin.d.ts +12 -0
  12. package/dist/elements/EFTemporal.d.ts +38 -0
  13. package/dist/elements/EFTimegroup.browsertest.d.ts +12 -0
  14. package/dist/elements/EFTimegroup.d.ts +39 -0
  15. package/dist/elements/EFVideo.d.ts +14 -0
  16. package/dist/elements/EFWaveform.d.ts +30 -0
  17. package/dist/elements/FetchMixin.d.ts +8 -0
  18. package/dist/elements/TimegroupController.d.ts +14 -0
  19. package/dist/elements/durationConverter.d.ts +4 -0
  20. package/dist/elements/parseTimeToMs.d.ts +1 -0
  21. package/{src/EF_FRAMEGEN.ts → dist/elements/src/EF_FRAMEGEN.js} +35 -115
  22. package/dist/elements/src/EF_INTERACTIVE.js +7 -0
  23. package/dist/elements/src/elements/CrossUpdateController.js +16 -0
  24. package/dist/elements/src/elements/EFAudio.js +54 -0
  25. package/dist/elements/src/elements/EFCaptions.js +166 -0
  26. package/dist/elements/src/elements/EFImage.js +80 -0
  27. package/dist/elements/src/elements/EFMedia.js +356 -0
  28. package/dist/elements/src/elements/EFSourceMixin.js +55 -0
  29. package/dist/elements/src/elements/EFTemporal.js +234 -0
  30. package/dist/elements/src/elements/EFTimegroup.js +355 -0
  31. package/dist/elements/src/elements/EFVideo.js +110 -0
  32. package/dist/elements/src/elements/EFWaveform.js +226 -0
  33. package/dist/elements/src/elements/FetchMixin.js +28 -0
  34. package/dist/elements/src/elements/TimegroupController.js +20 -0
  35. package/dist/elements/src/elements/durationConverter.js +8 -0
  36. package/dist/elements/src/elements/parseTimeToMs.js +12 -0
  37. package/dist/elements/src/elements/util.js +11 -0
  38. package/dist/elements/src/gui/ContextMixin.js +236 -0
  39. package/dist/elements/src/gui/EFFilmstrip.js +729 -0
  40. package/dist/elements/src/gui/EFPreview.js +45 -0
  41. package/dist/elements/src/gui/EFWorkbench.js +128 -0
  42. package/dist/elements/src/gui/TWMixin.css.js +4 -0
  43. package/dist/elements/src/gui/TWMixin.js +36 -0
  44. package/dist/elements/src/gui/apiHostContext.js +5 -0
  45. package/dist/elements/src/gui/fetchContext.js +5 -0
  46. package/dist/elements/src/gui/focusContext.js +5 -0
  47. package/dist/elements/src/gui/focusedElementContext.js +7 -0
  48. package/dist/elements/src/gui/playingContext.js +5 -0
  49. package/dist/elements/src/index.js +27 -0
  50. package/dist/elements/src/msToTimeCode.js +15 -0
  51. package/dist/elements/util.d.ts +4 -0
  52. package/dist/gui/ContextMixin.d.ts +23 -0
  53. package/dist/gui/EFFilmstrip.d.ts +144 -0
  54. package/dist/gui/EFPreview.d.ts +27 -0
  55. package/dist/gui/EFWorkbench.d.ts +34 -0
  56. package/dist/gui/TWMixin.d.ts +3 -0
  57. package/dist/gui/apiHostContext.d.ts +3 -0
  58. package/dist/gui/fetchContext.d.ts +3 -0
  59. package/dist/gui/focusContext.d.ts +6 -0
  60. package/dist/gui/focusedElementContext.d.ts +3 -0
  61. package/dist/gui/playingContext.d.ts +3 -0
  62. package/dist/index.d.ts +11 -0
  63. package/dist/msToTimeCode.d.ts +1 -0
  64. package/dist/style.css +800 -0
  65. package/package.json +6 -9
  66. package/src/elements/EFAudio.ts +1 -1
  67. package/src/elements/EFCaptions.ts +9 -9
  68. package/src/elements/EFImage.ts +3 -3
  69. package/src/elements/EFMedia.ts +39 -11
  70. package/src/elements/EFSourceMixin.ts +1 -1
  71. package/src/elements/EFTemporal.ts +42 -5
  72. package/src/elements/EFTimegroup.browsertest.ts +3 -3
  73. package/src/elements/EFTimegroup.ts +9 -6
  74. package/src/elements/EFVideo.ts +2 -2
  75. package/src/elements/EFWaveform.ts +6 -6
  76. package/src/elements/FetchMixin.ts +5 -3
  77. package/src/elements/TimegroupController.ts +1 -1
  78. package/src/elements/durationConverter.ts +1 -1
  79. package/src/elements/util.ts +1 -1
  80. package/src/gui/ContextMixin.ts +256 -0
  81. package/src/gui/EFFilmstrip.ts +41 -150
  82. package/src/gui/EFPreview.ts +39 -0
  83. package/src/gui/EFWorkbench.ts +7 -105
  84. package/src/gui/TWMixin.ts +10 -3
  85. package/src/gui/apiHostContext.ts +3 -0
  86. package/src/gui/fetchContext.ts +5 -0
  87. package/src/gui/focusContext.ts +7 -0
  88. package/src/gui/focusedElementContext.ts +5 -0
  89. package/src/gui/playingContext.ts +3 -0
  90. package/CHANGELOG.md +0 -7
  91. package/postcss.config.cjs +0 -12
  92. package/src/EF_INTERACTIVE.ts +0 -2
  93. package/src/elements.css +0 -22
  94. package/src/index.ts +0 -33
  95. package/tailwind.config.ts +0 -10
  96. package/tsconfig.json +0 -4
  97. package/vite.config.ts +0 -8
@@ -0,0 +1,28 @@
1
+ import { consume } from "@lit/context";
2
+ import { state } from "lit/decorators/state.js";
3
+ import { fetchContext } from "../gui/fetchContext.js";
4
+ var __defProp = Object.defineProperty;
5
+ var __decorateClass = (decorators, target, key, kind) => {
6
+ var result = void 0;
7
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
8
+ if (decorator = decorators[i])
9
+ result = decorator(target, key, result) || result;
10
+ if (result) __defProp(target, key, result);
11
+ return result;
12
+ };
13
+ function FetchMixin(superClass) {
14
+ class FetchElement extends superClass {
15
+ constructor() {
16
+ super(...arguments);
17
+ this.fetch = fetch.bind(window);
18
+ }
19
+ }
20
+ __decorateClass([
21
+ consume({ context: fetchContext, subscribe: true }),
22
+ state()
23
+ ], FetchElement.prototype, "fetch");
24
+ return FetchElement;
25
+ }
26
+ export {
27
+ FetchMixin
28
+ };
@@ -0,0 +1,20 @@
1
+ class TimegroupController {
2
+ constructor(host, child) {
3
+ this.host = host;
4
+ this.child = child;
5
+ this.host.addController(this);
6
+ }
7
+ remove() {
8
+ this.host.removeController(this);
9
+ }
10
+ hostDisconnected() {
11
+ this.host.removeController(this);
12
+ }
13
+ hostUpdated() {
14
+ this.child.requestUpdate();
15
+ this.child.currentTimeMs = this.host.currentTimeMs - (this.child.startTimeMs ?? 0);
16
+ }
17
+ }
18
+ export {
19
+ TimegroupController
20
+ };
@@ -0,0 +1,8 @@
1
+ import { parseTimeToMs } from "./parseTimeToMs.js";
2
+ const durationConverter = {
3
+ fromAttribute: (value) => parseTimeToMs(value),
4
+ toAttribute: (value) => `${value}s`
5
+ };
6
+ export {
7
+ durationConverter
8
+ };
@@ -0,0 +1,12 @@
1
+ const parseTimeToMs = (time) => {
2
+ if (time.endsWith("ms")) {
3
+ return Number.parseFloat(time);
4
+ }
5
+ if (time.endsWith("s")) {
6
+ return Number.parseFloat(time) * 1e3;
7
+ }
8
+ throw new Error("Time must be in milliseconds or seconds (10s, 10000ms)");
9
+ };
10
+ export {
11
+ parseTimeToMs
12
+ };
@@ -0,0 +1,11 @@
1
+ import { EFTimegroup } from "./EFTimegroup.js";
2
+ const getStartTimeMs = (element) => {
3
+ const nearestTimeGroup = element.closest("ef-timegroup");
4
+ if (!(nearestTimeGroup instanceof EFTimegroup)) {
5
+ return 0;
6
+ }
7
+ return nearestTimeGroup.startTimeMs;
8
+ };
9
+ export {
10
+ getStartTimeMs
11
+ };
@@ -0,0 +1,236 @@
1
+ import { provide } from "@lit/context";
2
+ import { state, property } from "lit/decorators.js";
3
+ import { focusContext } from "./focusContext.js";
4
+ import { focusedElementContext } from "./focusedElementContext.js";
5
+ import { fetchContext } from "./fetchContext.js";
6
+ import { apiHostContext } from "./apiHostContext.js";
7
+ import { createRef } from "lit/directives/ref.js";
8
+ import { playingContext } from "./playingContext.js";
9
+ var __defProp = Object.defineProperty;
10
+ var __decorateClass = (decorators, target, key, kind) => {
11
+ var result = void 0;
12
+ for (var i = decorators.length - 1, decorator; i >= 0; i--)
13
+ if (decorator = decorators[i])
14
+ result = decorator(target, key, result) || result;
15
+ if (result) __defProp(target, key, result);
16
+ return result;
17
+ };
18
+ function ContextMixin(superClass) {
19
+ class ContextElement extends superClass {
20
+ constructor() {
21
+ super(...arguments);
22
+ this.focusContext = this;
23
+ this.fetch = async (url, init = {}) => {
24
+ init.headers ||= {};
25
+ Object.assign(init.headers, {
26
+ "Content-Type": "application/json"
27
+ });
28
+ const bearerToken = this.apiToken;
29
+ if (bearerToken) {
30
+ Object.assign(init.headers, {
31
+ Authorization: `Bearer ${bearerToken}`
32
+ });
33
+ }
34
+ if (this.signingURL) {
35
+ if (!this.#URLTokens[url]) {
36
+ this.#URLTokens[url] = fetch(this.signingURL, {
37
+ method: "POST",
38
+ body: JSON.stringify({ url })
39
+ }).then(async (response) => {
40
+ if (response.ok) {
41
+ return (await response.json()).token;
42
+ }
43
+ throw new Error(
44
+ `Failed to sign URL: ${url}. SigningURL: ${this.signingURL} ${response.status} ${response.statusText}`
45
+ );
46
+ });
47
+ }
48
+ const urlToken = await this.#URLTokens[url];
49
+ Object.assign(init.headers, {
50
+ authorization: `Bearer ${urlToken}`
51
+ });
52
+ }
53
+ return fetch(url, init);
54
+ };
55
+ this.#URLTokens = {};
56
+ this.apiHost = "";
57
+ this.playing = false;
58
+ this.loop = false;
59
+ this.stageScale = 1;
60
+ this.rendering = false;
61
+ this.currentTimeMs = 0;
62
+ this.stageRef = createRef();
63
+ this.canvasRef = createRef();
64
+ this.setStageScale = () => {
65
+ if (this.isConnected && !this.rendering) {
66
+ const canvasElement = this.canvasRef.value;
67
+ const stageElement = this.stageRef.value;
68
+ if (stageElement && canvasElement) {
69
+ const stageWidth = stageElement.clientWidth;
70
+ const stageHeight = stageElement.clientHeight;
71
+ const canvasWidth = canvasElement.clientWidth;
72
+ const canvasHeight = canvasElement.clientHeight;
73
+ const stageRatio = stageWidth / stageHeight;
74
+ const canvasRatio = canvasWidth / canvasHeight;
75
+ if (stageRatio > canvasRatio) {
76
+ const scale = stageHeight / canvasHeight;
77
+ if (this.stageScale !== scale) {
78
+ canvasElement.style.transform = `scale(${scale})`;
79
+ }
80
+ this.stageScale = scale;
81
+ } else {
82
+ const scale = stageWidth / canvasWidth;
83
+ if (this.stageScale !== scale) {
84
+ canvasElement.style.transform = `scale(${scale})`;
85
+ }
86
+ this.stageScale = scale;
87
+ }
88
+ }
89
+ }
90
+ if (this.isConnected) {
91
+ requestAnimationFrame(this.setStageScale);
92
+ }
93
+ };
94
+ this.#playbackAudioContext = null;
95
+ this.#playbackAnimationFrameRequest = null;
96
+ this.#AUDIO_PLAYBACK_SLICE_MS = 1e3;
97
+ }
98
+ #URLTokens;
99
+ connectedCallback() {
100
+ super.connectedCallback();
101
+ requestAnimationFrame(this.setStageScale);
102
+ }
103
+ update(changedProperties) {
104
+ if (changedProperties.has("playing")) {
105
+ if (this.playing) {
106
+ this.#startPlayback();
107
+ } else {
108
+ this.#stopPlayback();
109
+ }
110
+ }
111
+ if (changedProperties.has("currentTimeMs") && this.targetTimegroup) {
112
+ if (this.targetTimegroup.currentTimeMs !== this.currentTimeMs) {
113
+ this.targetTimegroup.currentTimeMs = this.currentTimeMs;
114
+ }
115
+ }
116
+ super.update(changedProperties);
117
+ }
118
+ get targetTimegroup() {
119
+ return this.querySelector("ef-timegroup");
120
+ }
121
+ #playbackAudioContext;
122
+ #playbackAnimationFrameRequest;
123
+ #AUDIO_PLAYBACK_SLICE_MS;
124
+ #syncPlayheadToAudioContext(target, startMs) {
125
+ this.currentTimeMs = startMs + (this.#playbackAudioContext?.currentTime ?? 0) * 1e3;
126
+ this.#playbackAnimationFrameRequest = requestAnimationFrame(() => {
127
+ this.#syncPlayheadToAudioContext(target, startMs);
128
+ });
129
+ }
130
+ async #stopPlayback() {
131
+ if (this.#playbackAudioContext) {
132
+ if (this.#playbackAudioContext.state !== "closed") {
133
+ await this.#playbackAudioContext.close();
134
+ }
135
+ }
136
+ if (this.#playbackAnimationFrameRequest) {
137
+ cancelAnimationFrame(this.#playbackAnimationFrameRequest);
138
+ }
139
+ this.#playbackAudioContext = null;
140
+ }
141
+ async #startPlayback() {
142
+ await this.#stopPlayback();
143
+ const timegroup = this.targetTimegroup;
144
+ if (!timegroup) {
145
+ return;
146
+ }
147
+ let currentMs = timegroup.currentTimeMs;
148
+ let bufferCount = 0;
149
+ this.#playbackAudioContext = new AudioContext({
150
+ latencyHint: "playback"
151
+ });
152
+ if (this.#playbackAnimationFrameRequest) {
153
+ cancelAnimationFrame(this.#playbackAnimationFrameRequest);
154
+ }
155
+ this.#syncPlayheadToAudioContext(timegroup, currentMs);
156
+ const playbackContext = this.#playbackAudioContext;
157
+ await playbackContext.suspend();
158
+ const fillBuffer = async () => {
159
+ if (bufferCount > 1) {
160
+ return;
161
+ }
162
+ const canFillBuffer = await queueBufferSource();
163
+ if (canFillBuffer) {
164
+ fillBuffer();
165
+ }
166
+ };
167
+ const fromMs = currentMs;
168
+ const toMs = timegroup.endTimeMs;
169
+ const queueBufferSource = async () => {
170
+ if (currentMs >= toMs) {
171
+ return false;
172
+ }
173
+ const startMs = currentMs;
174
+ const endMs = currentMs + this.#AUDIO_PLAYBACK_SLICE_MS;
175
+ currentMs += this.#AUDIO_PLAYBACK_SLICE_MS;
176
+ const audioBuffer = await timegroup.renderAudio(startMs, endMs);
177
+ bufferCount++;
178
+ const source = playbackContext.createBufferSource();
179
+ source.buffer = audioBuffer;
180
+ source.connect(playbackContext.destination);
181
+ source.start((startMs - fromMs) / 1e3);
182
+ source.onended = () => {
183
+ bufferCount--;
184
+ if (endMs >= toMs) {
185
+ this.playing = false;
186
+ } else {
187
+ fillBuffer();
188
+ }
189
+ };
190
+ return true;
191
+ };
192
+ await fillBuffer();
193
+ await playbackContext.resume();
194
+ }
195
+ }
196
+ __decorateClass([
197
+ provide({ context: focusContext })
198
+ ], ContextElement.prototype, "focusContext");
199
+ __decorateClass([
200
+ provide({ context: focusedElementContext }),
201
+ state()
202
+ ], ContextElement.prototype, "focusedElement");
203
+ __decorateClass([
204
+ provide({ context: fetchContext })
205
+ ], ContextElement.prototype, "fetch");
206
+ __decorateClass([
207
+ property({ type: String })
208
+ ], ContextElement.prototype, "signingURL");
209
+ __decorateClass([
210
+ property({ type: String })
211
+ ], ContextElement.prototype, "apiToken");
212
+ __decorateClass([
213
+ provide({ context: apiHostContext }),
214
+ property({ type: String })
215
+ ], ContextElement.prototype, "apiHost");
216
+ __decorateClass([
217
+ provide({ context: playingContext }),
218
+ property({ type: Boolean, reflect: true })
219
+ ], ContextElement.prototype, "playing");
220
+ __decorateClass([
221
+ property({ type: Boolean, reflect: true })
222
+ ], ContextElement.prototype, "loop");
223
+ __decorateClass([
224
+ state()
225
+ ], ContextElement.prototype, "stageScale");
226
+ __decorateClass([
227
+ property({ type: Boolean })
228
+ ], ContextElement.prototype, "rendering");
229
+ __decorateClass([
230
+ state()
231
+ ], ContextElement.prototype, "currentTimeMs");
232
+ return ContextElement;
233
+ }
234
+ export {
235
+ ContextMixin
236
+ };