@editframe/elements 0.18.3-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.
Files changed (110) hide show
  1. package/dist/elements/EFAudio.d.ts +1 -2
  2. package/dist/elements/EFAudio.js +6 -9
  3. package/dist/elements/EFMedia/AssetMediaEngine.browsertest.d.ts +0 -0
  4. package/dist/elements/EFMedia/AssetMediaEngine.d.ts +2 -4
  5. package/dist/elements/EFMedia/AssetMediaEngine.js +34 -5
  6. package/dist/elements/EFMedia/BaseMediaEngine.js +20 -1
  7. package/dist/elements/EFMedia/BufferedSeekingInput.d.ts +5 -5
  8. package/dist/elements/EFMedia/BufferedSeekingInput.js +27 -7
  9. package/dist/elements/EFMedia/JitMediaEngine.d.ts +1 -1
  10. package/dist/elements/EFMedia/JitMediaEngine.js +22 -3
  11. package/dist/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.js +4 -1
  12. package/dist/elements/EFMedia/audioTasks/makeAudioInputTask.js +11 -3
  13. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.d.ts +0 -0
  14. package/dist/elements/EFMedia/audioTasks/makeAudioSeekTask.js +17 -4
  15. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.js +11 -1
  16. package/dist/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.js +3 -2
  17. package/dist/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js +4 -1
  18. package/dist/elements/EFMedia/shared/PrecisionUtils.d.ts +28 -0
  19. package/dist/elements/EFMedia/shared/PrecisionUtils.js +29 -0
  20. package/dist/elements/EFMedia/videoTasks/makeVideoSeekTask.js +11 -2
  21. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.js +11 -1
  22. package/dist/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.js +3 -2
  23. package/dist/elements/EFMedia.d.ts +0 -12
  24. package/dist/elements/EFMedia.js +4 -30
  25. package/dist/elements/EFTimegroup.js +12 -17
  26. package/dist/elements/EFVideo.d.ts +0 -9
  27. package/dist/elements/EFVideo.js +0 -7
  28. package/dist/elements/SampleBuffer.js +6 -6
  29. package/dist/getRenderInfo.d.ts +2 -2
  30. package/dist/gui/ContextMixin.js +71 -17
  31. package/dist/gui/TWMixin.js +1 -1
  32. package/dist/style.css +1 -1
  33. package/dist/transcoding/types/index.d.ts +9 -9
  34. package/package.json +2 -3
  35. package/src/elements/EFAudio.browsertest.ts +7 -7
  36. package/src/elements/EFAudio.ts +7 -20
  37. package/src/elements/EFMedia/AssetMediaEngine.browsertest.ts +100 -0
  38. package/src/elements/EFMedia/AssetMediaEngine.ts +72 -7
  39. package/src/elements/EFMedia/BaseMediaEngine.ts +50 -1
  40. package/src/elements/EFMedia/BufferedSeekingInput.browsertest.ts +135 -54
  41. package/src/elements/EFMedia/BufferedSeekingInput.ts +74 -17
  42. package/src/elements/EFMedia/JitMediaEngine.ts +58 -2
  43. package/src/elements/EFMedia/audioTasks/makeAudioFrequencyAnalysisTask.ts +10 -1
  44. package/src/elements/EFMedia/audioTasks/makeAudioInputTask.ts +16 -8
  45. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.chunkboundary.regression.browsertest.ts +199 -0
  46. package/src/elements/EFMedia/audioTasks/makeAudioSeekTask.ts +35 -4
  47. package/src/elements/EFMedia/audioTasks/makeAudioSegmentFetchTask.ts +12 -1
  48. package/src/elements/EFMedia/audioTasks/makeAudioSegmentIdTask.ts +3 -2
  49. package/src/elements/EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.ts +10 -1
  50. package/src/elements/EFMedia/shared/PrecisionUtils.ts +46 -0
  51. package/src/elements/EFMedia/videoTasks/makeVideoSeekTask.ts +27 -3
  52. package/src/elements/EFMedia/videoTasks/makeVideoSegmentFetchTask.ts +12 -1
  53. package/src/elements/EFMedia/videoTasks/makeVideoSegmentIdTask.ts +3 -2
  54. package/src/elements/EFMedia.browsertest.ts +73 -33
  55. package/src/elements/EFMedia.ts +11 -54
  56. package/src/elements/EFTimegroup.ts +21 -26
  57. package/src/elements/EFVideo.browsertest.ts +895 -162
  58. package/src/elements/EFVideo.ts +0 -16
  59. package/src/elements/SampleBuffer.ts +8 -10
  60. package/src/gui/ContextMixin.ts +104 -26
  61. package/src/transcoding/types/index.ts +10 -6
  62. package/test/EFVideo.framegen.browsertest.ts +1 -1
  63. package/test/__cache__/GET__api_v1_transcode_audio_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__32da3954ba60c96ad732020c65a08ebc/metadata.json +3 -3
  64. package/test/__cache__/GET__api_v1_transcode_audio_1_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__9ed2d25c675aa6bb6ff5b3ae23887c71/data.bin +0 -0
  65. package/test/__cache__/GET__api_v1_transcode_audio_1_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__9ed2d25c675aa6bb6ff5b3ae23887c71/metadata.json +22 -0
  66. package/test/__cache__/GET__api_v1_transcode_audio_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__b0b2b07efcf607de8ee0f650328c32f7/metadata.json +3 -3
  67. package/test/__cache__/GET__api_v1_transcode_audio_2_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__d5a3309a2bf756dd6e304807eb402f56/data.bin +0 -0
  68. package/test/__cache__/GET__api_v1_transcode_audio_2_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__d5a3309a2bf756dd6e304807eb402f56/metadata.json +22 -0
  69. package/test/__cache__/GET__api_v1_transcode_audio_3_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a75c2252b542e0c152c780e9a8d7b154/metadata.json +3 -3
  70. package/test/__cache__/GET__api_v1_transcode_audio_3_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__773254bb671e3466fca8677139fb239e/data.bin +0 -0
  71. package/test/__cache__/GET__api_v1_transcode_audio_3_mp4_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4_bytes_0__773254bb671e3466fca8677139fb239e/metadata.json +22 -0
  72. package/test/__cache__/GET__api_v1_transcode_audio_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a64ff1cfb1b52cae14df4b5dfa1e222b/metadata.json +3 -3
  73. package/test/__cache__/GET__api_v1_transcode_audio_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__e66d2c831d951e74ad0aeaa6489795d0/metadata.json +3 -3
  74. package/test/__cache__/GET__api_v1_transcode_high_1_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__26197f6f7c46cacb0a71134131c3f775/metadata.json +3 -3
  75. package/test/__cache__/GET__api_v1_transcode_high_2_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__4cb6774cd3650ccf59c8f8dc6678c0b9/metadata.json +3 -3
  76. package/test/__cache__/GET__api_v1_transcode_high_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a6fb05a22b18d850f7f2950bbcdbdeed/data.bin +0 -0
  77. package/test/__cache__/GET__api_v1_transcode_high_4_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a6fb05a22b18d850f7f2950bbcdbdeed/metadata.json +21 -0
  78. package/test/__cache__/GET__api_v1_transcode_high_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a50058c7c3602e90879fe3428ed891f4/data.bin +0 -0
  79. package/test/__cache__/GET__api_v1_transcode_high_5_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__a50058c7c3602e90879fe3428ed891f4/metadata.json +21 -0
  80. package/test/__cache__/GET__api_v1_transcode_high_init_m4s_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__0798c479b44aaeef850609a430f6e613/metadata.json +3 -3
  81. package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/data.bin +1 -1
  82. package/test/__cache__/GET__api_v1_transcode_manifest_json_url_http_3A_2F_2Fweb_3A3000_2Fhead_moov_480p_mp4__3be92a0437de726b431ed5af2369158a/metadata.json +4 -4
  83. package/test/recordReplayProxyPlugin.js +50 -0
  84. package/types.json +1 -1
  85. package/dist/DecoderResetFrequency.test.d.ts +0 -1
  86. package/dist/DecoderResetRecovery.test.d.ts +0 -1
  87. package/dist/ScrubTrackManager.d.ts +0 -96
  88. package/dist/elements/EFMedia/services/AudioElementFactory.browsertest.d.ts +0 -1
  89. package/dist/elements/EFMedia/services/AudioElementFactory.d.ts +0 -22
  90. package/dist/elements/EFMedia/services/AudioElementFactory.js +0 -72
  91. package/dist/elements/EFMedia/services/MediaSourceService.browsertest.d.ts +0 -1
  92. package/dist/elements/EFMedia/services/MediaSourceService.d.ts +0 -47
  93. package/dist/elements/EFMedia/services/MediaSourceService.js +0 -73
  94. package/dist/gui/services/ElementConnectionManager.browsertest.d.ts +0 -1
  95. package/dist/gui/services/ElementConnectionManager.d.ts +0 -59
  96. package/dist/gui/services/ElementConnectionManager.js +0 -128
  97. package/dist/gui/services/PlaybackController.browsertest.d.ts +0 -1
  98. package/dist/gui/services/PlaybackController.d.ts +0 -103
  99. package/dist/gui/services/PlaybackController.js +0 -290
  100. package/dist/services/MediaSourceManager.d.ts +0 -62
  101. package/dist/services/MediaSourceManager.js +0 -211
  102. package/src/elements/EFMedia/services/AudioElementFactory.browsertest.ts +0 -325
  103. package/src/elements/EFMedia/services/AudioElementFactory.ts +0 -119
  104. package/src/elements/EFMedia/services/MediaSourceService.browsertest.ts +0 -257
  105. package/src/elements/EFMedia/services/MediaSourceService.ts +0 -102
  106. package/src/gui/services/ElementConnectionManager.browsertest.ts +0 -263
  107. package/src/gui/services/ElementConnectionManager.ts +0 -224
  108. package/src/gui/services/PlaybackController.browsertest.ts +0 -437
  109. package/src/gui/services/PlaybackController.ts +0 -521
  110. package/src/services/MediaSourceManager.ts +0 -333
@@ -8,8 +8,7 @@ import { makeAudioSeekTask } from "./EFMedia/audioTasks/makeAudioSeekTask.js";
8
8
  import { makeAudioSegmentFetchTask } from "./EFMedia/audioTasks/makeAudioSegmentFetchTask.js";
9
9
  import { makeAudioSegmentIdTask } from "./EFMedia/audioTasks/makeAudioSegmentIdTask.js";
10
10
  import { makeAudioTimeDomainAnalysisTask } from "./EFMedia/audioTasks/makeAudioTimeDomainAnalysisTask.js";
11
- import { AudioElementFactory } from "./EFMedia/services/AudioElementFactory.js";
12
- import { MediaSourceService } from "./EFMedia/services/MediaSourceService.js";
11
+ import { fetchAudioSpanningTime } from "./EFMedia/shared/AudioSpanUtils.js";
13
12
  import { EFSourceMixin } from "./EFSourceMixin.js";
14
13
  import { EFTemporal } from "./EFTemporal.js";
15
14
  import { FetchMixin } from "./FetchMixin.js";
@@ -28,13 +27,6 @@ const deepGetMediaElements = (element, medias = []) => {
28
27
  var EFMedia = class extends EFTargetable(EFSourceMixin(EFTemporal(FetchMixin(LitElement)), { assetType: "isobmff_files" })) {
29
28
  constructor(..._args) {
30
29
  super(..._args);
31
- this.mediaSourceService = new MediaSourceService({
32
- onError: (error) => {
33
- console.error("🎵 [EFMedia] MediaSourceService error:", error);
34
- },
35
- onReady: () => {}
36
- });
37
- this.audioElementFactory = new AudioElementFactory();
38
30
  this.currentTimeMs = 0;
39
31
  this.audioBufferDurationMs = 3e4;
40
32
  this.maxAudioBufferFetches = 2;
@@ -112,6 +104,8 @@ var EFMedia = class extends EFTargetable(EFSourceMixin(EFTemporal(FetchMixin(Lit
112
104
  }
113
105
  updated(changedProperties) {
114
106
  super.updated(changedProperties);
107
+ const newCurrentSourceTimeMs = this.currentSourceTimeMs;
108
+ if (newCurrentSourceTimeMs !== this.desiredSeekTimeMs) this.executeSeek(newCurrentSourceTimeMs);
115
109
  if (changedProperties.has("ownCurrentTimeMs")) this.executeSeek(this.currentSourceTimeMs);
116
110
  if (changedProperties.has("currentTime") || changedProperties.has("ownCurrentTimeMs")) updateAnimations(this);
117
111
  }
@@ -132,15 +126,7 @@ var EFMedia = class extends EFTargetable(EFSourceMixin(EFTemporal(FetchMixin(Lit
132
126
  * Now powered by clean, testable utility functions
133
127
  */
134
128
  async fetchAudioSpanningTime(fromMs, toMs, signal = new AbortController().signal) {
135
- await this.mediaSourceService.initialize();
136
- const { fetchAudioSpanningTime: fetchAudioSpan } = await import("./EFMedia/shared/AudioSpanUtils.js");
137
- return fetchAudioSpan(this, fromMs, toMs, signal);
138
- }
139
- /**
140
- * Get the HTML audio element for ContextMixin integration
141
- */
142
- get audioElement() {
143
- return this.mediaSourceService.getAudioElement();
129
+ return fetchAudioSpanningTime(this, fromMs, toMs, signal);
144
130
  }
145
131
  /**
146
132
  * Check if an audio segment is cached in the unified buffer system
@@ -158,18 +144,6 @@ var EFMedia = class extends EFTargetable(EFSourceMixin(EFTemporal(FetchMixin(Lit
158
144
  if (!bufferState) return /* @__PURE__ */ new Set();
159
145
  return new Set(segmentIds.filter((id) => bufferState.cachedSegments.has(id)));
160
146
  }
161
- /**
162
- * Get MediaElementAudioSourceNode for ContextMixin integration
163
- * Uses AudioElementFactory for proper caching and lifecycle management
164
- */
165
- async getMediaElementSource(audioContext) {
166
- return this.audioElementFactory.createMediaElementSource(audioContext, this.mediaSourceService);
167
- }
168
- disconnectedCallback() {
169
- super.disconnectedCallback?.();
170
- this.mediaSourceService.cleanup();
171
- this.audioElementFactory.clearCache();
172
- }
173
147
  };
174
148
  _decorate([property({ type: Number })], EFMedia.prototype, "currentTimeMs", void 0);
175
149
  _decorate([property({
@@ -301,23 +301,18 @@ let EFTimegroup = class EFTimegroup$1 extends EFTemporal(LitElement) {
301
301
  * Usage: timegroup.testPlayAudio(0, 5000) // Play first 5 seconds
302
302
  */
303
303
  async testPlayAudio(fromMs, toMs) {
304
- try {
305
- const renderedBuffer = await this.renderAudio(fromMs, toMs);
306
- const playbackContext = new AudioContext();
307
- const bufferSource = playbackContext.createBufferSource();
308
- bufferSource.buffer = renderedBuffer;
309
- bufferSource.connect(playbackContext.destination);
310
- bufferSource.start(0);
311
- return new Promise((resolve) => {
312
- bufferSource.onended = () => {
313
- playbackContext.close();
314
- resolve();
315
- };
316
- });
317
- } catch (error) {
318
- console.error("🎵 [TEST_PLAY_AUDIO] Error:", error);
319
- throw error;
320
- }
304
+ const renderedBuffer = await this.renderAudio(fromMs, toMs);
305
+ const playbackContext = new AudioContext();
306
+ const bufferSource = playbackContext.createBufferSource();
307
+ bufferSource.buffer = renderedBuffer;
308
+ bufferSource.connect(playbackContext.destination);
309
+ bufferSource.start(0);
310
+ return new Promise((resolve) => {
311
+ bufferSource.onended = () => {
312
+ playbackContext.close();
313
+ resolve();
314
+ };
315
+ });
321
316
  }
322
317
  async loadMd5Sums() {
323
318
  const efElements = this.efElements;
@@ -1,6 +1,5 @@
1
1
  import { Task } from '@lit/task';
2
2
  import { PropertyValueMap } from 'lit';
3
- import { CacheStats, ScrubTrackManager } from '../ScrubTrackManager.js';
4
3
  import { EFMedia } from './EFMedia.js';
5
4
  declare global {
6
5
  var EF_FRAMEGEN: import("../EF_FRAMEGEN.js").EFFramegen;
@@ -36,10 +35,6 @@ export declare class EFVideo extends EFVideo_base {
36
35
  videoInputTask: import('./EFMedia/shared/MediaTaskUtils.ts').InputTask;
37
36
  videoSeekTask: Task<readonly [number, import('./EFMedia/BufferedSeekingInput.ts').BufferedSeekingInput | undefined], import('mediabunny').VideoSample | undefined>;
38
37
  videoBufferTask: Task<readonly [number], import('./EFMedia/videoTasks/makeVideoBufferTask.ts').VideoBufferState>;
39
- /**
40
- * Scrub track manager for fast timeline navigation
41
- */
42
- scrubTrackManager?: ScrubTrackManager;
43
38
  /**
44
39
  * Delayed loading state manager for user feedback
45
40
  */
@@ -84,10 +79,6 @@ export declare class EFVideo extends EFVideo_base {
84
79
  * Check if EF_FRAMEGEN has explicitly started frame rendering (not just initialization)
85
80
  */
86
81
  private isFrameRenderingActive;
87
- /**
88
- * Get scrub track performance statistics
89
- */
90
- getScrubTrackStats(): CacheStats | null;
91
82
  /**
92
83
  * Effective mode - always returns "asset" for EFVideo
93
84
  */
@@ -243,12 +243,6 @@ let EFVideo = class EFVideo$1 extends TWMixin(EFMedia) {
243
243
  return currentTime >= renderStartTime;
244
244
  }
245
245
  /**
246
- * Get scrub track performance statistics
247
- */
248
- getScrubTrackStats() {
249
- return this.scrubTrackManager?.getCacheStats() || null;
250
- }
251
- /**
252
246
  * Effective mode - always returns "asset" for EFVideo
253
247
  */
254
248
  get effectiveMode() {
@@ -307,7 +301,6 @@ let EFVideo = class EFVideo$1 extends TWMixin(EFMedia) {
307
301
  */
308
302
  disconnectedCallback() {
309
303
  super.disconnectedCallback();
310
- this.scrubTrackManager?.cleanup();
311
304
  this.delayedLoadingState.clearAllLoading();
312
305
  }
313
306
  };
@@ -1,3 +1,4 @@
1
+ import { roundToMilliseconds } from "./EFMedia/shared/PrecisionUtils.js";
1
2
  var SampleBuffer = class {
2
3
  constructor(bufferSize = 10) {
3
4
  this.buffer = [];
@@ -28,13 +29,12 @@ var SampleBuffer = class {
28
29
  find(desiredSeekTimeMs) {
29
30
  const currentBuffer = [...this.buffer];
30
31
  if (currentBuffer.length === 0) return void 0;
31
- const roundToMicroseconds = (timeMs) => Math.round(timeMs * 1e3) / 1e3;
32
- const targetTimeMs = roundToMicroseconds(desiredSeekTimeMs);
32
+ const targetTimeMs = roundToMilliseconds(desiredSeekTimeMs);
33
33
  for (const sample of currentBuffer) {
34
- const sampleStartMs = roundToMicroseconds((sample.timestamp || 0) * 1e3);
35
- const sampleDurationMs = roundToMicroseconds((sample.duration || 0) * 1e3);
36
- const sampleEndMs = sampleStartMs + sampleDurationMs;
37
- if (targetTimeMs >= sampleStartMs && targetTimeMs < sampleEndMs) return sample;
34
+ const sampleStartMs = roundToMilliseconds((sample.timestamp || 0) * 1e3);
35
+ const sampleDurationMs = roundToMilliseconds((sample.duration || 0) * 1e3);
36
+ const sampleEndMs = roundToMilliseconds(sampleStartMs + sampleDurationMs);
37
+ if (targetTimeMs >= sampleStartMs && targetTimeMs <= sampleEndMs) return sample;
38
38
  }
39
39
  return void 0;
40
40
  }
@@ -18,20 +18,20 @@ export declare const RenderInfo: z.ZodObject<{
18
18
  efImage: string[];
19
19
  }>;
20
20
  }, "strip", z.ZodTypeAny, {
21
- fps: number;
22
21
  width: number;
23
22
  height: number;
24
23
  durationMs: number;
24
+ fps: number;
25
25
  assets: {
26
26
  efMedia: Record<string, any>;
27
27
  efCaptions: string[];
28
28
  efImage: string[];
29
29
  };
30
30
  }, {
31
- fps: number;
32
31
  width: number;
33
32
  height: number;
34
33
  durationMs: number;
34
+ fps: number;
35
35
  assets: {
36
36
  efMedia: Record<string, any>;
37
37
  efCaptions: string[];
@@ -4,8 +4,6 @@ import { fetchContext } from "./fetchContext.js";
4
4
  import { focusContext } from "./focusContext.js";
5
5
  import { focusedElementContext } from "./focusedElementContext.js";
6
6
  import { loopContext, playingContext } from "./playingContext.js";
7
- import { ElementConnectionManager } from "./services/ElementConnectionManager.js";
8
- import { PlaybackController } from "./services/PlaybackController.js";
9
7
  import { consume, createContext, provide } from "@lit/context";
10
8
  import { property, state } from "lit/decorators.js";
11
9
  import _decorate from "@oxc-project/runtime/helpers/decorate";
@@ -42,19 +40,6 @@ function ContextMixin(superClass) {
42
40
  this.loop = false;
43
41
  this.rendering = false;
44
42
  this.currentTimeMs = 0;
45
- this._elementConnectionManager = new ElementConnectionManager(3e3);
46
- this.playbackController = new PlaybackController({
47
- fps: 30,
48
- onTimeUpdate: (timeMs) => {
49
- this.currentTimeMs = timeMs;
50
- },
51
- onPlayStateChange: (playing) => {
52
- this.playing = playing;
53
- },
54
- onError: (error) => {
55
- console.error("🎵 [PLAYBACK_ERROR]:", error);
56
- }
57
- });
58
43
  }
59
44
  static {
60
45
  this[contextMixinSymbol] = true;
@@ -78,6 +63,8 @@ function ContextMixin(superClass) {
78
63
  set signingURL(value) {
79
64
  this.#signingURL = value;
80
65
  }
66
+ #FPS = 30;
67
+ #MS_PER_FRAME = 1e3 / this.#FPS;
81
68
  #timegroupObserver = new MutationObserver((mutations) => {
82
69
  for (const mutation of mutations) if (mutation.type === "childList") {
83
70
  const newTimegroup = this.querySelector("ef-timegroup");
@@ -119,13 +106,80 @@ function ContextMixin(superClass) {
119
106
  pause() {
120
107
  this.playing = false;
121
108
  }
109
+ #playbackAudioContext = null;
110
+ #playbackAnimationFrameRequest = null;
111
+ #AUDIO_PLAYBACK_SLICE_MS = 47 * 1024 / 48e3 * 1e3;
112
+ #syncPlayheadToAudioContext(target, startMs) {
113
+ const rawTimeMs = startMs + (this.#playbackAudioContext?.currentTime ?? 0) * 1e3;
114
+ const nextTimeMs = Math.round(rawTimeMs / this.#MS_PER_FRAME) * this.#MS_PER_FRAME;
115
+ if (nextTimeMs !== this.currentTimeMs) this.currentTimeMs = nextTimeMs;
116
+ this.#playbackAnimationFrameRequest = requestAnimationFrame(() => {
117
+ this.#syncPlayheadToAudioContext(target, startMs);
118
+ });
119
+ }
122
120
  async stopPlayback() {
123
- await this.playbackController.stopPlayback();
121
+ if (this.#playbackAudioContext) {
122
+ if (this.#playbackAudioContext.state !== "closed") await this.#playbackAudioContext.close();
123
+ }
124
+ if (this.#playbackAnimationFrameRequest) cancelAnimationFrame(this.#playbackAnimationFrameRequest);
125
+ this.#playbackAudioContext = null;
126
+ this.#playbackAnimationFrameRequest = null;
124
127
  }
125
128
  async startPlayback() {
129
+ await this.stopPlayback();
126
130
  const timegroup = this.targetTimegroup;
127
131
  if (!timegroup) return;
128
- await this.playbackController.startPlayback(timegroup, timegroup.currentTimeMs);
132
+ await timegroup.waitForMediaDurations();
133
+ let currentMs = timegroup.currentTimeMs;
134
+ const fromMs = currentMs;
135
+ const toMs = timegroup.endTimeMs;
136
+ if (fromMs >= toMs) {
137
+ this.pause();
138
+ return;
139
+ }
140
+ let bufferCount = 0;
141
+ this.#playbackAudioContext = new AudioContext({ latencyHint: "playback" });
142
+ if (this.#playbackAnimationFrameRequest) cancelAnimationFrame(this.#playbackAnimationFrameRequest);
143
+ this.#syncPlayheadToAudioContext(timegroup, currentMs);
144
+ const playbackContext = this.#playbackAudioContext;
145
+ if (playbackContext.state === "suspended") {
146
+ console.warn("AudioContext is suspended, media playback will not work until user has interacted with page.");
147
+ this.playing = false;
148
+ return;
149
+ }
150
+ await playbackContext.suspend();
151
+ const fillBuffer = async () => {
152
+ if (bufferCount > 2) return;
153
+ const canFillBuffer = await queueBufferSource();
154
+ if (canFillBuffer) fillBuffer();
155
+ };
156
+ const queueBufferSource = async () => {
157
+ if (currentMs >= toMs) return false;
158
+ const startMs = currentMs;
159
+ const endMs = currentMs + this.#AUDIO_PLAYBACK_SLICE_MS;
160
+ currentMs += this.#AUDIO_PLAYBACK_SLICE_MS;
161
+ const audioBuffer = await timegroup.renderAudio(startMs, endMs);
162
+ bufferCount++;
163
+ const source = playbackContext.createBufferSource();
164
+ source.buffer = audioBuffer;
165
+ source.connect(playbackContext.destination);
166
+ source.start((startMs - fromMs) / 1e3);
167
+ source.onended = () => {
168
+ bufferCount--;
169
+ if (endMs >= toMs) {
170
+ this.pause();
171
+ if (this.loop) this.updateComplete.then(() => {
172
+ this.currentTimeMs = 0;
173
+ this.updateComplete.then(() => {
174
+ this.play();
175
+ });
176
+ });
177
+ } else fillBuffer();
178
+ };
179
+ return true;
180
+ };
181
+ await fillBuffer();
182
+ await playbackContext.resume();
129
183
  }
130
184
  }
131
185
  _decorate([consume({
@@ -1,2 +1,2 @@
1
- var TWMixin_default = "*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:\"\"}html,:host{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.top-0{top:0}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.col-span-2{grid-column:span 2/span 2}.mx-2{margin-left:.5rem;margin-right:.5rem}.mb-\\[1px\\]{margin-bottom:1px}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-\\[1\\.1rem\\]{height:1.1rem}.h-\\[270px\\]{height:270px}.h-\\[5px\\]{height:5px}.h-full{height:100%}.w-1{width:.25rem}.w-\\[2px\\]{width:2px}.w-\\[480px\\]{width:480px}.w-full{width:100%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.cursor-crosshair{cursor:crosshair}.resize{resize:both}.flex-wrap{flex-wrap:wrap}.place-content-center{place-content:center}.items-center{align-items:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.text-nowrap{text-wrap:nowrap}.rounded{border-radius:.25rem}.border{border-width:1px}.border-r-2{border-right-width:2px}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity))}.border-red-700{--tw-border-opacity:1;border-color:rgb(185 28 28/var(--tw-border-opacity))}.border-slate-500{--tw-border-opacity:1;border-color:rgb(100 116 139/var(--tw-border-opacity))}.border-b-slate-600{--tw-border-opacity:1;border-bottom-color:rgb(71 85 105/var(--tw-border-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(191 219 254/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity))}.bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity))}.bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity))}.bg-opacity-20{--tw-bg-opacity:.2}.p-\\[1px\\]{padding:1px}.pb-0{padding-bottom:0}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pr-0{padding-right:0}.pr-1{padding-right:.25rem}.pt-\\[8px\\]{padding-top:8px}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-5xl{font-size:3rem;line-height:1}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.line-through{text-decoration-line:line-through}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-slate-300{--tw-shadow-color:#cbd5e1;--tw-shadow:var(--tw-shadow-colored)}.shadow-slate-600{--tw-shadow-color:#475569;--tw-shadow:var(--tw-shadow-colored)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.filter{filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.hover\\:bg-slate-400:hover{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity))}.peer:hover~.peer-hover\\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity))}.peer:hover~.peer-hover\\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}.data-\\[focused\\]\\:bg-slate-400[data-focused]{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity))}.peer[data-focused]~.peer-data-\\[focused\\]\\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity))}.peer[data-focused]~.peer-data-\\[focused\\]\\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}";
1
+ var TWMixin_default = "*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:\"\"}html,:host{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.left-0{left:0}.top-0{top:0}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.col-span-2{grid-column:span 2/span 2}.mx-2{margin-left:.5rem;margin-right:.5rem}.mb-\\[1px\\]{margin-bottom:1px}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.grid{display:grid}.contents{display:contents}.hidden{display:none}.size-full{width:100%;height:100%}.h-\\[1\\.1rem\\]{height:1.1rem}.h-\\[270px\\]{height:270px}.h-\\[500px\\]{height:500px}.h-\\[5px\\]{height:5px}.h-full{height:100%}.w-1{width:.25rem}.w-\\[1000px\\]{width:1000px}.w-\\[2px\\]{width:2px}.w-\\[480px\\]{width:480px}.w-full{width:100%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.cursor-crosshair{cursor:crosshair}.flex-wrap{flex-wrap:wrap}.place-content-center{place-content:center}.items-center{align-items:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.text-nowrap{text-wrap:nowrap}.rounded{border-radius:.25rem}.border{border-width:1px}.border-r-2{border-right-width:2px}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity))}.border-red-700{--tw-border-opacity:1;border-color:rgb(185 28 28/var(--tw-border-opacity))}.border-slate-500{--tw-border-opacity:1;border-color:rgb(100 116 139/var(--tw-border-opacity))}.border-b-slate-600{--tw-border-opacity:1;border-bottom-color:rgb(71 85 105/var(--tw-border-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(191 219 254/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity))}.bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity))}.bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}.bg-slate-500{--tw-bg-opacity:1;background-color:rgb(100 116 139/var(--tw-bg-opacity))}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity))}.bg-opacity-20{--tw-bg-opacity:.2}.p-\\[1px\\]{padding:1px}.pb-0{padding-bottom:0}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pr-0{padding-right:0}.pr-1{padding-right:.25rem}.pt-\\[8px\\]{padding-top:8px}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-5xl{font-size:3rem;line-height:1}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.line-through{text-decoration-line:line-through}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-slate-300{--tw-shadow-color:#cbd5e1;--tw-shadow:var(--tw-shadow-colored)}.shadow-slate-600{--tw-shadow-color:#475569;--tw-shadow:var(--tw-shadow-colored)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.filter{filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.hover\\:bg-slate-400:hover{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity))}.peer:hover~.peer-hover\\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity))}.peer:hover~.peer-hover\\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}.data-\\[focused\\]\\:bg-slate-400[data-focused]{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity))}.peer[data-focused]~.peer-data-\\[focused\\]\\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity))}.peer[data-focused]~.peer-data-\\[focused\\]\\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}";
2
2
  export { TWMixin_default as default };
package/dist/style.css CHANGED
@@ -1,2 +1,2 @@
1
- *,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:""}html,:host{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.top-0{top:0}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.col-span-2{grid-column:span 2/span 2}.mx-2{margin-left:.5rem;margin-right:.5rem}.mb-\[1px\]{margin-bottom:1px}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.grid{display:grid}.contents{display:contents}.hidden{display:none}.h-\[1\.1rem\]{height:1.1rem}.h-\[270px\]{height:270px}.h-\[5px\]{height:5px}.h-full{height:100%}.w-1{width:.25rem}.w-\[2px\]{width:2px}.w-\[480px\]{width:480px}.w-full{width:100%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.cursor-crosshair{cursor:crosshair}.resize{resize:both}.flex-wrap{flex-wrap:wrap}.place-content-center{place-content:center}.items-center{align-items:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.text-nowrap{text-wrap:nowrap}.rounded{border-radius:.25rem}.border{border-width:1px}.border-r-2{border-right-width:2px}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity))}.border-red-700{--tw-border-opacity:1;border-color:rgb(185 28 28/var(--tw-border-opacity))}.border-slate-500{--tw-border-opacity:1;border-color:rgb(100 116 139/var(--tw-border-opacity))}.border-b-slate-600{--tw-border-opacity:1;border-bottom-color:rgb(71 85 105/var(--tw-border-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(191 219 254/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity))}.bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity))}.bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity))}.bg-opacity-20{--tw-bg-opacity:.2}.p-\[1px\]{padding:1px}.pb-0{padding-bottom:0}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pr-0{padding-right:0}.pr-1{padding-right:.25rem}.pt-\[8px\]{padding-top:8px}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-5xl{font-size:3rem;line-height:1}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.line-through{text-decoration-line:line-through}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-slate-300{--tw-shadow-color:#cbd5e1;--tw-shadow:var(--tw-shadow-colored)}.shadow-slate-600{--tw-shadow-color:#475569;--tw-shadow:var(--tw-shadow-colored)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.filter{filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.hover\:bg-slate-400:hover{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity))}.peer:hover~.peer-hover\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity))}.peer:hover~.peer-hover\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}.data-\[focused\]\:bg-slate-400[data-focused]{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity))}.peer[data-focused]~.peer-data-\[focused\]\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity))}.peer[data-focused]~.peer-data-\[focused\]\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}
1
+ *,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:""}html,:host{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]{display:none}*,:before,:after{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.static{position:static}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.left-0{left:0}.top-0{top:0}.isolate{isolation:isolate}.z-10{z-index:10}.z-20{z-index:20}.col-span-2{grid-column:span 2/span 2}.mx-2{margin-left:.5rem;margin-right:.5rem}.mb-\[1px\]{margin-bottom:1px}.block{display:block}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.grid{display:grid}.contents{display:contents}.hidden{display:none}.size-full{width:100%;height:100%}.h-\[1\.1rem\]{height:1.1rem}.h-\[270px\]{height:270px}.h-\[500px\]{height:500px}.h-\[5px\]{height:5px}.h-full{height:100%}.w-1{width:.25rem}.w-\[1000px\]{width:1000px}.w-\[2px\]{width:2px}.w-\[480px\]{width:480px}.w-full{width:100%}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.cursor-crosshair{cursor:crosshair}.flex-wrap{flex-wrap:wrap}.place-content-center{place-content:center}.items-center{align-items:center}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.text-nowrap{text-wrap:nowrap}.rounded{border-radius:.25rem}.border{border-width:1px}.border-r-2{border-right-width:2px}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity))}.border-red-700{--tw-border-opacity:1;border-color:rgb(185 28 28/var(--tw-border-opacity))}.border-slate-500{--tw-border-opacity:1;border-color:rgb(100 116 139/var(--tw-border-opacity))}.border-b-slate-600{--tw-border-opacity:1;border-bottom-color:rgb(71 85 105/var(--tw-border-opacity))}.bg-blue-200{--tw-bg-opacity:1;background-color:rgb(191 219 254/var(--tw-bg-opacity))}.bg-blue-500{--tw-bg-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity))}.bg-red-500{--tw-bg-opacity:1;background-color:rgb(239 68 68/var(--tw-bg-opacity))}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity))}.bg-slate-200{--tw-bg-opacity:1;background-color:rgb(226 232 240/var(--tw-bg-opacity))}.bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}.bg-slate-500{--tw-bg-opacity:1;background-color:rgb(100 116 139/var(--tw-bg-opacity))}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity))}.bg-opacity-20{--tw-bg-opacity:.2}.p-\[1px\]{padding:1px}.pb-0{padding-bottom:0}.pl-1{padding-left:.25rem}.pl-2{padding-left:.5rem}.pr-0{padding-right:0}.pr-1{padding-right:.25rem}.pt-\[8px\]{padding-top:8px}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-5xl{font-size:3rem;line-height:1}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.line-through{text-decoration-line:line-through}.opacity-50{opacity:.5}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-slate-300{--tw-shadow-color:#cbd5e1;--tw-shadow:var(--tw-shadow-colored)}.shadow-slate-600{--tw-shadow-color:#475569;--tw-shadow:var(--tw-shadow-colored)}.outline{outline-style:solid}.blur{--tw-blur:blur(8px);filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.filter{filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur)var(--tw-backdrop-brightness)var(--tw-backdrop-contrast)var(--tw-backdrop-grayscale)var(--tw-backdrop-hue-rotate)var(--tw-backdrop-invert)var(--tw-backdrop-opacity)var(--tw-backdrop-saturate)var(--tw-backdrop-sepia)}.hover\:bg-slate-400:hover{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity))}.peer:hover~.peer-hover\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity))}.peer:hover~.peer-hover\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}.data-\[focused\]\:bg-slate-400[data-focused]{--tw-bg-opacity:1;background-color:rgb(148 163 184/var(--tw-bg-opacity))}.peer[data-focused]~.peer-data-\[focused\]\:border-slate-400{--tw-border-opacity:1;border-color:rgb(148 163 184/var(--tw-border-opacity))}.peer[data-focused]~.peer-data-\[focused\]\:bg-slate-300{--tw-bg-opacity:1;background-color:rgb(203 213 225/var(--tw-bg-opacity))}
2
2
  /*$vite$:1*/
@@ -1,6 +1,4 @@
1
- /**
2
- * Core types and interfaces for JIT Transcoding System
3
- */
1
+ import { MediaRendition } from '../../elements/EFMedia/shared/MediaTaskUtils';
4
2
  export interface QualityPreset {
5
3
  name: string;
6
4
  width: number;
@@ -68,6 +66,8 @@ export interface ManifestVideoRendition {
68
66
  segmentDuration: number;
69
67
  /** Duration of each segment in milliseconds */
70
68
  segmentDurationMs: number;
69
+ /** Actual segment durations array (overrides fixed segmentDurationMs if provided) */
70
+ segmentDurationsMs?: number[];
71
71
  /** Video width in pixels */
72
72
  width: number;
73
73
  /** Video height in pixels */
@@ -94,6 +94,8 @@ export interface ManifestAudioRendition {
94
94
  segmentDuration: number;
95
95
  /** Duration of each segment in milliseconds */
96
96
  segmentDurationMs: number;
97
+ /** Actual segment durations array (overrides fixed segmentDurationMs if provided) */
98
+ segmentDurationsMs?: number[];
97
99
  /** Number of audio channels */
98
100
  channels: number;
99
101
  /** Sample rate in Hz */
@@ -173,12 +175,15 @@ export interface AudioRendition {
173
175
  trackId: number | undefined;
174
176
  src: string;
175
177
  segmentDurationMs?: number;
178
+ segmentDurationsMs?: number[];
179
+ startTimeOffsetMs?: number;
176
180
  }
177
181
  export interface VideoRendition {
178
182
  id?: RenditionId;
179
183
  trackId: number | undefined;
180
184
  src: string;
181
185
  segmentDurationMs?: number;
186
+ segmentDurationsMs?: number[];
182
187
  startTimeOffsetMs?: number;
183
188
  }
184
189
  export interface MediaEngine {
@@ -200,12 +205,7 @@ export interface MediaEngine {
200
205
  trackId: number | undefined;
201
206
  src: string;
202
207
  }, signal?: AbortSignal) => Promise<ArrayBuffer>;
203
- computeSegmentId: (desiredSeekTimeMs: number, rendition: {
204
- id?: RenditionId;
205
- trackId: number | undefined;
206
- src: string;
207
- segmentDurationMs?: number;
208
- }) => number | undefined;
208
+ computeSegmentId: (desiredSeekTimeMs: number, rendition: MediaRendition) => number | undefined;
209
209
  /**
210
210
  * Get the video rendition, or throws if no video rendition is available
211
211
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@editframe/elements",
3
- "version": "0.18.3-beta.0",
3
+ "version": "0.18.8-beta.0",
4
4
  "description": "",
5
5
  "exports": {
6
6
  ".": {
@@ -27,14 +27,13 @@
27
27
  "license": "UNLICENSED",
28
28
  "dependencies": {
29
29
  "@bramus/style-observer": "^1.3.0",
30
- "@editframe/assets": "0.18.3-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",
34
34
  "debug": "^4.3.5",
35
35
  "lit": "^3.1.4",
36
36
  "mediabunny": "^1.1.1",
37
- "mp4box": "^0.5.2",
38
37
  "zod": "^3.24.1"
39
38
  },
40
39
  "devDependencies": {
@@ -124,7 +124,7 @@ describe("EFAudio", () => {
124
124
  render(
125
125
  html`
126
126
  <ef-preview>
127
- <ef-audio src="/test-assets/media/bars-n-tone2.mp4" mode="asset"></ef-audio>
127
+ <ef-audio src="media/bars-n-tone2.mp4" mode="asset"></ef-audio>
128
128
  </ef-preview>
129
129
  `,
130
130
  container,
@@ -151,11 +151,11 @@ describe("EFAudio", () => {
151
151
  "Fragment index loading failed, skipping duration test:",
152
152
  error,
153
153
  );
154
- expect(audio.src).toBe("/test-assets/media/bars-n-tone2.mp4");
154
+ expect(audio.src).toBe("media/bars-n-tone2.mp4");
155
155
  return;
156
156
  }
157
157
 
158
- expect(audio.src).toBe("/test-assets/media/bars-n-tone2.mp4");
158
+ expect(audio.src).toBe("media/bars-n-tone2.mp4");
159
159
 
160
160
  // The audio should have loaded successfully and have a duration > 0
161
161
  // We don't test for specific duration since real assets may vary
@@ -272,7 +272,7 @@ describe("EFAudio", () => {
272
272
  html`
273
273
  <ef-preview>
274
274
  <ef-timegroup mode="sequence">
275
- <ef-audio src="/test-assets/media/bars-n-tone2.mp4" mode="asset"></ef-audio>
275
+ <ef-audio src="media/bars-n-tone2.mp4" mode="asset"></ef-audio>
276
276
  </ef-timegroup>
277
277
  </ef-preview>
278
278
  `,
@@ -612,7 +612,7 @@ describe("EFAudio", () => {
612
612
  html`
613
613
  <ef-preview>
614
614
  <ef-timegroup mode="sequence">
615
- <ef-audio src="/test-assets/media/bars-n-tone2.mp4" mode="asset"></ef-audio>
615
+ <ef-audio src="media/bars-n-tone2.mp4" mode="asset"></ef-audio>
616
616
  </ef-timegroup>
617
617
  </ef-preview>
618
618
  `,
@@ -637,7 +637,7 @@ describe("EFAudio", () => {
637
637
  html`
638
638
  <ef-preview>
639
639
  <ef-timegroup mode="contain">
640
- <ef-audio src="/test-assets/media/bars-n-tone2.mp4" mode="asset" sourcein="1s" sourceout="4s"></ef-audio>
640
+ <ef-audio src="media/bars-n-tone2.mp4" mode="asset" sourcein="1s" sourceout="4s"></ef-audio>
641
641
  </ef-timegroup>
642
642
  </ef-preview>
643
643
  `,
@@ -688,7 +688,7 @@ describe("EFAudio", () => {
688
688
  render(
689
689
  html`
690
690
  <ef-preview>
691
- <ef-audio src="/test-assets/media/bars-n-tone2.mp4" mode="asset"></ef-audio>
691
+ <ef-audio src="media/bars-n-tone2.mp4" mode="asset"></ef-audio>
692
692
  </ef-preview>
693
693
  `,
694
694
  container,
@@ -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