@editframe/elements 0.7.0-beta.1 → 0.7.0-beta.5

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 (36) hide show
  1. package/dist/lib/av/EncodedAsset.cjs +21 -14
  2. package/dist/lib/av/EncodedAsset.js +21 -14
  3. package/dist/lib/av/MP4File.cjs +6 -1
  4. package/dist/lib/av/MP4File.js +6 -1
  5. package/dist/packages/elements/src/EF_FRAMEGEN.cjs +10 -13
  6. package/dist/packages/elements/src/EF_FRAMEGEN.d.ts +0 -1
  7. package/dist/packages/elements/src/EF_FRAMEGEN.js +10 -13
  8. package/dist/packages/elements/src/elements/EFMedia.cjs +9 -7
  9. package/dist/packages/elements/src/elements/EFMedia.d.ts +1 -1
  10. package/dist/packages/elements/src/elements/EFMedia.js +9 -7
  11. package/dist/packages/elements/src/elements/EFTemporal.cjs +4 -3
  12. package/dist/packages/elements/src/elements/EFTemporal.d.ts +2 -0
  13. package/dist/packages/elements/src/elements/EFTemporal.js +4 -3
  14. package/dist/packages/elements/src/elements/EFTimegroup.cjs +6 -4
  15. package/dist/packages/elements/src/elements/EFTimegroup.js +6 -4
  16. package/dist/packages/elements/src/gui/EFFilmstrip.cjs +24 -19
  17. package/dist/packages/elements/src/gui/EFFilmstrip.js +24 -19
  18. package/dist/packages/elements/src/gui/EFWorkbench.cjs +6 -5
  19. package/dist/packages/elements/src/gui/EFWorkbench.d.ts +4 -4
  20. package/dist/packages/elements/src/gui/EFWorkbench.js +6 -5
  21. package/dist/packages/elements/src/gui/TWMixin.css.cjs +1 -1
  22. package/dist/packages/elements/src/gui/TWMixin.css.js +1 -1
  23. package/dist/packages/elements/src/index.cjs +1 -2
  24. package/dist/packages/elements/src/index.d.ts +1 -1
  25. package/dist/packages/elements/src/index.js +1 -2
  26. package/dist/style.css +4 -0
  27. package/package.json +14 -8
  28. package/src/elements/EFMedia.ts +13 -8
  29. package/src/elements/EFTemporal.ts +8 -5
  30. package/src/elements/EFTimegroup.ts +8 -4
  31. package/src/gui/EFFilmstrip.ts +24 -20
  32. package/src/gui/EFWorkbench.ts +9 -7
  33. package/dist/packages/elements/src/elements/EFTimeline.cjs +0 -15
  34. package/dist/packages/elements/src/elements/EFTimeline.d.ts +0 -3
  35. package/dist/packages/elements/src/elements/EFTimeline.js +0 -15
  36. package/src/elements/EFTimeline.ts +0 -13
@@ -1,7 +1,7 @@
1
1
 
2
2
  export { EFTimegroup } from './elements/EFTimegroup';
3
- export { EFTimeline } from './elements/EFTimeline';
4
3
  export { EFImage } from './elements/EFImage';
4
+ export type { EFMedia } from './elements/EFMedia';
5
5
  export { EFAudio } from './elements/EFAudio';
6
6
  export { EFVideo } from './elements/EFVideo';
7
7
  export { EFCaptions, EFCaptionsActiveWord } from './elements/EFCaptions';
@@ -1,7 +1,7 @@
1
1
  /* empty css */
2
2
  import { EFTimegroup } from "./elements/EFTimegroup.js";
3
- import { EFTimeline } from "./elements/EFTimeline.js";
4
3
  import { EFImage } from "./elements/EFImage.js";
4
+ import "./elements/EFMedia.js";
5
5
  import { EFAudio } from "./elements/EFAudio.js";
6
6
  import { EFVideo } from "./elements/EFVideo.js";
7
7
  import { EFCaptions, EFCaptionsActiveWord } from "./elements/EFCaptions.js";
@@ -17,7 +17,6 @@ export {
17
17
  EFFilmstrip,
18
18
  EFImage,
19
19
  EFTimegroup,
20
- EFTimeline,
21
20
  EFVideo,
22
21
  EFWaveform,
23
22
  EFWorkbench
package/dist/style.css CHANGED
@@ -761,6 +761,10 @@ body {
761
761
  -moz-osx-font-smoothing: grayscale;
762
762
  -webkit-text-size-adjust: 100%;
763
763
  }
764
+ .hover\:bg-blue-400:hover {
765
+ --tw-bg-opacity: 1;
766
+ background-color: rgb(96 165 250 / var(--tw-bg-opacity));
767
+ }
764
768
  .hover\:bg-slate-400:hover {
765
769
  --tw-bg-opacity: 1;
766
770
  background-color: rgb(148 163 184 / var(--tw-bg-opacity));
package/package.json CHANGED
@@ -1,15 +1,20 @@
1
1
  {
2
2
  "name": "@editframe/elements",
3
- "version": "0.7.0-beta.1",
3
+ "version": "0.7.0-beta.5",
4
4
  "description": "",
5
5
  "exports": {
6
6
  ".": {
7
- "import": "./dist/packages/elements/src/index.js",
8
- "require": "./dist/packages/elements/src/index.cjs"
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"
14
+ }
9
15
  },
10
16
  "./styles.css": "./dist/style.css"
11
17
  },
12
- "types": "./dist/packages/elements/src/index.d.ts",
13
18
  "type": "module",
14
19
  "scripts": {
15
20
  "typecheck": "tsc --noEmit --emitDeclarationOnly false",
@@ -19,11 +24,12 @@
19
24
  "author": "",
20
25
  "license": "UNLICENSED",
21
26
  "dependencies": {
22
- "@editframe/assets": "0.7.0-beta.1",
23
- "@lit/context": "^1.1.1",
24
- "@lit/task": "^1.0.0",
27
+ "@editframe/assets": "0.7.0-beta.5",
28
+ "@lit/context": "^1.1.2",
29
+ "@lit/task": "^1.0.1",
25
30
  "d3": "^7.9.0",
26
- "lit": "^3.1.3",
31
+ "debug": "^4.3.5",
32
+ "lit": "^3.1.4",
27
33
  "mp4box": "^0.5.2"
28
34
  },
29
35
  "devDependencies": {
@@ -1,19 +1,24 @@
1
1
  import { LitElement, type PropertyValueMap, css } from "lit";
2
- import { EFTemporal } from "./EFTemporal";
3
2
  import { property, state } from "lit/decorators.js";
4
3
  import { deepArrayEquals } from "@lit/task/deep-equals.js";
5
4
  import { Task } from "@lit/task";
6
5
  import type * as MP4Box from "mp4box";
7
- import { MP4File } from "@/av/MP4File";
6
+ import { consume } from "@lit/context";
7
+ import debug from "debug";
8
+
8
9
  import type { TrackFragmentIndex, TrackSegment } from "@editframe/assets";
9
- import { getStartTimeMs } from "./util";
10
+
11
+ import { MP4File } from "@/av/MP4File";
12
+ import { EFTemporal } from "./EFTemporal";
10
13
  import { VideoAsset } from "@/av/EncodedAsset";
11
14
  import { FetchMixin } from "./FetchMixin";
12
15
  import { apiHostContext } from "../gui/EFWorkbench";
13
- import { consume } from "@lit/context";
14
16
  import { EFSourceMixin } from "./EFSourceMixin";
17
+ import { getStartTimeMs } from "./util";
15
18
  import { EF_INTERACTIVE } from "../EF_INTERACTIVE";
16
19
 
20
+ const log = debug("ef:elements:EFMedia");
21
+
17
22
  export const deepGetMediaElements = (
18
23
  element: Element,
19
24
  medias: EFMedia[] = [],
@@ -313,12 +318,12 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
313
318
  await this.trackFragmentIndexLoader.taskComplete;
314
319
  const audioTrackId = this.defaultAudioTrackId;
315
320
  if (!audioTrackId) {
316
- console.warn("No audio track found");
321
+ log("No audio track found");
317
322
  return;
318
323
  }
319
324
  const audioTrackIndex = this.trackFragmentIndexLoader.value?.[audioTrackId];
320
325
  if (!audioTrackIndex) {
321
- console.warn("No audio track found");
326
+ log("No audio track found");
322
327
  return;
323
328
  }
324
329
 
@@ -345,12 +350,12 @@ export class EFMedia extends EFSourceMixin(EFTemporal(FetchMixin(LitElement)), {
345
350
 
346
351
  const firstFragment = fragments[0];
347
352
  if (!firstFragment) {
348
- console.warn("No audio fragments found");
353
+ log("No audio fragments found");
349
354
  return;
350
355
  }
351
356
  const lastFragment = fragments[fragments.length - 1];
352
357
  if (!lastFragment) {
353
- console.warn("No audio fragments found");
358
+ log("No audio fragments found");
354
359
  return;
355
360
  }
356
361
  const fragmentStart = firstFragment.offset;
@@ -19,6 +19,9 @@ export declare class TemporalMixinInterface {
19
19
  get endTimeMs(): number;
20
20
  get ownCurrentTimeMs(): number;
21
21
 
22
+ set duration(value: string);
23
+ get duration(): string;
24
+
22
25
  parentTimegroup?: EFTimegroup;
23
26
  rootTimegroup?: EFTimegroup;
24
27
 
@@ -105,7 +108,7 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
105
108
  if (this.rootTimegroup) {
106
109
  this.ownCurrentTimeController = new OwnCurrentTimeController(
107
110
  this.rootTimegroup,
108
- this,
111
+ this as InstanceType<Constructor<TemporalMixinInterface> & T>,
109
112
  );
110
113
  }
111
114
  }
@@ -146,9 +149,7 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
146
149
  // Defining this as a getter to a private property allows us to
147
150
  // override it classes that include this mixin.
148
151
  get durationMs() {
149
- const durationMs =
150
- this._durationMs || this.parentTimegroup?.durationMs || 0;
151
- return durationMs || 0;
152
+ return this._durationMs || this.parentTimegroup?.durationMs || 0;
152
153
  }
153
154
 
154
155
  get offsetMs() {
@@ -178,7 +179,9 @@ export const EFTemporal = <T extends Constructor<LitElement>>(
178
179
  switch (parentTimegroup.mode) {
179
180
  case "sequence": {
180
181
  const siblingTemorals = shallowGetTemporalElements(parentTimegroup);
181
- const ownIndex = siblingTemorals.indexOf(this);
182
+ const ownIndex = siblingTemorals.indexOf(
183
+ this as InstanceType<Constructor<TemporalMixinInterface> & T>,
184
+ );
182
185
  if (ownIndex === 0) {
183
186
  return parentTimegroup.startTimeMs;
184
187
  }
@@ -1,6 +1,9 @@
1
1
  import { LitElement, html, css, type PropertyValueMap } from "lit";
2
2
  import { provide } from "@lit/context";
3
+ import { Task } from "@lit/task";
3
4
  import { customElement, property } from "lit/decorators.js";
5
+ import debug from "debug";
6
+
4
7
  import {
5
8
  EFTemporal,
6
9
  isEFTemporal,
@@ -10,7 +13,8 @@ import {
10
13
  import { TimegroupController } from "./TimegroupController";
11
14
  import { EF_INTERACTIVE } from "../EF_INTERACTIVE";
12
15
  import { deepGetMediaElements } from "./EFMedia";
13
- import { Task } from "@lit/task";
16
+
17
+ const log = debug("ef:elements:EFTimegroup");
14
18
 
15
19
  export const shallowGetTimegroups = (
16
20
  element: Element,
@@ -59,7 +63,7 @@ export class EFTimegroup extends EFTemporal(LitElement) {
59
63
  }
60
64
  }
61
65
  } catch (error) {
62
- console.warn("Failed to save time to localStorage", error);
66
+ log("Failed to save time to localStorage", error);
63
67
  }
64
68
  }
65
69
  get currentTime() {
@@ -100,7 +104,7 @@ export class EFTimegroup extends EFTemporal(LitElement) {
100
104
  try {
101
105
  return Number.parseFloat(localStorage.getItem(this.storageKey) || "0");
102
106
  } catch (error) {
103
- console.warn("Failed to load time from localStorage", error);
107
+ log("Failed to load time from localStorage", error);
104
108
  }
105
109
  }
106
110
  return 0;
@@ -148,7 +152,7 @@ export class EFTimegroup extends EFTemporal(LitElement) {
148
152
  get durationMs() {
149
153
  switch (this.mode) {
150
154
  case "fixed":
151
- return super.durationMs || 0;
155
+ return super.durationMs;
152
156
  case "sequence": {
153
157
  let duration = 0;
154
158
  for (const node of this.childTemporals) {
@@ -65,14 +65,14 @@ class FilmstripItem extends TWMixin(LitElement) {
65
65
  `,
66
66
  ];
67
67
 
68
- @consume({ context: focusContext })
68
+ @consume({ context: focusContext, subscribe: true })
69
69
  focusContext?: FocusContext;
70
70
 
71
71
  @consume({ context: focusedElement, subscribe: true })
72
72
  focusedElement?: HTMLElement | null;
73
73
 
74
74
  get isFocused() {
75
- return this.element && this.focusedElement === this.element;
75
+ return this.element && this.focusContext?.focusedElement === this.element;
76
76
  }
77
77
 
78
78
  @property({ type: HTMLElement, attribute: false })
@@ -92,6 +92,8 @@ class FilmstripItem extends TWMixin(LitElement) {
92
92
  render() {
93
93
  return html` <div class="" style=${styleMap(this.styles)}>
94
94
  <div
95
+ class="border-outset relative mb-[1px] block h-[1.1rem] text-nowrap border border-slate-500 bg-blue-200 hover:bg-blue-400 text-sm data-[focused]:bg-slate-400"
96
+ ?data-focused=${this.isFocused}
95
97
  @mouseenter=${() => {
96
98
  if (this.focusContext) {
97
99
  this.focusContext.focusedElement = this.element;
@@ -102,8 +104,6 @@ class FilmstripItem extends TWMixin(LitElement) {
102
104
  this.focusContext.focusedElement = null;
103
105
  }
104
106
  }}
105
- ?data-focused=${this.isFocused}
106
- class="border-outset relative mb-[1px] block h-[1.1rem] text-nowrap border border-slate-500 bg-blue-200 text-sm data-[focused]:bg-slate-400"
107
107
  >
108
108
  ${this.animations()}
109
109
  </div>
@@ -269,7 +269,7 @@ class EFHierarchyItem<
269
269
  }
270
270
 
271
271
  get isFocused() {
272
- return this.element && this.focusedElement === this.element;
272
+ return this.element && this.focusContext?.focusedElement === this.element;
273
273
  }
274
274
 
275
275
  displayLabel(): TemplateResult<1> | string | typeof nothing {
@@ -280,10 +280,10 @@ class EFHierarchyItem<
280
280
  return html`
281
281
  <div>
282
282
  <div
283
- ?data-focused=${this.isFocused}
284
283
  class="peer
285
284
  flex h-[1.1rem] items-center overflow-hidden text-nowrap border border-slate-500
286
285
  bg-slate-200 pl-2 text-xs font-mono hover:bg-slate-400 data-[focused]:bg-slate-400"
286
+ ?data-focused=${this.isFocused}
287
287
  @mouseenter=${() => {
288
288
  if (this.focusContext) {
289
289
  this.focusContext.focusedElement = this.element;
@@ -504,6 +504,19 @@ export class EFFilmstrip extends TWMixin(LitElement) {
504
504
 
505
505
  connectedCallback(): void {
506
506
  super.connectedCallback();
507
+ this.#bindToTargetTimegroup();
508
+ window.addEventListener("keypress", this.#handleKeyPress);
509
+ }
510
+
511
+ disconnectedCallback(): void {
512
+ super.disconnectedCallback();
513
+ window.removeEventListener("keypress", this.#handleKeyPress);
514
+ }
515
+
516
+ #bindToTargetTimegroup() {
517
+ if (this.timegroupController) {
518
+ this.timegroupController.remove();
519
+ }
507
520
  const target = this.targetTimegroup;
508
521
  if (target) {
509
522
  this.timegroupController = new TimegroupController(target, this);
@@ -511,13 +524,6 @@ export class EFFilmstrip extends TWMixin(LitElement) {
511
524
  // where the filmstrip clobbers the time loaded from localStorage
512
525
  this.currentTimeMs = target.currentTimeMs;
513
526
  }
514
-
515
- window.addEventListener("keypress", this.#handleKeyPress);
516
- }
517
-
518
- disconnectedCallback(): void {
519
- super.disconnectedCallback();
520
- window.removeEventListener("keypress", this.#handleKeyPress);
521
527
  }
522
528
 
523
529
  #handleKeyPress = (event: KeyboardEvent) => {
@@ -790,7 +796,7 @@ export class EFFilmstrip extends TWMixin(LitElement) {
790
796
  ${ref(this.hierarchyRef)}
791
797
  @scroll=${this.syncHierarchyScroll}
792
798
  >
793
- ${renderHierarchyChildren(Array.from(target?.children ?? []))}
799
+ ${renderHierarchyChildren(target ? [target] : [])}
794
800
  </div>
795
801
  <div
796
802
  class="h-full w-full cursor-crosshair overflow-auto bg-slate-200 pt-2"
@@ -814,10 +820,7 @@ export class EFFilmstrip extends TWMixin(LitElement) {
814
820
  ${ref(this.playheadRef)}
815
821
  ></div>
816
822
 
817
- ${renderFilmstripChildren(
818
- Array.from(target?.children || []),
819
- this.pixelsPerMs,
820
- )}
823
+ ${renderFilmstripChildren(target ? [target] : [], this.pixelsPerMs)}
821
824
  </div>
822
825
  </div>
823
826
  </div>`;
@@ -843,6 +846,9 @@ export class EFFilmstrip extends TWMixin(LitElement) {
843
846
  this.targetTimegroup.currentTimeMs = this.currentTimeMs;
844
847
  }
845
848
  }
849
+ if (changes.has("target")) {
850
+ this.#bindToTargetTimegroup();
851
+ }
846
852
  }
847
853
 
848
854
  get targetTimegroup() {
@@ -851,8 +857,6 @@ export class EFFilmstrip extends TWMixin(LitElement) {
851
857
  if (target instanceof EFTimegroup) {
852
858
  return target;
853
859
  }
854
-
855
- throw new Error("Invalid target, must be an EFTimegroup element");
856
860
  }
857
861
  return undefined;
858
862
  }
@@ -17,13 +17,15 @@ import { shallowGetTimegroups } from "../elements/EFTimegroup";
17
17
  export interface FocusContext {
18
18
  focusedElement: HTMLElement | null;
19
19
  }
20
- export const focusContext = createContext<FocusContext>(null);
20
+ export const focusContext = createContext<FocusContext>(Symbol("focusContext"));
21
21
 
22
- export const focusedElement = createContext<HTMLElement | null>(null);
22
+ export const focusedElement = createContext<HTMLElement | undefined>(
23
+ Symbol("focusedElement"),
24
+ );
23
25
 
24
- export const fetchContext = createContext<typeof fetch>(fetch);
26
+ export const fetchContext = createContext<typeof fetch>(Symbol("fetchContext"));
25
27
 
26
- export const apiHostContext = createContext<string>(null);
28
+ export const apiHostContext = createContext<string>(Symbol("apiHostContext"));
27
29
 
28
30
  @customElement("ef-workbench")
29
31
  export class EFWorkbench extends TWMixin(LitElement) {
@@ -92,11 +94,11 @@ export class EFWorkbench extends TWMixin(LitElement) {
92
94
  }
93
95
 
94
96
  @provide({ context: focusContext })
95
- focusContext = this;
97
+ focusContext = this as FocusContext;
96
98
 
97
99
  @provide({ context: focusedElement })
98
100
  @state()
99
- focusedElement: HTMLElement | null = null;
101
+ focusedElement?: HTMLElement;
100
102
 
101
103
  @provide({ context: fetchContext })
102
104
  fetch = (path: URL | RequestInfo, init: RequestInit = {}) => {
@@ -127,7 +129,7 @@ export class EFWorkbench extends TWMixin(LitElement) {
127
129
 
128
130
  focusOverlay = createRef<HTMLDivElement>();
129
131
 
130
- protected update(
132
+ update(
131
133
  changedProperties: PropertyValueMap<any> | Map<PropertyKey, unknown>,
132
134
  ): void {
133
135
  super.update(changedProperties);
@@ -1,15 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- class EFTimeline extends HTMLElement {
4
- get durationMs() {
5
- let duration = 0;
6
- for (const node of this.childNodes) {
7
- if ("durationMs" in node && typeof node.durationMs === "number") {
8
- duration += node.durationMs;
9
- }
10
- }
11
- return duration;
12
- }
13
- }
14
- window.customElements.define("ef-timeline", EFTimeline);
15
- exports.EFTimeline = EFTimeline;
@@ -1,3 +0,0 @@
1
- export declare class EFTimeline extends HTMLElement {
2
- get durationMs(): number;
3
- }
@@ -1,15 +0,0 @@
1
- class EFTimeline extends HTMLElement {
2
- get durationMs() {
3
- let duration = 0;
4
- for (const node of this.childNodes) {
5
- if ("durationMs" in node && typeof node.durationMs === "number") {
6
- duration += node.durationMs;
7
- }
8
- }
9
- return duration;
10
- }
11
- }
12
- window.customElements.define("ef-timeline", EFTimeline);
13
- export {
14
- EFTimeline
15
- };
@@ -1,13 +0,0 @@
1
- export class EFTimeline extends HTMLElement {
2
- get durationMs() {
3
- let duration = 0;
4
- for (const node of this.childNodes) {
5
- if ("durationMs" in node && typeof node.durationMs === "number") {
6
- duration += node.durationMs;
7
- }
8
- }
9
- return duration;
10
- }
11
- }
12
-
13
- window.customElements.define("ef-timeline", EFTimeline);