@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
package/package.json CHANGED
@@ -1,16 +1,12 @@
1
1
  {
2
2
  "name": "@editframe/elements",
3
- "version": "0.7.0-beta.9",
3
+ "version": "0.8.0-beta.2",
4
4
  "description": "",
5
5
  "exports": {
6
6
  ".": {
7
7
  "import": {
8
- "default": "./dist/packages/elements/src/index.js",
9
- "types": "./dist/packages/elements/src/index.d.ts"
10
- },
11
- "require": {
12
- "default": "./dist/packages/elements/src/index.cjs",
13
- "types": "./dist/packages/elements/src/index.d.ts"
8
+ "types": "./dist/index.d.ts",
9
+ "default": "./dist/elements/src/index.js"
14
10
  }
15
11
  },
16
12
  "./styles.css": "./dist/style.css"
@@ -24,7 +20,7 @@
24
20
  "author": "",
25
21
  "license": "UNLICENSED",
26
22
  "dependencies": {
27
- "@editframe/assets": "0.7.0-beta.8",
23
+ "@editframe/assets": "0.8.0-beta.2",
28
24
  "@lit/context": "^1.1.2",
29
25
  "@lit/task": "^1.0.1",
30
26
  "d3": "^7.9.0",
@@ -35,9 +31,10 @@
35
31
  "devDependencies": {
36
32
  "@types/d3": "^7.4.3",
37
33
  "@types/dom-webcodecs": "^0.1.11",
38
- "@types/node": "^20.14.9",
34
+ "@types/node": "^20.14.13",
39
35
  "autoprefixer": "^10.4.19",
40
36
  "rollup-plugin-tsconfig-paths": "^1.5.2",
37
+ "typescript": "^5.5.4",
41
38
  "vite-plugin-dts": "^3.9.1",
42
39
  "vite-tsconfig-paths": "^4.3.2"
43
40
  }
@@ -1,7 +1,7 @@
1
1
  import { html } from "lit";
2
2
  import { createRef, ref } from "lit/directives/ref.js";
3
3
  import { customElement, property } from "lit/decorators.js";
4
- import { EFMedia } from "./EFMedia";
4
+ import { EFMedia } from "./EFMedia.ts";
5
5
  import { Task } from "@lit/task";
6
6
 
7
7
  @customElement("ef-audio")
@@ -1,13 +1,13 @@
1
- import { EFAudio } from "./EFAudio";
2
1
  import { LitElement, type PropertyValueMap, html, css } from "lit";
3
2
  import { Task } from "@lit/task";
4
3
  import { customElement, property } from "lit/decorators.js";
5
- import { EFVideo } from "./EFVideo";
6
- import { EFTemporal } from "./EFTemporal";
7
- import { CrossUpdateController } from "./CrossUpdateController";
8
- import { FetchMixin } from "./FetchMixin";
9
- import { EFSourceMixin } from "./EFSourceMixin";
10
- import { EF_INTERACTIVE } from "../EF_INTERACTIVE";
4
+ import { EFVideo } from "./EFVideo.ts";
5
+ import { EFAudio } from "./EFAudio.ts";
6
+ import { EFTemporal } from "./EFTemporal.ts";
7
+ import { CrossUpdateController } from "./CrossUpdateController.ts";
8
+ import { FetchMixin } from "./FetchMixin.ts";
9
+ import { EFSourceMixin } from "./EFSourceMixin.ts";
10
+ import { EF_INTERACTIVE } from "../EF_INTERACTIVE.ts";
11
11
 
12
12
  interface Word {
13
13
  text: string;
@@ -93,8 +93,8 @@ export class EFCaptions extends EFSourceMixin(
93
93
 
94
94
  protected md5SumLoader = new Task(this, {
95
95
  autoRun: false,
96
- args: () => [this.target] as const,
97
- task: async ([], { signal }) => {
96
+ args: () => [this.target, this.fetch] as const,
97
+ task: async ([_target, fetch], { signal }) => {
98
98
  const md5Path = `/@ef-asset/${this.targetElement.src ?? ""}`;
99
99
  const response = await fetch(md5Path, { method: "HEAD", signal });
100
100
  return response.headers.get("etag") ?? undefined;
@@ -2,9 +2,9 @@ import { Task } from "@lit/task";
2
2
  import { LitElement, html, css } from "lit";
3
3
  import { customElement } from "lit/decorators.js";
4
4
  import { createRef, ref } from "lit/directives/ref.js";
5
- import { FetchMixin } from "./FetchMixin";
6
- import { EFSourceMixin } from "./EFSourceMixin";
7
- import { EF_INTERACTIVE } from "../EF_INTERACTIVE";
5
+ import { FetchMixin } from "./FetchMixin.ts";
6
+ import { EFSourceMixin } from "./EFSourceMixin.ts";
7
+ import { EF_INTERACTIVE } from "../EF_INTERACTIVE.ts";
8
8
 
9
9
  @customElement("ef-image")
10
10
  export class EFImage extends EFSourceMixin(FetchMixin(LitElement), {
@@ -8,14 +8,14 @@ import debug from "debug";
8
8
 
9
9
  import type { TrackFragmentIndex, TrackSegment } from "@editframe/assets";
10
10
 
11
- import { MP4File } from "@/av/MP4File";
12
- import { EFTemporal } from "./EFTemporal";
13
- import { VideoAsset } from "@/av/EncodedAsset";
14
- import { FetchMixin } from "./FetchMixin";
15
- import { apiHostContext } from "../gui/EFWorkbench";
16
- import { EFSourceMixin } from "./EFSourceMixin";
17
- import { getStartTimeMs } from "./util";
18
- import { EF_INTERACTIVE } from "../EF_INTERACTIVE";
11
+ import { MP4File } from "@editframe/assets/MP4File.js";
12
+ import { VideoAsset } from "@editframe/assets/EncodedAsset.js";
13
+ import { EFTemporal } from "./EFTemporal.ts";
14
+ import { FetchMixin } from "./FetchMixin.ts";
15
+ import { EFSourceMixin } from "./EFSourceMixin.ts";
16
+ import { getStartTimeMs } from "./util.ts";
17
+ import { EF_INTERACTIVE } from "../EF_INTERACTIVE.ts";
18
+ import { apiHostContext } from "../gui/apiHostContext.ts";
19
19
 
20
20
  const log = debug("ef:elements:EFMedia");
21
21
 
@@ -70,6 +70,9 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
70
70
  public trackFragmentIndexLoader = new Task(this, {
71
71
  args: () => [this.fragmentIndexPath(), this.fetch] as const,
72
72
  task: async ([fragmentIndexPath, fetch], { signal }) => {
73
+ if (this.src === "") {
74
+ return;
75
+ }
73
76
  const response = await fetch(fragmentIndexPath, { signal });
74
77
  return (await response.json()) as Record<number, TrackFragmentIndex>;
75
78
  },
@@ -142,7 +145,11 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
142
145
 
143
146
  const result: Record<
144
147
  string,
145
- { segment: TrackSegment; track: MP4Box.TrackInfo }
148
+ {
149
+ segment: TrackSegment;
150
+ track: MP4Box.TrackInfo;
151
+ nextSegment?: TrackSegment;
152
+ }
146
153
  > = {};
147
154
 
148
155
  for (const index of Object.values(fragmentIndex)) {
@@ -158,11 +165,15 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
158
165
  return (segment.dts / track.timescale) * 1000 <= seekToMs;
159
166
  });
160
167
 
168
+ const nextSegment = index.segments.find((segment) => {
169
+ return (segment.dts / track.timescale) * 1000 > seekToMs;
170
+ });
171
+
161
172
  if (!segment) {
162
173
  return;
163
174
  }
164
175
 
165
- result[index.track] = { segment, track };
176
+ result[index.track] = { segment, track, nextSegment };
166
177
  }
167
178
 
168
179
  return result;
@@ -184,7 +195,9 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
184
195
 
185
196
  const files: Record<string, File> = {};
186
197
 
187
- for (const [trackId, { segment, track }] of Object.entries(seekResult)) {
198
+ for (const [trackId, { segment, track, nextSegment }] of Object.entries(
199
+ seekResult,
200
+ )) {
188
201
  const start = segment.offset;
189
202
  const end = segment.offset + segment.size;
190
203
 
@@ -193,6 +206,21 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
193
206
  headers: { Range: `bytes=${start}-${end}` },
194
207
  });
195
208
 
209
+ if (nextSegment) {
210
+ const nextStart = nextSegment.offset;
211
+ const nextEnd = nextSegment.offset + nextSegment.size;
212
+ fetch(this.fragmentTrackPath(trackId), {
213
+ signal,
214
+ headers: { Range: `bytes=${nextStart}-${nextEnd}` },
215
+ })
216
+ .then(() => {
217
+ log("Prefetched next segment");
218
+ })
219
+ .catch((error) => {
220
+ log("Failed to prefetch next segment", error);
221
+ });
222
+ }
223
+
196
224
  const initSegment = Object.values(initSegments).find(
197
225
  (initSegment) => initSegment.trackId === String(track.id),
198
226
  );
@@ -1,9 +1,9 @@
1
1
  import { consume } from "@lit/context";
2
2
  import type { LitElement } from "lit";
3
- import { apiHostContext } from "../gui/EFWorkbench";
4
3
  import { state } from "lit/decorators/state.js";
5
4
  import { Task } from "@lit/task";
6
5
  import { property } from "lit/decorators/property.js";
6
+ import { apiHostContext } from "../gui/apiHostContext.ts";
7
7
 
8
8
  export declare class EFSourceMixinInterface {
9
9
  productionSrc(): string;
@@ -1,11 +1,11 @@
1
1
  import type { LitElement, ReactiveController } from "lit";
2
2
  import { consume, createContext } from "@lit/context";
3
3
  import { property, state } from "lit/decorators.js";
4
- import type { EFTimegroup } from "./EFTimegroup";
4
+ import type { EFTimegroup } from "./EFTimegroup.ts";
5
5
 
6
- import { durationConverter } from "./durationConverter";
6
+ import { durationConverter } from "./durationConverter.ts";
7
7
  import { Task } from "@lit/task";
8
- import { EF_INTERACTIVE } from "../EF_INTERACTIVE";
8
+ import { EF_INTERACTIVE } from "../EF_INTERACTIVE.ts";
9
9
 
10
10
  export const timegroupContext = createContext<EFTimegroup>(
11
11
  Symbol("timeGroupContext"),
@@ -59,10 +59,23 @@ export const deepGetElementsWithFrameTasks = (
59
59
  return elements;
60
60
  };
61
61
 
62
+ let temporalCache: Map<Element, TemporalMixinInterface[]>;
63
+ const resetTemporalCache = () => {
64
+ temporalCache = new Map();
65
+ if (typeof requestAnimationFrame !== "undefined") {
66
+ requestAnimationFrame(resetTemporalCache);
67
+ }
68
+ };
69
+ resetTemporalCache();
70
+
62
71
  export const shallowGetTemporalElements = (
63
72
  element: Element,
64
73
  temporals: TemporalMixinInterface[] = [],
65
74
  ) => {
75
+ const cachedResult = temporalCache.get(element);
76
+ if (cachedResult) {
77
+ return cachedResult;
78
+ }
66
79
  for (const child of element.children) {
67
80
  if (isEFTemporal(child)) {
68
81
  temporals.push(child);
@@ -70,6 +83,7 @@ export const shallowGetTemporalElements = (
70
83
  shallowGetTemporalElements(child, temporals);
71
84
  }
72
85
  }
86
+ temporalCache.set(element, temporals);
73
87
  return temporals;
74
88
  };
75
89
 
@@ -92,6 +106,15 @@ export class OwnCurrentTimeController implements ReactiveController {
92
106
 
93
107
  type Constructor<T = {}> = new (...args: any[]) => T;
94
108
 
109
+ let startTimeMsCache = new WeakMap<Element, number>();
110
+ const resetStartTimeMsCache = () => {
111
+ startTimeMsCache = new WeakMap();
112
+ if (typeof requestAnimationFrame !== "undefined") {
113
+ requestAnimationFrame(resetStartTimeMsCache);
114
+ }
115
+ };
116
+ resetStartTimeMsCache();
117
+
95
118
  export const EFTemporal = <T extends Constructor<LitElement>>(
96
119
  superClass: T,
97
120
  ) => {
@@ -172,27 +195,41 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
172
195
  }
173
196
 
174
197
  get startTimeMs(): number {
198
+ const cachedStartTime = startTimeMsCache.get(this);
199
+ if (cachedStartTime !== undefined) {
200
+ return cachedStartTime;
201
+ }
175
202
  const parentTimegroup = this.parentTimegroup;
176
203
  if (!parentTimegroup) {
204
+ startTimeMsCache.set(this, 0);
177
205
  return 0;
178
206
  }
179
207
  switch (parentTimegroup.mode) {
180
208
  case "sequence": {
181
209
  const siblingTemorals = shallowGetTemporalElements(parentTimegroup);
182
- const ownIndex = siblingTemorals.indexOf(
210
+ const ownIndex = siblingTemorals?.indexOf(
183
211
  this as InstanceType<Constructor<TemporalMixinInterface> & T>,
184
212
  );
185
213
  if (ownIndex === 0) {
214
+ startTimeMsCache.set(this, parentTimegroup.startTimeMs);
186
215
  return parentTimegroup.startTimeMs;
187
216
  }
188
- const previous = siblingTemorals[ownIndex - 1];
217
+ const previous = siblingTemorals?.[(ownIndex ?? 0) - 1];
189
218
  if (!previous) {
190
219
  throw new Error("Previous temporal element not found");
191
220
  }
221
+ startTimeMsCache.set(
222
+ this,
223
+ previous.startTimeMs + previous.durationMs,
224
+ );
192
225
  return previous.startTimeMs + previous.durationMs;
193
226
  }
194
227
  case "contain":
195
228
  case "fixed":
229
+ startTimeMsCache.set(
230
+ this,
231
+ parentTimegroup.startTimeMs + this.offsetMs,
232
+ );
196
233
  return parentTimegroup.startTimeMs + this.offsetMs;
197
234
  default:
198
235
  throw new Error(`Invalid time mode: ${parentTimegroup.mode}`);
@@ -5,10 +5,10 @@ import {
5
5
  html,
6
6
  render as litRender,
7
7
  } from "lit";
8
- import { EFTimegroup } from "./EFTimegroup";
9
- import "./EFTimegroup";
8
+ import { EFTimegroup } from "./EFTimegroup.ts";
9
+ import "./EFTimegroup.ts";
10
10
  import { customElement } from "lit/decorators/custom-element.js";
11
- import { EFTemporal } from "./EFTemporal";
11
+ import { EFTemporal } from "./EFTemporal.ts";
12
12
 
13
13
  beforeEach(() => {
14
14
  for (let i = 0; i < localStorage.length; i++) {
@@ -9,10 +9,10 @@ import {
9
9
  isEFTemporal,
10
10
  shallowGetTemporalElements,
11
11
  timegroupContext,
12
- } from "./EFTemporal";
13
- import { TimegroupController } from "./TimegroupController";
14
- import { EF_INTERACTIVE } from "../EF_INTERACTIVE";
15
- import { deepGetMediaElements } from "./EFMedia";
12
+ } from "./EFTemporal.ts";
13
+ import { TimegroupController } from "./TimegroupController.ts";
14
+ import { EF_INTERACTIVE } from "../EF_INTERACTIVE.ts";
15
+ import { deepGetMediaElements } from "./EFMedia.ts";
16
16
 
17
17
  const log = debug("ef:elements:EFTimegroup");
18
18
 
@@ -113,7 +113,9 @@ export class EFTimegroup extends EFTemporal(LitElement) {
113
113
  connectedCallback() {
114
114
  super.connectedCallback();
115
115
  if (this.id) {
116
- this.#currentTime = this.maybeLoadTimeFromLocalStorage();
116
+ this.waitForMediaDurations().then(() => {
117
+ this.#currentTime = this.maybeLoadTimeFromLocalStorage();
118
+ });
117
119
  }
118
120
 
119
121
  if (this.parentTimegroup) {
@@ -265,7 +267,8 @@ export class EFTimegroup extends EFTemporal(LitElement) {
265
267
  return (
266
268
  EF_INTERACTIVE &&
267
269
  this.closest("ef-timegroup") === this &&
268
- this.closest("ef-workbench") === null
270
+ this.closest("ef-workbench") === null &&
271
+ this.closest("ef-preview") === null
269
272
  );
270
273
  }
271
274
 
@@ -3,8 +3,8 @@ import { Task } from "@lit/task";
3
3
  import { createRef, ref } from "lit/directives/ref.js";
4
4
  import { customElement } from "lit/decorators.js";
5
5
 
6
- import { EFMedia } from "./EFMedia";
7
- import { TWMixin } from "../gui/TWMixin";
6
+ import { EFMedia } from "./EFMedia.ts";
7
+ import { TWMixin } from "../gui/TWMixin.ts";
8
8
 
9
9
  @customElement("ef-video")
10
10
  export class EFVideo extends TWMixin(EFMedia) {
@@ -1,15 +1,15 @@
1
- import { EFAudio } from "./EFAudio";
1
+ import { EFAudio } from "./EFAudio.ts";
2
2
 
3
3
  import { LitElement, html } from "lit";
4
4
  import { customElement, property } from "lit/decorators.js";
5
- import { EFVideo } from "./EFVideo";
6
- import { EFTemporal } from "./EFTemporal";
7
- import { CrossUpdateController } from "./CrossUpdateController";
8
- import { TWMixin } from "../gui/TWMixin";
5
+ import { EFVideo } from "./EFVideo.ts";
6
+ import { EFTemporal } from "./EFTemporal.ts";
7
+ import { CrossUpdateController } from "./CrossUpdateController.ts";
8
+ import { TWMixin } from "../gui/TWMixin.ts";
9
9
  import { Task } from "@lit/task";
10
10
  import * as d3 from "d3";
11
11
  import { type Ref, createRef, ref } from "lit/directives/ref.js";
12
- import { EF_INTERACTIVE } from "../EF_INTERACTIVE";
12
+ import { EF_INTERACTIVE } from "../EF_INTERACTIVE.ts";
13
13
 
14
14
  @customElement("ef-waveform")
15
15
  export class EFWaveform extends EFTemporal(TWMixin(LitElement)) {
@@ -1,8 +1,9 @@
1
- import { consume } from "@lit/context";
2
1
  import type { LitElement } from "lit";
3
- import { fetchContext } from "../gui/EFWorkbench";
2
+ import { consume } from "@lit/context";
4
3
  import { state } from "lit/decorators/state.js";
5
4
 
5
+ import { fetchContext } from "../gui/fetchContext.ts";
6
+
6
7
  export declare class FetchMixinInterface {
7
8
  fetch: typeof fetch;
8
9
  }
@@ -12,7 +13,8 @@ export function FetchMixin<T extends Constructor<LitElement>>(superClass: T) {
12
13
  class FetchElement extends superClass {
13
14
  @consume({ context: fetchContext, subscribe: true })
14
15
  @state()
15
- fetch = fetch.bind(window);
16
+ fetch: (url: string, init?: RequestInit) => Promise<Response> =
17
+ fetch.bind(window);
16
18
  }
17
19
 
18
20
  return FetchElement as Constructor<FetchMixinInterface> & T;
@@ -1,5 +1,5 @@
1
1
  import type { ReactiveController, LitElement } from "lit";
2
- import type { EFTimegroup } from "./EFTimegroup";
2
+ import type { EFTimegroup } from "./EFTimegroup.ts";
3
3
 
4
4
  export class TimegroupController implements ReactiveController {
5
5
  constructor(
@@ -1,4 +1,4 @@
1
- import { parseTimeToMs } from "./parseTimeToMs";
1
+ import { parseTimeToMs } from "./parseTimeToMs.ts";
2
2
 
3
3
  export const durationConverter = {
4
4
  fromAttribute: (value: string): number => parseTimeToMs(value),
@@ -1,4 +1,4 @@
1
- import { EFTimegroup } from "./EFTimegroup";
1
+ import { EFTimegroup } from "./EFTimegroup.ts";
2
2
 
3
3
  export const getRootTimeGroup = (element: Element): EFTimegroup | null => {
4
4
  let bestCandidate: EFTimegroup | null = null;