@editframe/elements 0.18.7-beta.0 → 0.18.8-beta.0

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.
@@ -2,8 +2,7 @@ import { Task } from '@lit/task';
2
2
  import { EFMedia } from './EFMedia.js';
3
3
  declare const EFAudio_base: typeof EFMedia;
4
4
  export declare class EFAudio extends EFAudio_base {
5
- static get observedAttributes(): string[];
6
- attributeChangedCallback(name: string, old: string | null, value: string | null): void;
5
+ private _propertyHack;
7
6
  audioElementRef: import('lit-html/directives/ref.js').Ref<HTMLAudioElement>;
8
7
  render(): import('lit-html').TemplateResult<1>;
9
8
  frameTask: Task<readonly [import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus, import('@lit/task').TaskStatus], void>;
@@ -2,12 +2,13 @@ import { EFMedia } from "./EFMedia.js";
2
2
  import { TWMixin } from "../gui/TWMixin2.js";
3
3
  import { Task } from "@lit/task";
4
4
  import { html } from "lit";
5
- import { customElement } from "lit/decorators.js";
5
+ import { customElement, property } from "lit/decorators.js";
6
6
  import _decorate from "@oxc-project/runtime/helpers/decorate";
7
7
  import { createRef, ref } from "lit/directives/ref.js";
8
8
  let EFAudio = class EFAudio$1 extends TWMixin(EFMedia) {
9
9
  constructor(..._args) {
10
10
  super(..._args);
11
+ this._propertyHack = false;
11
12
  this.audioElementRef = createRef();
12
13
  this.frameTask = new Task(this, {
13
14
  args: () => [
@@ -25,14 +26,6 @@ let EFAudio = class EFAudio$1 extends TWMixin(EFMedia) {
25
26
  }
26
27
  });
27
28
  }
28
- static get observedAttributes() {
29
- const parentAttributes = super.observedAttributes || [];
30
- return [...parentAttributes];
31
- }
32
- attributeChangedCallback(name, old, value) {
33
- super.attributeChangedCallback(name, old, value);
34
- if (name === "asset-id") this.assetId = value;
35
- }
36
29
  render() {
37
30
  return html`<audio ${ref(this.audioElementRef)}></audio>`;
38
31
  }
@@ -61,5 +54,9 @@ let EFAudio = class EFAudio$1 extends TWMixin(EFMedia) {
61
54
  return this.audioBufferTask;
62
55
  }
63
56
  };
57
+ _decorate([property({
58
+ type: Boolean,
59
+ attribute: "dummy-property"
60
+ })], EFAudio.prototype, "_propertyHack", void 0);
64
61
  EFAudio = _decorate([customElement("ef-audio")], EFAudio);
65
62
  export { EFAudio };
@@ -82,9 +82,15 @@ var AssetMediaEngine = class AssetMediaEngine extends BaseMediaEngine {
82
82
  * Calculate audio segments for variable-duration segments using track fragment index
83
83
  */
84
84
  calculateAudioSegmentRange(fromMs, toMs, rendition, _durationMs) {
85
- if (fromMs >= toMs || !rendition.trackId) return [];
85
+ if (fromMs >= toMs || !rendition.trackId) {
86
+ console.warn(`calculateAudioSegmentRange: invalid fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify(rendition)}`);
87
+ return [];
88
+ }
86
89
  const track = this.data[rendition.trackId];
87
- if (!track) return [];
90
+ if (!track) {
91
+ console.warn(`calculateAudioSegmentRange: track not found for rendition ${JSON.stringify(rendition)}`);
92
+ return [];
93
+ }
88
94
  const { timescale, segments } = track;
89
95
  const segmentRanges = [];
90
96
  for (let i = 0; i < segments.length; i++) {
@@ -99,6 +105,10 @@ var AssetMediaEngine = class AssetMediaEngine extends BaseMediaEngine {
99
105
  endMs: segmentEndMs
100
106
  });
101
107
  }
108
+ if (segmentRanges.length === 0) console.warn(`calculateAudioSegmentRange: no segments found for fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify({
109
+ rendition,
110
+ track
111
+ })}`);
102
112
  return segmentRanges;
103
113
  }
104
114
  computeSegmentId(desiredSeekTimeMs, rendition) {
@@ -4,8 +4,13 @@ const makeAudioSeekTask = (host) => {
4
4
  return new Task(host, {
5
5
  args: () => [host.desiredSeekTimeMs, host.audioInputTask.value],
6
6
  onError: (error) => {
7
- if (error instanceof IgnorableError) console.info("audioSeekTask aborted");
8
- console.error("audioSeekTask error", error);
7
+ if (error instanceof IgnorableError) {
8
+ console.info("audioSeekTask aborted");
9
+ return;
10
+ }
11
+ if (error instanceof DOMException) console.error(`audioSeekTask error: ${error.message} ${error.name} ${error.code}`);
12
+ else if (error instanceof Error) console.error(`audioSeekTask error ${error.name}: ${error.message}`);
13
+ else console.error("audioSeekTask unknown error", error);
9
14
  },
10
15
  onComplete: (_value) => {},
11
16
  task: async ([targetSeekTimeMs], { signal }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@editframe/elements",
3
- "version": "0.18.7-beta.0",
3
+ "version": "0.18.8-beta.0",
4
4
  "description": "",
5
5
  "exports": {
6
6
  ".": {
@@ -27,7 +27,7 @@
27
27
  "license": "UNLICENSED",
28
28
  "dependencies": {
29
29
  "@bramus/style-observer": "^1.3.0",
30
- "@editframe/assets": "0.18.7-beta.0",
30
+ "@editframe/assets": "0.18.8-beta.0",
31
31
  "@lit/context": "^1.1.2",
32
32
  "@lit/task": "^1.0.1",
33
33
  "d3": "^7.9.0",
@@ -1,31 +1,18 @@
1
1
  import { Task } from "@lit/task";
2
2
  import { html } from "lit";
3
- import { customElement } from "lit/decorators.js";
3
+ import { customElement, property } from "lit/decorators.js";
4
4
  import { createRef, ref } from "lit/directives/ref.js";
5
5
  import { TWMixin } from "../gui/TWMixin.js";
6
6
  import { EFMedia } from "./EFMedia.js";
7
7
 
8
8
  @customElement("ef-audio")
9
9
  export class EFAudio extends TWMixin(EFMedia) {
10
- static get observedAttributes() {
11
- // biome-ignore lint/complexity/noThisInStatic: We need to access super
12
- const parentAttributes = super.observedAttributes || [];
13
- return [...parentAttributes];
14
- }
15
-
16
- attributeChangedCallback(
17
- name: string,
18
- old: string | null,
19
- value: string | null,
20
- ) {
21
- super.attributeChangedCallback(name, old, value);
22
-
23
- // Explicitly handle asset-id attribute to property conversion
24
- // EFVideo works without this fix, but EFAudio requires it due to some fundamental difference
25
- if (name === "asset-id") {
26
- this.assetId = value;
27
- }
28
- }
10
+ // HACK: This dummy property is needed to activate Lit's property processing system
11
+ // Without it, inherited properties from EFMedia don't work correctly
12
+ // TODO: Remove this as soon as we have an audio-specific property that needs @property
13
+ @property({ type: Boolean, attribute: "dummy-property" })
14
+ // @ts-expect-error - This is a hack to activate Lit's property processing system
15
+ private _propertyHack = false;
29
16
 
30
17
  audioElementRef = createRef<HTMLAudioElement>();
31
18
 
@@ -156,11 +156,21 @@ export class AssetMediaEngine extends BaseMediaEngine implements MediaEngine {
156
156
  _durationMs: number,
157
157
  ): SegmentTimeRange[] {
158
158
  if (fromMs >= toMs || !rendition.trackId) {
159
+ console.warn(
160
+ `calculateAudioSegmentRange: invalid fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify(
161
+ rendition,
162
+ )}`,
163
+ );
159
164
  return [];
160
165
  }
161
166
 
162
167
  const track = this.data[rendition.trackId];
163
168
  if (!track) {
169
+ console.warn(
170
+ `calculateAudioSegmentRange: track not found for rendition ${JSON.stringify(
171
+ rendition,
172
+ )}`,
173
+ );
164
174
  return [];
165
175
  }
166
176
 
@@ -186,6 +196,16 @@ export class AssetMediaEngine extends BaseMediaEngine implements MediaEngine {
186
196
  });
187
197
  }
188
198
  }
199
+ if (segmentRanges.length === 0) {
200
+ console.warn(
201
+ `calculateAudioSegmentRange: no segments found for fromMs ${fromMs} toMs ${toMs} rendition ${JSON.stringify(
202
+ {
203
+ rendition,
204
+ track,
205
+ },
206
+ )}`,
207
+ );
208
+ }
189
209
 
190
210
  return segmentRanges;
191
211
  }
@@ -13,8 +13,17 @@ export const makeAudioSeekTask = (host: EFMedia): AudioSeekTask => {
13
13
  onError: (error) => {
14
14
  if (error instanceof IgnorableError) {
15
15
  console.info("audioSeekTask aborted");
16
+ return;
17
+ }
18
+ if (error instanceof DOMException) {
19
+ console.error(
20
+ `audioSeekTask error: ${error.message} ${error.name} ${error.code}`,
21
+ );
22
+ } else if (error instanceof Error) {
23
+ console.error(`audioSeekTask error ${error.name}: ${error.message}`);
24
+ } else {
25
+ console.error("audioSeekTask unknown error", error);
16
26
  }
17
- console.error("audioSeekTask error", error);
18
27
  },
19
28
  onComplete: (_value) => {},
20
29
  task: async (