@editframe/elements 0.12.0-beta.8 → 0.13.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.
- package/dist/elements/EFAudio.d.ts +1 -1
- package/dist/elements/EFCaptions.d.ts +5 -5
- package/dist/elements/EFImage.d.ts +1 -1
- package/dist/elements/EFMedia.browsertest.d.ts +1 -1
- package/dist/elements/EFMedia.d.ts +6 -1
- package/dist/elements/{src/elements/EFMedia.js → EFMedia.js} +3 -3
- package/dist/elements/EFTemporal.browsertest.d.ts +1 -1
- package/dist/elements/EFTemporal.d.ts +145 -2
- package/dist/elements/{src/elements/EFTemporal.js → EFTemporal.js} +3 -0
- package/dist/elements/EFTimegroup.browsertest.d.ts +2 -2
- package/dist/elements/EFTimegroup.d.ts +8 -3
- package/dist/elements/{src/elements/EFTimegroup.js → EFTimegroup.js} +104 -53
- package/dist/elements/EFVideo.d.ts +1 -1
- package/dist/elements/{src/elements/EFVideo.js → EFVideo.js} +10 -2
- package/dist/elements/EFWaveform.d.ts +7 -4
- package/dist/elements/{src/elements/EFWaveform.js → EFWaveform.js} +48 -56
- package/dist/elements/TimegroupController.d.ts +2 -2
- package/dist/elements/util.d.ts +1 -1
- package/dist/gui/ContextMixin.browsertest.d.ts +1 -1
- package/dist/gui/ContextMixin.d.ts +4 -1
- package/dist/{elements/src/gui → gui}/ContextMixin.js +26 -42
- package/dist/gui/EFFilmstrip.d.ts +15 -9
- package/dist/{elements/src/gui → gui}/EFFilmstrip.js +64 -16
- package/dist/gui/EFFocusOverlay.d.ts +17 -0
- package/dist/gui/EFFocusOverlay.js +82 -0
- package/dist/gui/EFPreview.d.ts +3 -1
- package/dist/{elements/src/gui → gui}/EFPreview.js +24 -16
- package/dist/gui/EFScrubber.d.ts +1 -1
- package/dist/gui/EFTimeDisplay.d.ts +1 -1
- package/dist/gui/EFToggleLoop.d.ts +1 -1
- package/dist/gui/EFTogglePlay.d.ts +1 -1
- package/dist/gui/EFWorkbench.d.ts +1 -1
- package/dist/{elements/src/gui → gui}/TWMixin.css.js +1 -1
- package/dist/gui/efContext.d.ts +1 -1
- package/dist/index.d.ts +15 -14
- package/dist/{elements/src/index.js → index.js} +2 -0
- package/dist/style.css +769 -19
- package/package.json +5 -4
- package/src/elements/EFAudio.ts +3 -3
- package/src/elements/EFCaptions.browsertest.ts +3 -3
- package/src/elements/EFCaptions.ts +9 -9
- package/src/elements/EFImage.browsertest.ts +2 -2
- package/src/elements/EFImage.ts +4 -4
- package/src/elements/EFMedia.browsertest.ts +6 -6
- package/src/elements/EFMedia.ts +14 -7
- package/src/elements/EFSourceMixin.ts +3 -3
- package/src/elements/EFTemporal.browsertest.ts +1 -1
- package/src/elements/EFTemporal.ts +159 -4
- package/src/elements/EFTimegroup.browsertest.ts +5 -5
- package/src/elements/EFTimegroup.ts +141 -68
- package/src/elements/EFVideo.ts +15 -4
- package/src/elements/EFWaveform.ts +82 -98
- package/src/elements/FetchMixin.ts +2 -2
- package/src/elements/TimegroupController.ts +2 -2
- package/src/elements/durationConverter.ts +1 -1
- package/src/elements/util.ts +1 -1
- package/src/gui/ContextMixin.browsertest.ts +3 -3
- package/src/gui/ContextMixin.ts +37 -49
- package/src/gui/EFFilmstrip.ts +92 -36
- package/src/gui/EFFocusOverlay.ts +79 -0
- package/src/gui/EFPreview.ts +35 -18
- package/src/gui/EFScrubber.ts +3 -3
- package/src/gui/EFTimeDisplay.ts +2 -2
- package/src/gui/EFToggleLoop.ts +4 -4
- package/src/gui/EFTogglePlay.ts +3 -3
- package/src/gui/EFWorkbench.ts +2 -2
- package/src/gui/efContext.ts +1 -1
- package/dist/assets/src/EncodedAsset.js +0 -560
- package/dist/assets/src/MP4File.js +0 -223
- package/dist/assets/src/memoize.js +0 -14
- package/dist/{elements/src/EF_FRAMEGEN.js → EF_FRAMEGEN.js} +0 -0
- package/dist/{elements/src/EF_INTERACTIVE.js → EF_INTERACTIVE.js} +0 -0
- package/dist/{elements/src/EF_RENDERING.js → EF_RENDERING.js} +0 -0
- package/dist/elements/{src/elements/CrossUpdateController.js → CrossUpdateController.js} +0 -0
- package/dist/elements/{src/elements/EFAudio.js → EFAudio.js} +2 -2
- package/dist/elements/{src/elements/EFCaptions.js → EFCaptions.js} +0 -0
- package/dist/elements/{src/elements/EFImage.js → EFImage.js} +0 -0
- package/dist/elements/{src/elements/EFSourceMixin.js → EFSourceMixin.js} +1 -1
- package/dist/elements/{src/elements/FetchMixin.js → FetchMixin.js} +0 -0
- package/dist/elements/{src/elements/TimegroupController.js → TimegroupController.js} +0 -0
- package/dist/elements/{src/elements/durationConverter.js → durationConverter.js} +0 -0
- package/dist/elements/{src/elements/parseTimeToMs.js → parseTimeToMs.js} +0 -0
- package/dist/{elements/src/gui → gui}/EFScrubber.js +0 -0
- package/dist/{elements/src/gui → gui}/EFTimeDisplay.js +0 -0
- package/dist/{elements/src/gui → gui}/EFToggleLoop.js +1 -1
- /package/dist/{elements/src/gui → gui}/EFTogglePlay.js +0 -0
- /package/dist/{elements/src/gui → gui}/EFWorkbench.js +0 -0
- /package/dist/{elements/src/gui → gui}/TWMixin.js +0 -0
- /package/dist/{elements/src/gui → gui}/apiHostContext.js +0 -0
- /package/dist/{elements/src/gui → gui}/efContext.js +0 -0
- /package/dist/{elements/src/gui → gui}/fetchContext.js +0 -0
- /package/dist/{elements/src/gui → gui}/focusContext.js +0 -0
- /package/dist/{elements/src/gui → gui}/focusedElementContext.js +0 -0
- /package/dist/{elements/src/gui → gui}/playingContext.js +0 -0
- /package/dist/{elements/src/msToTimeCode.js → msToTimeCode.js} +0 -0
|
@@ -26,53 +26,39 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
26
26
|
this.mode = "bars";
|
|
27
27
|
this.color = "currentColor";
|
|
28
28
|
this.targetSelector = "";
|
|
29
|
-
this.lastFrameTime = 0;
|
|
30
29
|
this.frameTask = new Task(this, {
|
|
31
30
|
autoRun: EF_INTERACTIVE,
|
|
32
31
|
args: () => [this.targetElement.audioBufferTask.status],
|
|
33
32
|
task: async () => {
|
|
34
|
-
const currentTime = performance.now();
|
|
35
|
-
const timeSinceLastFrame = this.lastFrameTime ? currentTime - this.lastFrameTime : 0;
|
|
36
|
-
console.log(`Time since last frame: ${timeSinceLastFrame.toFixed(2)}ms`);
|
|
37
|
-
this.lastFrameTime = currentTime;
|
|
38
33
|
await this.targetElement.audioBufferTask.taskComplete;
|
|
39
34
|
this.ctx ||= this.initCanvas();
|
|
40
35
|
const ctx = this.ctx;
|
|
41
36
|
if (!ctx) return;
|
|
42
37
|
if (!this.targetElement.audioBufferTask.value) return;
|
|
43
38
|
if (this.targetElement.trimAdjustedOwnCurrentTimeMs > 0) {
|
|
44
|
-
const
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const smoothedData = new Uint8Array(dataLength);
|
|
68
|
-
for (let i = 0; i < smoothedData.length; i++) {
|
|
69
|
-
let sum = 0;
|
|
70
|
-
for (const frameData of multiFrameData) {
|
|
71
|
-
sum += frameData[i] ?? 0;
|
|
72
|
-
}
|
|
73
|
-
let avg = sum / FRAMES_TO_ANALYZE;
|
|
74
|
-
avg = (avg / 255) ** 1.2 * 255;
|
|
75
|
-
smoothedData[i] = Math.round(avg);
|
|
39
|
+
const FRAME_DURATION_MS = 48e3 / 1e3;
|
|
40
|
+
const FRAME_SMEAR_MS = FRAME_DURATION_MS * 1;
|
|
41
|
+
const FRAME_SMEAR_S = FRAME_SMEAR_MS / 1e3;
|
|
42
|
+
const audioContext = new OfflineAudioContext(2, 48e3 / 25, 48e3);
|
|
43
|
+
const audioBufferSource = audioContext.createBufferSource();
|
|
44
|
+
audioBufferSource.buffer = this.targetElement.audioBufferTask.value.buffer;
|
|
45
|
+
const analyser = audioContext.createAnalyser();
|
|
46
|
+
analyser.fftSize = 128 * 8;
|
|
47
|
+
audioBufferSource.connect(analyser);
|
|
48
|
+
const startTime = Math.max(
|
|
49
|
+
0,
|
|
50
|
+
(this.targetElement.trimAdjustedOwnCurrentTimeMs - this.targetElement.audioBufferTask.value.startOffsetMs) / 1e3
|
|
51
|
+
);
|
|
52
|
+
audioBufferSource.start(0, startTime, FRAME_SMEAR_S);
|
|
53
|
+
await audioContext.startRendering();
|
|
54
|
+
const frameData = new Uint8Array(analyser.frequencyBinCount);
|
|
55
|
+
analyser.getByteFrequencyData(frameData);
|
|
56
|
+
const smoothedData = frameData.slice(0, frameData.length / 2);
|
|
57
|
+
if (this.color === "currentColor") {
|
|
58
|
+
const computedStyle = getComputedStyle(this);
|
|
59
|
+
const currentColor = computedStyle.color;
|
|
60
|
+
ctx.strokeStyle = currentColor;
|
|
61
|
+
ctx.fillStyle = currentColor;
|
|
76
62
|
}
|
|
77
63
|
switch (this.mode) {
|
|
78
64
|
case "bars":
|
|
@@ -118,9 +104,31 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
118
104
|
if (this.targetElement) {
|
|
119
105
|
new CrossUpdateController(this.targetElement, this);
|
|
120
106
|
}
|
|
107
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
108
|
+
this.resizeCanvas();
|
|
109
|
+
});
|
|
110
|
+
this.resizeObserver.observe(this);
|
|
111
|
+
this.mutationObserver = new MutationObserver((mutationsList) => {
|
|
112
|
+
for (const mutation of mutationsList) {
|
|
113
|
+
if (mutation.type === "attributes") {
|
|
114
|
+
this.frameTask.run();
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
this.mutationObserver.observe(this, { attributes: true });
|
|
119
|
+
}
|
|
120
|
+
disconnectedCallback() {
|
|
121
|
+
super.disconnectedCallback();
|
|
122
|
+
this.resizeObserver?.disconnect();
|
|
123
|
+
this.mutationObserver?.disconnect();
|
|
124
|
+
}
|
|
125
|
+
resizeCanvas() {
|
|
126
|
+
this.ctx = this.initCanvas();
|
|
127
|
+
if (this.ctx) {
|
|
128
|
+
this.frameTask.run();
|
|
129
|
+
}
|
|
121
130
|
}
|
|
122
131
|
initCanvas() {
|
|
123
|
-
console.count("initCanvas");
|
|
124
132
|
const canvas = this.canvasRef.value;
|
|
125
133
|
if (!canvas) return null;
|
|
126
134
|
const rect = this.getBoundingClientRect();
|
|
@@ -135,8 +143,6 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
135
143
|
return ctx;
|
|
136
144
|
}
|
|
137
145
|
drawBars(ctx, frequencyData) {
|
|
138
|
-
ctx.strokeStyle = this.color;
|
|
139
|
-
ctx.fillStyle = this.color;
|
|
140
146
|
const canvas = ctx.canvas;
|
|
141
147
|
const waveWidth = canvas.width / devicePixelRatio;
|
|
142
148
|
const waveHeight = canvas.height / devicePixelRatio;
|
|
@@ -151,8 +157,6 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
151
157
|
});
|
|
152
158
|
}
|
|
153
159
|
drawBricks(ctx, frequencyData) {
|
|
154
|
-
ctx.strokeStyle = this.color;
|
|
155
|
-
ctx.fillStyle = this.color;
|
|
156
160
|
const canvas = ctx.canvas;
|
|
157
161
|
const waveWidth = canvas.width / devicePixelRatio;
|
|
158
162
|
const waveHeight = canvas.height / devicePixelRatio;
|
|
@@ -176,8 +180,6 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
176
180
|
});
|
|
177
181
|
}
|
|
178
182
|
drawLine(ctx, frequencyData) {
|
|
179
|
-
ctx.strokeStyle = this.color;
|
|
180
|
-
ctx.fillStyle = this.color;
|
|
181
183
|
const canvas = ctx.canvas;
|
|
182
184
|
const waveWidth = canvas.width / devicePixelRatio;
|
|
183
185
|
const waveHeight = canvas.height / devicePixelRatio;
|
|
@@ -196,8 +198,6 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
196
198
|
ctx.stroke();
|
|
197
199
|
}
|
|
198
200
|
drawRoundBars(ctx, frequencyData) {
|
|
199
|
-
ctx.strokeStyle = this.color;
|
|
200
|
-
ctx.fillStyle = this.color;
|
|
201
201
|
const canvas = ctx.canvas;
|
|
202
202
|
const waveWidth = canvas.width / devicePixelRatio;
|
|
203
203
|
const waveHeight = canvas.height / devicePixelRatio;
|
|
@@ -216,8 +216,6 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
216
216
|
});
|
|
217
217
|
}
|
|
218
218
|
drawEqualizer(ctx, frequencyData) {
|
|
219
|
-
ctx.strokeStyle = this.color;
|
|
220
|
-
ctx.fillStyle = this.color;
|
|
221
219
|
const canvas = ctx.canvas;
|
|
222
220
|
const waveWidth = canvas.width / devicePixelRatio;
|
|
223
221
|
const waveHeight = canvas.height / devicePixelRatio;
|
|
@@ -237,8 +235,6 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
237
235
|
});
|
|
238
236
|
}
|
|
239
237
|
drawCurve(ctx, frequencyData) {
|
|
240
|
-
ctx.strokeStyle = this.color;
|
|
241
|
-
ctx.fillStyle = this.color;
|
|
242
238
|
const canvas = ctx.canvas;
|
|
243
239
|
const waveWidth = canvas.width / devicePixelRatio;
|
|
244
240
|
const waveHeight = canvas.height / devicePixelRatio;
|
|
@@ -257,8 +253,6 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
257
253
|
ctx.stroke();
|
|
258
254
|
}
|
|
259
255
|
drawPixel(ctx, frequencyData) {
|
|
260
|
-
ctx.strokeStyle = this.color;
|
|
261
|
-
ctx.fillStyle = this.color;
|
|
262
256
|
const canvas = ctx.canvas;
|
|
263
257
|
const waveWidth = canvas.width / devicePixelRatio;
|
|
264
258
|
const waveHeight = canvas.height / devicePixelRatio;
|
|
@@ -273,8 +267,6 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
273
267
|
});
|
|
274
268
|
}
|
|
275
269
|
drawWave(ctx, frequencyData) {
|
|
276
|
-
ctx.strokeStyle = this.color;
|
|
277
|
-
ctx.fillStyle = this.color;
|
|
278
270
|
const canvas = ctx.canvas;
|
|
279
271
|
const waveWidth = canvas.width / devicePixelRatio;
|
|
280
272
|
const waveHeight = canvas.height / devicePixelRatio;
|
|
@@ -285,7 +277,7 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
285
277
|
ctx.moveTo(0, baseline);
|
|
286
278
|
ctx.lineTo(waveWidth, baseline);
|
|
287
279
|
ctx.strokeStyle = this.color;
|
|
288
|
-
ctx.lineWidth =
|
|
280
|
+
ctx.lineWidth = 1;
|
|
289
281
|
ctx.stroke();
|
|
290
282
|
frequencyData.forEach((value, i) => {
|
|
291
283
|
const x = i * (waveWidth / frequencyData.length);
|
|
@@ -306,7 +298,7 @@ let EFWaveform = class extends EFTemporal(TWMixin(LitElement)) {
|
|
|
306
298
|
}
|
|
307
299
|
updated(changedProperties) {
|
|
308
300
|
super.updated(changedProperties);
|
|
309
|
-
if (changedProperties.
|
|
301
|
+
if (changedProperties.size > 0) {
|
|
310
302
|
this.frameTask.run();
|
|
311
303
|
}
|
|
312
304
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { EFTimegroup } from './EFTimegroup.
|
|
1
|
+
import { LitElement, ReactiveController } from 'lit';
|
|
2
|
+
import { EFTimegroup } from './EFTimegroup.js';
|
|
3
3
|
export declare class TimegroupController implements ReactiveController {
|
|
4
4
|
private host;
|
|
5
5
|
private child;
|
package/dist/elements/util.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
|
-
declare const TestContext_base: (new (...args: any[]) => import('./ContextMixin.
|
|
2
|
+
declare const TestContext_base: (new (...args: any[]) => import('./ContextMixin.js').ContextMixinInterface) & typeof LitElement;
|
|
3
3
|
declare class TestContext extends TestContext_base {
|
|
4
4
|
}
|
|
5
5
|
declare global {
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
2
|
import { createRef } from 'lit/directives/ref.js';
|
|
3
|
-
import { EFTimegroup } from '../elements/EFTimegroup.
|
|
3
|
+
import { EFTimegroup } from '../elements/EFTimegroup.js';
|
|
4
|
+
export declare const targetTimegroupContext: {
|
|
5
|
+
__context__: EFTimegroup | null;
|
|
6
|
+
};
|
|
4
7
|
export declare class ContextMixinInterface extends LitElement {
|
|
5
8
|
signingURL?: string;
|
|
6
9
|
apiHost?: string;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { provide } from "@lit/context";
|
|
1
|
+
import { createContext, provide } from "@lit/context";
|
|
2
2
|
import { state, property } from "lit/decorators.js";
|
|
3
3
|
import { createRef } from "lit/directives/ref.js";
|
|
4
4
|
import { apiHostContext } from "./apiHostContext.js";
|
|
@@ -16,6 +16,9 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
16
16
|
if (result) __defProp(target, key, result);
|
|
17
17
|
return result;
|
|
18
18
|
};
|
|
19
|
+
const targetTimegroupContext = createContext(
|
|
20
|
+
"target-timegroup"
|
|
21
|
+
);
|
|
19
22
|
const contextMixinSymbol = Symbol("contextMixin");
|
|
20
23
|
function isContextMixin(value) {
|
|
21
24
|
return typeof value === "object" && value !== null && contextMixinSymbol in value.constructor;
|
|
@@ -27,6 +30,7 @@ function ContextMixin(superClass) {
|
|
|
27
30
|
super(...arguments);
|
|
28
31
|
this.focusContext = this;
|
|
29
32
|
this.efContext = this;
|
|
33
|
+
this.targetTimegroup = null;
|
|
30
34
|
this.fetch = async (url, init = {}) => {
|
|
31
35
|
init.headers ||= {};
|
|
32
36
|
Object.assign(init.headers, {
|
|
@@ -58,48 +62,22 @@ function ContextMixin(superClass) {
|
|
|
58
62
|
this.#URLTokens = {};
|
|
59
63
|
this.playing = false;
|
|
60
64
|
this.loop = false;
|
|
61
|
-
this.stageScale = 1;
|
|
62
65
|
this.rendering = false;
|
|
63
66
|
this.currentTimeMs = 0;
|
|
64
67
|
this.stageRef = createRef();
|
|
65
68
|
this.canvasRef = createRef();
|
|
66
69
|
this.#FPS = 30;
|
|
67
70
|
this.#MS_PER_FRAME = 1e3 / this.#FPS;
|
|
68
|
-
this
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
canvasElement.style.width = `${canvasChild.clientWidth}px`;
|
|
75
|
-
canvasElement.style.height = `${canvasChild.clientHeight}px`;
|
|
76
|
-
const stageWidth = stageElement.clientWidth;
|
|
77
|
-
const stageHeight = stageElement.clientHeight;
|
|
78
|
-
const canvasWidth = canvasElement.clientWidth;
|
|
79
|
-
const canvasHeight = canvasElement.clientHeight;
|
|
80
|
-
const stageRatio = stageWidth / stageHeight;
|
|
81
|
-
const canvasRatio = canvasWidth / canvasHeight;
|
|
82
|
-
if (stageRatio > canvasRatio) {
|
|
83
|
-
const scale = stageHeight / canvasHeight;
|
|
84
|
-
if (this.stageScale !== scale) {
|
|
85
|
-
canvasElement.style.transform = `scale(${scale})`;
|
|
86
|
-
canvasElement.style.transformOrigin = "center left";
|
|
87
|
-
}
|
|
88
|
-
this.stageScale = scale;
|
|
89
|
-
} else {
|
|
90
|
-
const scale = stageWidth / canvasWidth;
|
|
91
|
-
if (this.stageScale !== scale) {
|
|
92
|
-
canvasElement.style.transform = `scale(${scale})`;
|
|
93
|
-
canvasElement.style.transformOrigin = "center left";
|
|
94
|
-
}
|
|
95
|
-
this.stageScale = scale;
|
|
71
|
+
this.#timegroupObserver = new MutationObserver((mutations) => {
|
|
72
|
+
for (const mutation of mutations) {
|
|
73
|
+
if (mutation.type === "childList") {
|
|
74
|
+
const newTimegroup = this.querySelector("ef-timegroup");
|
|
75
|
+
if (newTimegroup !== this.targetTimegroup) {
|
|
76
|
+
this.targetTimegroup = newTimegroup;
|
|
96
77
|
}
|
|
97
78
|
}
|
|
98
79
|
}
|
|
99
|
-
|
|
100
|
-
requestAnimationFrame(this.setStageScale);
|
|
101
|
-
}
|
|
102
|
-
};
|
|
80
|
+
});
|
|
103
81
|
this.#playbackAudioContext = null;
|
|
104
82
|
this.#playbackAnimationFrameRequest = null;
|
|
105
83
|
this.#AUDIO_PLAYBACK_SLICE_MS = 1e3;
|
|
@@ -110,15 +88,22 @@ function ContextMixin(superClass) {
|
|
|
110
88
|
#URLTokens;
|
|
111
89
|
#FPS;
|
|
112
90
|
#MS_PER_FRAME;
|
|
91
|
+
#timegroupObserver;
|
|
113
92
|
connectedCallback() {
|
|
114
93
|
super.connectedCallback();
|
|
115
|
-
|
|
94
|
+
this.targetTimegroup = this.querySelector("ef-timegroup");
|
|
95
|
+
this.#timegroupObserver.observe(this, {
|
|
96
|
+
childList: true,
|
|
97
|
+
subtree: true,
|
|
98
|
+
attributes: true
|
|
99
|
+
});
|
|
116
100
|
if (this.playing) {
|
|
117
101
|
this.startPlayback();
|
|
118
102
|
}
|
|
119
103
|
}
|
|
120
104
|
disconnectedCallback() {
|
|
121
105
|
super.disconnectedCallback();
|
|
106
|
+
this.#timegroupObserver.disconnect();
|
|
122
107
|
this.stopPlayback();
|
|
123
108
|
}
|
|
124
109
|
update(changedProperties) {
|
|
@@ -146,9 +131,6 @@ function ContextMixin(superClass) {
|
|
|
146
131
|
}
|
|
147
132
|
super.update(changedProperties);
|
|
148
133
|
}
|
|
149
|
-
get targetTimegroup() {
|
|
150
|
-
return this.querySelector("ef-timegroup");
|
|
151
|
-
}
|
|
152
134
|
play() {
|
|
153
135
|
this.playing = true;
|
|
154
136
|
}
|
|
@@ -268,6 +250,10 @@ function ContextMixin(superClass) {
|
|
|
268
250
|
__decorateClass([
|
|
269
251
|
provide({ context: efContext })
|
|
270
252
|
], ContextElement.prototype, "efContext");
|
|
253
|
+
__decorateClass([
|
|
254
|
+
provide({ context: targetTimegroupContext }),
|
|
255
|
+
state()
|
|
256
|
+
], ContextElement.prototype, "targetTimegroup");
|
|
271
257
|
__decorateClass([
|
|
272
258
|
provide({ context: fetchContext })
|
|
273
259
|
], ContextElement.prototype, "fetch");
|
|
@@ -282,9 +268,6 @@ function ContextMixin(superClass) {
|
|
|
282
268
|
provide({ context: loopContext }),
|
|
283
269
|
property({ type: Boolean, reflect: true })
|
|
284
270
|
], ContextElement.prototype, "loop");
|
|
285
|
-
__decorateClass([
|
|
286
|
-
state()
|
|
287
|
-
], ContextElement.prototype, "stageScale");
|
|
288
271
|
__decorateClass([
|
|
289
272
|
property({ type: Boolean })
|
|
290
273
|
], ContextElement.prototype, "rendering");
|
|
@@ -295,5 +278,6 @@ function ContextMixin(superClass) {
|
|
|
295
278
|
}
|
|
296
279
|
export {
|
|
297
280
|
ContextMixin,
|
|
298
|
-
isContextMixin
|
|
281
|
+
isContextMixin,
|
|
282
|
+
targetTimegroupContext
|
|
299
283
|
};
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { LitElement, PropertyValueMap, ReactiveController, TemplateResult, nothing } from 'lit';
|
|
2
|
-
import { EFAudio } from '../elements/EFAudio.
|
|
3
|
-
import { EFImage } from '../elements/EFImage.
|
|
4
|
-
import { TemporalMixinInterface } from '../elements/EFTemporal.
|
|
5
|
-
import { EFTimegroup } from '../elements/EFTimegroup.
|
|
6
|
-
import { EFVideo } from '../elements/EFVideo.
|
|
7
|
-
import { TimegroupController } from '../elements/TimegroupController.
|
|
8
|
-
import { FocusContext } from './focusContext.
|
|
2
|
+
import { EFAudio } from '../elements/EFAudio.js';
|
|
3
|
+
import { EFImage } from '../elements/EFImage.js';
|
|
4
|
+
import { TemporalMixinInterface } from '../elements/EFTemporal.js';
|
|
5
|
+
import { EFTimegroup } from '../elements/EFTimegroup.js';
|
|
6
|
+
import { EFVideo } from '../elements/EFVideo.js';
|
|
7
|
+
import { TimegroupController } from '../elements/TimegroupController.js';
|
|
8
|
+
import { FocusContext } from './focusContext.js';
|
|
9
9
|
declare class ElementFilmstripController implements ReactiveController {
|
|
10
10
|
private host;
|
|
11
11
|
private filmstrip;
|
|
@@ -69,7 +69,7 @@ declare class EFHierarchyItem<ElementType extends HTMLElement = HTMLElement> ext
|
|
|
69
69
|
get isFocused(): boolean;
|
|
70
70
|
displayLabel(): TemplateResult<1> | string | typeof nothing;
|
|
71
71
|
render(): TemplateResult<1>;
|
|
72
|
-
renderChildren(): Array<TemplateResult<1
|
|
72
|
+
renderChildren(): Array<TemplateResult<1> | typeof nothing> | typeof nothing;
|
|
73
73
|
}
|
|
74
74
|
declare class EFTimegroupHierarchyItem extends EFHierarchyItem<EFTimegroup> {
|
|
75
75
|
get icon(): string;
|
|
@@ -103,6 +103,7 @@ declare class EFHTMLHierarchyItem extends EFHierarchyItem {
|
|
|
103
103
|
declare const EFFilmstrip_base: typeof LitElement;
|
|
104
104
|
export declare class EFFilmstrip extends EFFilmstrip_base {
|
|
105
105
|
#private;
|
|
106
|
+
static styles: import('lit').CSSResult[];
|
|
106
107
|
pixelsPerMs: number;
|
|
107
108
|
scrubbing: boolean;
|
|
108
109
|
timelineScrolltop: number;
|
|
@@ -110,8 +111,11 @@ export declare class EFFilmstrip extends EFFilmstrip_base {
|
|
|
110
111
|
loop?: boolean;
|
|
111
112
|
timegroupController?: TimegroupController;
|
|
112
113
|
currentTimeMs: number;
|
|
114
|
+
autoScale: boolean;
|
|
115
|
+
private resizeObserver;
|
|
113
116
|
connectedCallback(): void;
|
|
114
117
|
disconnectedCallback(): void;
|
|
118
|
+
updatePixelsPerMs(): void;
|
|
115
119
|
syncGutterScroll(): void;
|
|
116
120
|
syncHierarchyScroll(): void;
|
|
117
121
|
scrub(e: MouseEvent): void;
|
|
@@ -123,7 +127,9 @@ export declare class EFFilmstrip extends EFFilmstrip_base {
|
|
|
123
127
|
get gutter(): HTMLDivElement | undefined;
|
|
124
128
|
render(): TemplateResult<1>;
|
|
125
129
|
updated(changes: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
|
|
126
|
-
|
|
130
|
+
target?: string;
|
|
131
|
+
targetTimegroup?: EFTimegroup | null;
|
|
132
|
+
protected willUpdate(changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>): void;
|
|
127
133
|
}
|
|
128
134
|
declare global {
|
|
129
135
|
interface HTMLElementTagNameMap {
|
|
@@ -11,6 +11,7 @@ import { EFVideo } from "../elements/EFVideo.js";
|
|
|
11
11
|
import { EFWaveform } from "../elements/EFWaveform.js";
|
|
12
12
|
import { TimegroupController } from "../elements/TimegroupController.js";
|
|
13
13
|
import { msToTimeCode } from "../msToTimeCode.js";
|
|
14
|
+
import { targetTimegroupContext } from "./ContextMixin.js";
|
|
14
15
|
import { TWMixin } from "./TWMixin.js";
|
|
15
16
|
import { focusContext } from "./focusContext.js";
|
|
16
17
|
import { focusedElementContext } from "./focusedElementContext.js";
|
|
@@ -410,6 +411,9 @@ EFHTMLHierarchyItem = __decorateClass([
|
|
|
410
411
|
], EFHTMLHierarchyItem);
|
|
411
412
|
const renderHierarchyChildren = (children) => {
|
|
412
413
|
return children.map((child) => {
|
|
414
|
+
if (child instanceof HTMLElement && child.dataset?.efHidden) {
|
|
415
|
+
return nothing;
|
|
416
|
+
}
|
|
413
417
|
if (child instanceof EFTimegroup) {
|
|
414
418
|
return html`<ef-timegroup-hierarchy-item
|
|
415
419
|
.element=${child}
|
|
@@ -452,6 +456,9 @@ const renderHierarchyChildren = (children) => {
|
|
|
452
456
|
};
|
|
453
457
|
const renderFilmstripChildren = (children, pixelsPerMs) => {
|
|
454
458
|
return children.map((child) => {
|
|
459
|
+
if (child instanceof HTMLElement && child.dataset?.efHidden) {
|
|
460
|
+
return nothing;
|
|
461
|
+
}
|
|
455
462
|
if (child instanceof EFTimegroup) {
|
|
456
463
|
return html`<ef-timegroup-filmstrip
|
|
457
464
|
.element=${child}
|
|
@@ -503,6 +510,12 @@ let EFFilmstrip = class extends TWMixin(LitElement) {
|
|
|
503
510
|
this.scrubbing = false;
|
|
504
511
|
this.timelineScrolltop = 0;
|
|
505
512
|
this.currentTimeMs = 0;
|
|
513
|
+
this.autoScale = false;
|
|
514
|
+
this.resizeObserver = new ResizeObserver(() => {
|
|
515
|
+
if (this.autoScale) {
|
|
516
|
+
this.updatePixelsPerMs();
|
|
517
|
+
}
|
|
518
|
+
});
|
|
506
519
|
__privateAdd(this, _handleKeyPress, (event) => {
|
|
507
520
|
if (event.key === " ") {
|
|
508
521
|
const [target] = event.composedPath();
|
|
@@ -527,10 +540,19 @@ let EFFilmstrip = class extends TWMixin(LitElement) {
|
|
|
527
540
|
super.connectedCallback();
|
|
528
541
|
__privateMethod(this, _EFFilmstrip_instances, bindToTargetTimegroup_fn).call(this);
|
|
529
542
|
window.addEventListener("keypress", __privateGet(this, _handleKeyPress));
|
|
543
|
+
this.resizeObserver.observe(this);
|
|
530
544
|
}
|
|
531
545
|
disconnectedCallback() {
|
|
532
546
|
super.disconnectedCallback();
|
|
533
547
|
window.removeEventListener("keypress", __privateGet(this, _handleKeyPress));
|
|
548
|
+
this.resizeObserver.disconnect();
|
|
549
|
+
}
|
|
550
|
+
updatePixelsPerMs() {
|
|
551
|
+
const target = this.targetTimegroup;
|
|
552
|
+
const gutter = this.gutterRef.value;
|
|
553
|
+
if (target && gutter && gutter.clientWidth > 0) {
|
|
554
|
+
this.pixelsPerMs = gutter.clientWidth / (target.durationMs || 1);
|
|
555
|
+
}
|
|
534
556
|
}
|
|
535
557
|
syncGutterScroll() {
|
|
536
558
|
if (this.gutter && this.hierarchyRef.value) {
|
|
@@ -585,7 +607,9 @@ let EFFilmstrip = class extends TWMixin(LitElement) {
|
|
|
585
607
|
}
|
|
586
608
|
scrollScrub(e) {
|
|
587
609
|
if (this.targetTimegroup && this.gutter && !this.playing) {
|
|
588
|
-
e.
|
|
610
|
+
if (e.deltaX !== 0) {
|
|
611
|
+
e.preventDefault();
|
|
612
|
+
}
|
|
589
613
|
if (this.gutterRef.value && this.gutterRef.value.scrollLeft === 0 && e.deltaX < 0) {
|
|
590
614
|
this.gutter.scrollBy(0, e.deltaY);
|
|
591
615
|
return;
|
|
@@ -615,38 +639,38 @@ let EFFilmstrip = class extends TWMixin(LitElement) {
|
|
|
615
639
|
<div
|
|
616
640
|
class="z-20 col-span-2 border-b-slate-600 bg-slate-100 shadow shadow-slate-300"
|
|
617
641
|
>
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
642
|
+
${!this.autoScale ? html`<input
|
|
643
|
+
type="range"
|
|
644
|
+
.value=${this.pixelsPerMs}
|
|
645
|
+
min="0.01"
|
|
646
|
+
max="0.1"
|
|
647
|
+
step="0.001"
|
|
648
|
+
@input=${(e) => {
|
|
625
649
|
const target2 = e.target;
|
|
626
650
|
this.pixelsPerMs = Number.parseFloat(target2.value);
|
|
627
651
|
}}
|
|
628
|
-
|
|
652
|
+
/>` : nothing}
|
|
629
653
|
<code>${msToTimeCode(this.currentTimeMs, true)} </code> /
|
|
630
654
|
<code>${msToTimeCode(target?.durationMs ?? 0, true)}</code>
|
|
631
655
|
<ef-toggle-play class="inline-block mx-2">
|
|
632
656
|
<div slot="pause">
|
|
633
|
-
<button
|
|
657
|
+
<button>⏸️</button>
|
|
634
658
|
</div>
|
|
635
659
|
<div slot="play">
|
|
636
|
-
<button
|
|
660
|
+
<button>▶️</button>
|
|
637
661
|
</div>
|
|
638
662
|
</ef-toggle-play>
|
|
639
|
-
<ef-toggle-loop><button>${this.loop ? "🔁" : html`<span class="opacity-50">🔁</span>`}</button></ef-toggle-loop>
|
|
663
|
+
<ef-toggle-loop><button>${this.loop ? "🔁" : html`<span class="opacity-50 line-through">🔁</span>`}</button></ef-toggle-loop>
|
|
640
664
|
</div>
|
|
641
665
|
<div
|
|
642
|
-
class="z-10 pl-1 pr-1 pt-
|
|
666
|
+
class="z-10 pl-1 pr-1 pt-[8px] shadow shadow-slate-600 overflow-auto"
|
|
643
667
|
${ref(this.hierarchyRef)}
|
|
644
668
|
@scroll=${this.syncHierarchyScroll}
|
|
645
669
|
>
|
|
646
670
|
${renderHierarchyChildren(target ? [target] : [])}
|
|
647
671
|
</div>
|
|
648
672
|
<div
|
|
649
|
-
class="h-full w-full cursor-crosshair overflow-auto bg-slate-200 pt-
|
|
673
|
+
class="flex h-full w-full cursor-crosshair overflow-auto bg-slate-200 pt-[8px]"
|
|
650
674
|
id="gutter"
|
|
651
675
|
${ref(this.gutterRef)}
|
|
652
676
|
@scroll=${this.syncGutterScroll}
|
|
@@ -682,8 +706,14 @@ let EFFilmstrip = class extends TWMixin(LitElement) {
|
|
|
682
706
|
}
|
|
683
707
|
}
|
|
684
708
|
}
|
|
685
|
-
|
|
686
|
-
|
|
709
|
+
willUpdate(changedProperties) {
|
|
710
|
+
if (changedProperties.has("targetTimegroup")) {
|
|
711
|
+
__privateMethod(this, _EFFilmstrip_instances, bindToTargetTimegroup_fn).call(this);
|
|
712
|
+
}
|
|
713
|
+
if (this.autoScale) {
|
|
714
|
+
this.updatePixelsPerMs();
|
|
715
|
+
}
|
|
716
|
+
super.willUpdate(changedProperties);
|
|
687
717
|
}
|
|
688
718
|
};
|
|
689
719
|
_EFFilmstrip_instances = /* @__PURE__ */ new WeakSet();
|
|
@@ -701,6 +731,14 @@ _handleKeyPress = /* @__PURE__ */ new WeakMap();
|
|
|
701
731
|
contextElement_get = function() {
|
|
702
732
|
return this.closest("ef-workbench, ef-preview");
|
|
703
733
|
};
|
|
734
|
+
EFFilmstrip.styles = [
|
|
735
|
+
css`
|
|
736
|
+
:host {
|
|
737
|
+
display: block;
|
|
738
|
+
overflow: hidden;
|
|
739
|
+
}
|
|
740
|
+
`
|
|
741
|
+
];
|
|
704
742
|
__decorateClass([
|
|
705
743
|
property({ type: Number })
|
|
706
744
|
], EFFilmstrip.prototype, "pixelsPerMs", 2);
|
|
@@ -721,6 +759,9 @@ __decorateClass([
|
|
|
721
759
|
__decorateClass([
|
|
722
760
|
state()
|
|
723
761
|
], EFFilmstrip.prototype, "currentTimeMs", 2);
|
|
762
|
+
__decorateClass([
|
|
763
|
+
property({ type: Boolean, reflect: true, attribute: "auto-scale" })
|
|
764
|
+
], EFFilmstrip.prototype, "autoScale", 2);
|
|
724
765
|
__decorateClass([
|
|
725
766
|
eventOptions({ passive: false })
|
|
726
767
|
], EFFilmstrip.prototype, "syncGutterScroll", 1);
|
|
@@ -736,6 +777,13 @@ __decorateClass([
|
|
|
736
777
|
__decorateClass([
|
|
737
778
|
eventOptions({ passive: false })
|
|
738
779
|
], EFFilmstrip.prototype, "scrollScrub", 1);
|
|
780
|
+
__decorateClass([
|
|
781
|
+
property({ type: String })
|
|
782
|
+
], EFFilmstrip.prototype, "target", 2);
|
|
783
|
+
__decorateClass([
|
|
784
|
+
consume({ context: targetTimegroupContext, subscribe: true }),
|
|
785
|
+
state()
|
|
786
|
+
], EFFilmstrip.prototype, "targetTimegroup", 2);
|
|
739
787
|
EFFilmstrip = __decorateClass([
|
|
740
788
|
customElement("ef-filmstrip")
|
|
741
789
|
], EFFilmstrip);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
export declare class EFFocusOverlay extends LitElement {
|
|
3
|
+
static styles: import('lit').CSSResult;
|
|
4
|
+
focusedElement?: HTMLElement | null;
|
|
5
|
+
overlay: import('lit-html/directives/ref.js').Ref<HTMLDivElement>;
|
|
6
|
+
private animationFrame?;
|
|
7
|
+
drawOverlay: () => void;
|
|
8
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
9
|
+
connectedCallback(): void;
|
|
10
|
+
disconnectedCallback(): void;
|
|
11
|
+
protected updated(): void;
|
|
12
|
+
}
|
|
13
|
+
declare global {
|
|
14
|
+
interface HTMLElementTagNameMap {
|
|
15
|
+
"ef-focus-overlay": EFFocusOverlay;
|
|
16
|
+
}
|
|
17
|
+
}
|