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