@editframe/elements 0.15.0-beta.1 → 0.15.0-beta.3
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/EF_FRAMEGEN.js +0 -2
- package/dist/elements/EFAudio.d.ts +0 -1
- package/dist/elements/EFAudio.js +1 -5
- package/dist/elements/EFCaptions.js +1 -1
- package/dist/elements/EFMedia.d.ts +1 -1
- package/dist/elements/EFMedia.js +37 -14
- package/dist/elements/EFTemporal.d.ts +3 -3
- package/dist/elements/EFTemporal.js +6 -2
- package/dist/elements/EFTimegroup.d.ts +1 -5
- package/dist/elements/EFTimegroup.js +4 -5
- package/dist/elements/EFWaveform.d.ts +13 -6
- package/dist/elements/EFWaveform.js +122 -50
- package/dist/elements/TargetController.d.ts +25 -0
- package/dist/elements/TargetController.js +164 -0
- package/dist/elements/TargetController.test.d.ts +19 -0
- package/dist/gui/EFPreview.d.ts +1 -1
- package/dist/gui/EFPreview.js +1 -0
- package/package.json +2 -2
- package/src/elements/EFAudio.ts +1 -4
- package/src/elements/EFCaptions.ts +1 -1
- package/src/elements/EFMedia.ts +41 -22
- package/src/elements/EFTemporal.ts +10 -10
- package/src/elements/EFTimegroup.ts +4 -9
- package/src/elements/EFWaveform.ts +161 -66
- package/src/elements/TargetController.test.ts +229 -0
- package/src/elements/TargetController.ts +219 -0
- package/src/gui/EFPreview.ts +10 -9
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { LitElement, ReactiveController } from 'lit';
|
|
2
|
+
type Constructor<T = {}> = new (...args: any[]) => T;
|
|
3
|
+
export declare class TargetableMixinInterface {
|
|
4
|
+
id: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const isEFTargetable: (obj: any) => obj is TargetableMixinInterface;
|
|
7
|
+
export declare const EFTargetable: <T extends Constructor<LitElement>>(superClass: T) => T;
|
|
8
|
+
export declare class TargetController implements ReactiveController {
|
|
9
|
+
private host;
|
|
10
|
+
private targetController;
|
|
11
|
+
private currentTargetString;
|
|
12
|
+
constructor(host: LitElement & {
|
|
13
|
+
targetElement: Element | null;
|
|
14
|
+
target: string;
|
|
15
|
+
});
|
|
16
|
+
private registryCallback;
|
|
17
|
+
private updateTarget;
|
|
18
|
+
private connectToTarget;
|
|
19
|
+
private disconnectFromTarget;
|
|
20
|
+
private get registry();
|
|
21
|
+
hostDisconnected(): void;
|
|
22
|
+
hostConnected(): void;
|
|
23
|
+
hostUpdate(): void;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { LitElement } from "lit";
|
|
2
|
+
const EF_TARGETABLE = Symbol("EF_TARGETABLE");
|
|
3
|
+
class TargetRegistry {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.idMap = /* @__PURE__ */ new Map();
|
|
6
|
+
this.callbacks = /* @__PURE__ */ new Map();
|
|
7
|
+
}
|
|
8
|
+
subscribe(id, callback) {
|
|
9
|
+
this.callbacks.set(id, this.callbacks.get(id) ?? /* @__PURE__ */ new Set());
|
|
10
|
+
this.callbacks.get(id)?.add(callback);
|
|
11
|
+
}
|
|
12
|
+
unsubscribe(id, callback) {
|
|
13
|
+
if (id === null) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
this.callbacks.get(id)?.delete(callback);
|
|
17
|
+
if (this.callbacks.get(id)?.size === 0) {
|
|
18
|
+
this.callbacks.delete(id);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
get(id) {
|
|
22
|
+
return this.idMap.get(id);
|
|
23
|
+
}
|
|
24
|
+
register(id, target) {
|
|
25
|
+
this.idMap.set(id, target);
|
|
26
|
+
for (const callback of this.callbacks.get(id) ?? []) {
|
|
27
|
+
callback(target);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
unregister(id) {
|
|
31
|
+
for (const callback of this.callbacks.get(id) ?? []) {
|
|
32
|
+
callback(void 0);
|
|
33
|
+
}
|
|
34
|
+
this.idMap.delete(id);
|
|
35
|
+
this.callbacks.delete(id);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const documentRegistries = /* @__PURE__ */ new WeakMap();
|
|
39
|
+
const getRegistry = (root) => {
|
|
40
|
+
let registry = documentRegistries.get(root);
|
|
41
|
+
if (!registry) {
|
|
42
|
+
registry = new TargetRegistry();
|
|
43
|
+
documentRegistries.set(root, registry);
|
|
44
|
+
}
|
|
45
|
+
return registry;
|
|
46
|
+
};
|
|
47
|
+
const EFTargetable = (superClass) => {
|
|
48
|
+
class TargetableElement extends superClass {
|
|
49
|
+
#registry = null;
|
|
50
|
+
static get observedAttributes() {
|
|
51
|
+
const parentAttributes = superClass.observedAttributes || [];
|
|
52
|
+
return [.../* @__PURE__ */ new Set([...parentAttributes, "id"])];
|
|
53
|
+
}
|
|
54
|
+
updateRegistry(oldValue, newValue) {
|
|
55
|
+
if (!this.#registry) return;
|
|
56
|
+
if (oldValue === newValue) return;
|
|
57
|
+
if (oldValue) {
|
|
58
|
+
this.#registry.unregister(oldValue);
|
|
59
|
+
}
|
|
60
|
+
if (newValue) {
|
|
61
|
+
this.#registry.register(newValue, this);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
connectedCallback() {
|
|
65
|
+
super.connectedCallback();
|
|
66
|
+
this.#registry = getRegistry(this.getRootNode());
|
|
67
|
+
const initialId = this.getAttribute("id");
|
|
68
|
+
if (initialId) {
|
|
69
|
+
this.updateRegistry("", initialId);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
attributeChangedCallback(name, old, value) {
|
|
73
|
+
super.attributeChangedCallback(name, old, value);
|
|
74
|
+
if (name === "id") {
|
|
75
|
+
this.updateRegistry(old ?? "", value ?? "");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
disconnectedCallback() {
|
|
79
|
+
if (this.#registry) {
|
|
80
|
+
this.updateRegistry(this.id, "");
|
|
81
|
+
this.#registry = null;
|
|
82
|
+
}
|
|
83
|
+
super.disconnectedCallback();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
Object.defineProperty(TargetableElement.prototype, EF_TARGETABLE, {
|
|
87
|
+
value: true
|
|
88
|
+
});
|
|
89
|
+
return TargetableElement;
|
|
90
|
+
};
|
|
91
|
+
class TargetUpdateController {
|
|
92
|
+
constructor(host) {
|
|
93
|
+
this.host = host;
|
|
94
|
+
}
|
|
95
|
+
hostConnected() {
|
|
96
|
+
this.host.requestUpdate();
|
|
97
|
+
}
|
|
98
|
+
hostDisconnected() {
|
|
99
|
+
this.host.requestUpdate();
|
|
100
|
+
}
|
|
101
|
+
hostUpdate() {
|
|
102
|
+
this.host.requestUpdate();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
class TargetController {
|
|
106
|
+
constructor(host) {
|
|
107
|
+
this.targetController = null;
|
|
108
|
+
this.currentTargetString = null;
|
|
109
|
+
this.registryCallback = (target) => {
|
|
110
|
+
this.host.targetElement = target ?? null;
|
|
111
|
+
};
|
|
112
|
+
this.host = host;
|
|
113
|
+
this.host.addController(this);
|
|
114
|
+
this.currentTargetString = this.host.target;
|
|
115
|
+
if (this.currentTargetString) {
|
|
116
|
+
this.registry.subscribe(this.currentTargetString, this.registryCallback);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
updateTarget() {
|
|
120
|
+
const newTarget = this.registry.get(this.host.target);
|
|
121
|
+
if (this.host.targetElement !== newTarget) {
|
|
122
|
+
this.disconnectFromTarget();
|
|
123
|
+
this.host.targetElement = newTarget ?? null;
|
|
124
|
+
this.connectToTarget();
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
connectToTarget() {
|
|
128
|
+
if (this.host.targetElement instanceof LitElement) {
|
|
129
|
+
this.targetController = new TargetUpdateController(this.host);
|
|
130
|
+
this.host.targetElement.addController(this.targetController);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
disconnectFromTarget() {
|
|
134
|
+
if (this.host.targetElement instanceof LitElement && this.targetController) {
|
|
135
|
+
this.host.targetElement.removeController(this.targetController);
|
|
136
|
+
this.targetController = null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
get registry() {
|
|
140
|
+
const root = this.host.getRootNode();
|
|
141
|
+
return getRegistry(root);
|
|
142
|
+
}
|
|
143
|
+
hostDisconnected() {
|
|
144
|
+
this.disconnectFromTarget();
|
|
145
|
+
}
|
|
146
|
+
hostConnected() {
|
|
147
|
+
this.updateTarget();
|
|
148
|
+
}
|
|
149
|
+
hostUpdate() {
|
|
150
|
+
if (this.currentTargetString !== this.host.target) {
|
|
151
|
+
this.registry.unsubscribe(
|
|
152
|
+
this.currentTargetString,
|
|
153
|
+
this.registryCallback
|
|
154
|
+
);
|
|
155
|
+
this.registry.subscribe(this.host.target, this.registryCallback);
|
|
156
|
+
this.updateTarget();
|
|
157
|
+
this.currentTargetString = this.host.target;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
export {
|
|
162
|
+
EFTargetable,
|
|
163
|
+
TargetController
|
|
164
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { LitElement } from 'lit';
|
|
2
|
+
declare const TargetableTest_base: typeof LitElement;
|
|
3
|
+
declare class TargetableTest extends TargetableTest_base {
|
|
4
|
+
value: string;
|
|
5
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
6
|
+
}
|
|
7
|
+
declare class TargeterTest extends LitElement {
|
|
8
|
+
private targetController;
|
|
9
|
+
targetElement: Element | null;
|
|
10
|
+
target: string;
|
|
11
|
+
render(): import('lit-html').TemplateResult<1>;
|
|
12
|
+
}
|
|
13
|
+
declare global {
|
|
14
|
+
interface HTMLElementTagNameMap {
|
|
15
|
+
"targetable-test": TargetableTest & Element;
|
|
16
|
+
"targeter-test": TargeterTest & Element;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
export {};
|
package/dist/gui/EFPreview.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { LitElement } from 'lit';
|
|
2
2
|
declare const EFPreview_base: (new (...args: any[]) => import('./ContextMixin.js').ContextMixinInterface) & typeof LitElement;
|
|
3
3
|
export declare class EFPreview extends EFPreview_base {
|
|
4
|
+
static styles: import('lit').CSSResult[];
|
|
4
5
|
focusedElement?: HTMLElement;
|
|
5
6
|
constructor();
|
|
6
|
-
static styles: import('lit').CSSResult[];
|
|
7
7
|
render(): import('lit-html').TemplateResult<1>;
|
|
8
8
|
}
|
|
9
9
|
declare global {
|
package/dist/gui/EFPreview.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@editframe/elements",
|
|
3
|
-
"version": "0.15.0-beta.
|
|
3
|
+
"version": "0.15.0-beta.3",
|
|
4
4
|
"description": "",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"license": "UNLICENSED",
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@bramus/style-observer": "^1.3.0",
|
|
25
|
-
"@editframe/assets": "0.15.0-beta.
|
|
25
|
+
"@editframe/assets": "0.15.0-beta.3",
|
|
26
26
|
"@lit/context": "^1.1.2",
|
|
27
27
|
"@lit/task": "^1.0.1",
|
|
28
28
|
"d3": "^7.9.0",
|
package/src/elements/EFAudio.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Task } from "@lit/task";
|
|
2
2
|
import { html } from "lit";
|
|
3
|
-
import { customElement
|
|
3
|
+
import { customElement } from "lit/decorators.js";
|
|
4
4
|
import { createRef, ref } from "lit/directives/ref.js";
|
|
5
5
|
import { EFMedia } from "./EFMedia.js";
|
|
6
6
|
|
|
@@ -8,9 +8,6 @@ import { EFMedia } from "./EFMedia.js";
|
|
|
8
8
|
export class EFAudio extends EFMedia {
|
|
9
9
|
audioElementRef = createRef<HTMLAudioElement>();
|
|
10
10
|
|
|
11
|
-
@property({ type: String })
|
|
12
|
-
src = "";
|
|
13
|
-
|
|
14
11
|
render() {
|
|
15
12
|
return html`<audio ${ref(this.audioElementRef)}></audio>`;
|
|
16
13
|
}
|
|
@@ -373,7 +373,7 @@ export class EFCaptions extends EFSourceMixin(
|
|
|
373
373
|
return;
|
|
374
374
|
}
|
|
375
375
|
|
|
376
|
-
const currentTimeMs = this.targetElement.
|
|
376
|
+
const currentTimeMs = this.targetElement.currentSourceTimeMs;
|
|
377
377
|
const currentTimeSec = currentTimeMs / 1000;
|
|
378
378
|
|
|
379
379
|
// Find the current word from word_segments
|
package/src/elements/EFMedia.ts
CHANGED
|
@@ -14,6 +14,7 @@ import { EF_RENDERING } from "../EF_RENDERING.js";
|
|
|
14
14
|
import { EFSourceMixin } from "./EFSourceMixin.js";
|
|
15
15
|
import { EFTemporal, isEFTemporal } from "./EFTemporal.js";
|
|
16
16
|
import { FetchMixin } from "./FetchMixin.js";
|
|
17
|
+
import { EFTargetable } from "./TargetController.ts";
|
|
17
18
|
|
|
18
19
|
const log = debug("ef:elements:EFMedia");
|
|
19
20
|
|
|
@@ -43,15 +44,14 @@ class LRUCache<K, V> {
|
|
|
43
44
|
} else if (this.cache.size >= this.maxSize) {
|
|
44
45
|
// Remove oldest entry (first item in map)
|
|
45
46
|
const firstKey = this.cache.keys().next().value;
|
|
46
|
-
|
|
47
|
+
if (firstKey) {
|
|
48
|
+
this.cache.delete(firstKey);
|
|
49
|
+
}
|
|
47
50
|
}
|
|
48
51
|
this.cache.set(key, value);
|
|
49
52
|
}
|
|
50
53
|
}
|
|
51
54
|
|
|
52
|
-
// Cache individual frame analyses
|
|
53
|
-
const frequencyDataCache = new LRUCache<string, Uint8Array>(100);
|
|
54
|
-
|
|
55
55
|
export const deepGetMediaElements = (
|
|
56
56
|
element: Element,
|
|
57
57
|
medias: EFMedia[] = [],
|
|
@@ -66,9 +66,11 @@ export const deepGetMediaElements = (
|
|
|
66
66
|
return medias;
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
export class EFMedia extends
|
|
70
|
-
|
|
71
|
-
|
|
69
|
+
export class EFMedia extends EFTargetable(
|
|
70
|
+
EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
|
|
71
|
+
assetType: "isobmff_files",
|
|
72
|
+
}),
|
|
73
|
+
) {
|
|
72
74
|
static styles = [
|
|
73
75
|
css`
|
|
74
76
|
:host {
|
|
@@ -319,7 +321,8 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
|
|
|
319
321
|
},
|
|
320
322
|
});
|
|
321
323
|
|
|
322
|
-
@state()
|
|
324
|
+
@state()
|
|
325
|
+
desiredSeekTimeMs = 0;
|
|
323
326
|
|
|
324
327
|
protected async executeSeek(seekToMs: number) {
|
|
325
328
|
this.desiredSeekTimeMs = seekToMs;
|
|
@@ -329,7 +332,7 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
|
|
|
329
332
|
changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,
|
|
330
333
|
): void {
|
|
331
334
|
if (changedProperties.has("ownCurrentTimeMs")) {
|
|
332
|
-
this.executeSeek(this.
|
|
335
|
+
this.executeSeek(this.currentSourceTimeMs);
|
|
333
336
|
}
|
|
334
337
|
// TODO: this is copied straight from EFTimegroup.ts
|
|
335
338
|
// and should be refactored to be shared/reduce bad duplication of
|
|
@@ -344,13 +347,9 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
|
|
|
344
347
|
this.endTimeMs < timelineTimeMs
|
|
345
348
|
) {
|
|
346
349
|
this.style.display = "none";
|
|
347
|
-
// this.style.zIndex = "";
|
|
348
|
-
// this.style.opacity = "0";
|
|
349
350
|
return;
|
|
350
351
|
}
|
|
351
352
|
this.style.display = "";
|
|
352
|
-
// this.style.zIndex = "100000";
|
|
353
|
-
// this.style.opacity = "";
|
|
354
353
|
const animations = this.getAnimations({ subtree: true });
|
|
355
354
|
|
|
356
355
|
this.style.setProperty("--ef-duration", `${this.durationMs}ms`);
|
|
@@ -617,18 +616,31 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
|
|
|
617
616
|
return weights;
|
|
618
617
|
}
|
|
619
618
|
|
|
619
|
+
#frequencyDataCache = new LRUCache<string, Uint8Array>(100);
|
|
620
|
+
|
|
620
621
|
frequencyDataTask = new Task(this, {
|
|
621
622
|
autoRun: EF_INTERACTIVE,
|
|
622
623
|
args: () =>
|
|
623
|
-
[
|
|
624
|
+
[
|
|
625
|
+
this.audioBufferTask.status,
|
|
626
|
+
this.currentSourceTimeMs,
|
|
627
|
+
this.fftSize, // Add fftSize to dependency array
|
|
628
|
+
this.fftDecay, // Add fftDecay to dependency array
|
|
629
|
+
] as const,
|
|
624
630
|
task: async () => {
|
|
625
631
|
await this.audioBufferTask.taskComplete;
|
|
626
632
|
if (!this.audioBufferTask.value) return null;
|
|
627
|
-
if (this.
|
|
633
|
+
if (this.currentSourceTimeMs <= 0) return null;
|
|
628
634
|
|
|
629
|
-
const currentTimeMs = this.
|
|
635
|
+
const currentTimeMs = this.currentSourceTimeMs;
|
|
630
636
|
const startOffsetMs = this.audioBufferTask.value.startOffsetMs;
|
|
631
637
|
const audioBuffer = this.audioBufferTask.value.buffer;
|
|
638
|
+
const smoothedKey = `${this.fftSize}:${this.fftDecay}:${startOffsetMs}:${currentTimeMs}`;
|
|
639
|
+
|
|
640
|
+
const cachedSmoothedData = this.#frequencyDataCache.get(smoothedKey);
|
|
641
|
+
if (cachedSmoothedData) {
|
|
642
|
+
return cachedSmoothedData;
|
|
643
|
+
}
|
|
632
644
|
|
|
633
645
|
const framesData = await Promise.all(
|
|
634
646
|
Array.from({ length: this.fftDecay }, async (_, i) => {
|
|
@@ -639,10 +651,10 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
|
|
|
639
651
|
);
|
|
640
652
|
|
|
641
653
|
// Cache key for this specific frame
|
|
642
|
-
const cacheKey = `${startOffsetMs}
|
|
654
|
+
const cacheKey = `${this.fftSize}:${startOffsetMs}:${startTime}`;
|
|
643
655
|
|
|
644
656
|
// Check cache for this specific frame
|
|
645
|
-
const cachedFrame = frequencyDataCache.get(cacheKey);
|
|
657
|
+
const cachedFrame = this.#frequencyDataCache.get(cacheKey);
|
|
646
658
|
if (cachedFrame) {
|
|
647
659
|
return cachedFrame;
|
|
648
660
|
}
|
|
@@ -667,11 +679,11 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
|
|
|
667
679
|
|
|
668
680
|
try {
|
|
669
681
|
await audioContext.startRendering();
|
|
670
|
-
const frameData = new Uint8Array(
|
|
682
|
+
const frameData = new Uint8Array(this.fftSize / 2);
|
|
671
683
|
analyser.getByteFrequencyData(frameData);
|
|
672
684
|
|
|
673
685
|
// Cache this frame's analysis
|
|
674
|
-
frequencyDataCache.set(cacheKey, frameData);
|
|
686
|
+
this.#frequencyDataCache.set(cacheKey, frameData);
|
|
675
687
|
return frameData;
|
|
676
688
|
} finally {
|
|
677
689
|
audioBufferSource.disconnect();
|
|
@@ -700,12 +712,19 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
|
|
|
700
712
|
|
|
701
713
|
// Apply frequency weights using instance FREQ_WEIGHTS
|
|
702
714
|
smoothedData.forEach((value, i) => {
|
|
703
|
-
// biome-ignore lint/style/noNonNullAssertion:
|
|
715
|
+
// biome-ignore lint/style/noNonNullAssertion: Will exist due to forEach
|
|
704
716
|
const freqWeight = this.FREQ_WEIGHTS[i]!;
|
|
705
717
|
smoothedData[i] = Math.min(255, Math.round(value * freqWeight));
|
|
706
718
|
});
|
|
707
719
|
|
|
708
|
-
return
|
|
720
|
+
// Only return the lower half of the frequency data
|
|
721
|
+
// The top half is zeroed out, which makes for aesthetically unpleasing waveforms
|
|
722
|
+
const slicedData = smoothedData.slice(
|
|
723
|
+
0,
|
|
724
|
+
Math.floor(smoothedData.length / 2),
|
|
725
|
+
);
|
|
726
|
+
this.#frequencyDataCache.set(smoothedKey, slicedData);
|
|
727
|
+
return slicedData;
|
|
709
728
|
},
|
|
710
729
|
});
|
|
711
730
|
}
|
|
@@ -151,18 +151,18 @@ export declare class TemporalMixinInterface {
|
|
|
151
151
|
* elements.
|
|
152
152
|
*
|
|
153
153
|
* For example, if the media has a `sourcein` value of 10s, when `ownCurrentTimeMs` is 0s,
|
|
154
|
-
* `
|
|
154
|
+
* `currentSourceTimeMs` will be 10s.
|
|
155
155
|
*
|
|
156
156
|
* sourcein=10s sourceout=10s
|
|
157
157
|
* / / /
|
|
158
158
|
* |--------|=================|---------|
|
|
159
159
|
* ^
|
|
160
160
|
* |_
|
|
161
|
-
*
|
|
161
|
+
* currentSourceTimeMs === 10s
|
|
162
162
|
* |_
|
|
163
163
|
* ownCurrentTimeMs === 0s
|
|
164
164
|
*/
|
|
165
|
-
get
|
|
165
|
+
get currentSourceTimeMs(): number;
|
|
166
166
|
|
|
167
167
|
set duration(value: string);
|
|
168
168
|
get duration(): string;
|
|
@@ -567,6 +567,10 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
567
567
|
return this.startTimeMs + this.durationMs;
|
|
568
568
|
}
|
|
569
569
|
|
|
570
|
+
/**
|
|
571
|
+
* The current time of the element within itself.
|
|
572
|
+
* Compare with `currentTimeMs` to see the current time with respect to the root timegroup
|
|
573
|
+
*/
|
|
570
574
|
get ownCurrentTimeMs() {
|
|
571
575
|
if (this.rootTimegroup) {
|
|
572
576
|
return Math.min(
|
|
@@ -581,7 +585,7 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
581
585
|
* Used to calculate the internal currentTimeMs of the element. This is useful
|
|
582
586
|
* for mapping to internal media time codes for audio/video elements.
|
|
583
587
|
*/
|
|
584
|
-
get
|
|
588
|
+
get currentSourceTimeMs() {
|
|
585
589
|
if (this.rootTimegroup) {
|
|
586
590
|
if (this.sourceInMs && this.sourceOutMs) {
|
|
587
591
|
return Math.min(
|
|
@@ -632,17 +636,13 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
|
|
|
632
636
|
) {
|
|
633
637
|
const timelineTimeMs = (this.rootTimegroup ?? this).ownCurrentTimeMs;
|
|
634
638
|
if (
|
|
635
|
-
this.startTimeMs
|
|
636
|
-
this.endTimeMs
|
|
639
|
+
this.startTimeMs > timelineTimeMs ||
|
|
640
|
+
this.endTimeMs < timelineTimeMs
|
|
637
641
|
) {
|
|
638
642
|
this.style.display = "none";
|
|
639
|
-
// this.style.zIndex = "";
|
|
640
|
-
// this.style.opacity = "0";
|
|
641
643
|
return;
|
|
642
644
|
}
|
|
643
645
|
this.style.display = "";
|
|
644
|
-
// this.style.zIndex = "100000";
|
|
645
|
-
// this.style.opacity = "";
|
|
646
646
|
}
|
|
647
647
|
}
|
|
648
648
|
}
|
|
@@ -53,7 +53,7 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
53
53
|
type: String,
|
|
54
54
|
attribute: "mode",
|
|
55
55
|
})
|
|
56
|
-
mode: "fixed" | "sequence" | "contain" = "
|
|
56
|
+
mode: "fixed" | "sequence" | "contain" = "contain";
|
|
57
57
|
|
|
58
58
|
@property({
|
|
59
59
|
type: Number,
|
|
@@ -67,7 +67,7 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
67
67
|
|
|
68
68
|
#resizeObserver?: ResizeObserver;
|
|
69
69
|
|
|
70
|
-
@property({ type: Number })
|
|
70
|
+
@property({ type: Number, attribute: "currenttime" })
|
|
71
71
|
set currentTime(time: number) {
|
|
72
72
|
this.#currentTime = Math.max(0, Math.min(time, this.durationMs / 1000));
|
|
73
73
|
try {
|
|
@@ -227,10 +227,9 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
227
227
|
* in calculations and it was not clear why.
|
|
228
228
|
*/
|
|
229
229
|
async waitForMediaDurations() {
|
|
230
|
+
const mediaElements = deepGetMediaElements(this);
|
|
230
231
|
return await Promise.all(
|
|
231
|
-
|
|
232
|
-
(media) => media.initSegmentsLoader.taskComplete,
|
|
233
|
-
),
|
|
232
|
+
mediaElements.map((m) => m.trackFragmentIndexLoader.taskComplete),
|
|
234
233
|
);
|
|
235
234
|
}
|
|
236
235
|
|
|
@@ -258,13 +257,9 @@ export class EFTimegroup extends EFTemporal(LitElement) {
|
|
|
258
257
|
const timelineTimeMs = (this.rootTimegroup ?? this).currentTimeMs;
|
|
259
258
|
if (this.startTimeMs > timelineTimeMs || this.endTimeMs < timelineTimeMs) {
|
|
260
259
|
this.style.display = "none";
|
|
261
|
-
// this.style.zIndex = "";
|
|
262
|
-
// this.style.opacity = "0";
|
|
263
260
|
return;
|
|
264
261
|
}
|
|
265
262
|
this.style.display = "";
|
|
266
|
-
// this.style.zIndex = "100000";
|
|
267
|
-
// this.style.opacity = "";
|
|
268
263
|
const animations = this.getAnimations({ subtree: true });
|
|
269
264
|
this.style.setProperty("--ef-duration", `${this.durationMs}ms`);
|
|
270
265
|
this.style.setProperty(
|