ngx-kit 7.3.3 → 8.0.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 (37) hide show
  1. package/drag-resize/README.md +25 -3
  2. package/fesm2022/ngx-kit-box-shadow.mjs +2 -2
  3. package/fesm2022/ngx-kit-box-shadow.mjs.map +1 -1
  4. package/fesm2022/ngx-kit-data-table.mjs +3 -3
  5. package/fesm2022/ngx-kit-data-table.mjs.map +1 -1
  6. package/fesm2022/ngx-kit-date-picker.mjs +27 -22
  7. package/fesm2022/ngx-kit-date-picker.mjs.map +1 -1
  8. package/fesm2022/ngx-kit-dialog.mjs +17 -12
  9. package/fesm2022/ngx-kit-dialog.mjs.map +1 -1
  10. package/fesm2022/ngx-kit-drag-resize.mjs +1311 -406
  11. package/fesm2022/ngx-kit-drag-resize.mjs.map +1 -1
  12. package/fesm2022/ngx-kit-image-viewer.mjs +348 -0
  13. package/fesm2022/ngx-kit-image-viewer.mjs.map +1 -0
  14. package/fesm2022/ngx-kit-media-control-mse-media-engine-CtP97cb9.mjs +326 -0
  15. package/fesm2022/ngx-kit-media-control-mse-media-engine-CtP97cb9.mjs.map +1 -0
  16. package/fesm2022/ngx-kit-media-control.mjs +1847 -0
  17. package/fesm2022/ngx-kit-media-control.mjs.map +1 -0
  18. package/fesm2022/ngx-kit-notify.mjs +2 -2
  19. package/fesm2022/ngx-kit-notify.mjs.map +1 -1
  20. package/fesm2022/ngx-kit-side-nav.mjs +170 -0
  21. package/fesm2022/ngx-kit-side-nav.mjs.map +1 -0
  22. package/{gallery → image-viewer}/README.md +43 -7
  23. package/media-control/README.md +349 -0
  24. package/package.json +13 -9
  25. package/side-nav/README.md +11 -0
  26. package/types/ngx-kit-date-picker.d.ts +1 -1
  27. package/types/ngx-kit-dialog.d.ts +7 -4
  28. package/types/ngx-kit-drag-resize.d.ts +135 -39
  29. package/types/{ngx-kit-gallery.d.ts → ngx-kit-image-viewer.d.ts} +5 -39
  30. package/types/ngx-kit-media-control.d.ts +671 -0
  31. package/types/ngx-kit-side-nav.d.ts +53 -0
  32. package/drawer-menu/README.md +0 -125
  33. package/fesm2022/ngx-kit-drawer-menu.mjs +0 -456
  34. package/fesm2022/ngx-kit-drawer-menu.mjs.map +0 -1
  35. package/fesm2022/ngx-kit-gallery.mjs +0 -419
  36. package/fesm2022/ngx-kit-gallery.mjs.map +0 -1
  37. package/types/ngx-kit-drawer-menu.d.ts +0 -161
@@ -0,0 +1,326 @@
1
+ import { signal } from '@angular/core';
2
+ import { initialMediaState, hasMediaSource, NgxMediaError } from './ngx-kit-media-control.mjs';
3
+
4
+ function rangesEqual(a, b) {
5
+ if (a.length !== b.length)
6
+ return false;
7
+ for (let i = 0; i < a.length; i++) {
8
+ if (a[i].start !== b[i].start || a[i].end !== b[i].end)
9
+ return false;
10
+ }
11
+ return true;
12
+ }
13
+ function bufferedRanges(el) {
14
+ const ranges = [];
15
+ const b = el.buffered;
16
+ for (let i = 0; i < b.length; i++) {
17
+ ranges.push({ start: b.start(i), end: b.end(i) });
18
+ }
19
+ return ranges;
20
+ }
21
+ /**
22
+ * Wires the standard set of `HTMLMediaElement` events into `patch()` the
23
+ * same way for every engine that ultimately plays through a real media
24
+ * element (native, MSE, ...) — extracted so the MSE engine doesn't drift
25
+ * from the native engine's state-reporting behavior (buffering, seeking,
26
+ * volumechange, ratechange, etc. all need to reach the UI the same way
27
+ * regardless of which engine is currently active). Returns a cleanup
28
+ * function that removes every listener it added.
29
+ */
30
+ function bindMediaElementEvents(el, patch, getState, runOutsideAngular = (fn) => fn()) {
31
+ const cleanupFns = [];
32
+ runOutsideAngular(() => {
33
+ const on = (type, handler) => {
34
+ el.addEventListener(type, handler);
35
+ cleanupFns.push(() => el.removeEventListener(type, handler));
36
+ };
37
+ on('waiting', () => patch({ playback: 'buffering' }));
38
+ on('playing', () => patch({ playback: 'playing' }));
39
+ on('pause', () => {
40
+ if (getState().playback !== 'ended')
41
+ patch({ playback: 'paused' });
42
+ });
43
+ on('ended', () => patch({ playback: 'ended' }));
44
+ on('seeked', () => patch({ playback: el.paused ? 'paused' : 'playing', currentTime: el.currentTime }));
45
+ on('timeupdate', () => patch({ currentTime: el.currentTime }));
46
+ on('durationchange', () => {
47
+ if (Number.isFinite(el.duration))
48
+ patch({ duration: el.duration });
49
+ });
50
+ on('progress', () => {
51
+ const ranges = bufferedRanges(el);
52
+ if (!rangesEqual(ranges, getState().buffered))
53
+ patch({ buffered: ranges });
54
+ });
55
+ on('volumechange', () => patch({ volume: el.volume, muted: el.muted }));
56
+ on('ratechange', () => patch({ playbackRate: el.playbackRate }));
57
+ });
58
+ return () => cleanupFns.forEach((fn) => fn());
59
+ }
60
+
61
+ /**
62
+ * Advanced backend for progressive/segmented delivery via MediaSource
63
+ * Extensions. This module is only ever reached through a dynamic `import()`
64
+ * so ordinary file playback never pulls it into the initial bundle.
65
+ *
66
+ * Scope note (unchanged, worth restating): this is a real, working
67
+ * single-SourceBuffer progressive-fetch engine — it is NOT a full
68
+ * adaptive-bitrate/DASH-HLS manifest player, and it does not demux/transmux
69
+ * arbitrary bytes into valid media segments. It assumes the response body
70
+ * is already a sequence of valid segments for the given mime/codecs (e.g. a
71
+ * server that already serves fragmented MP4/WebM appropriate for MSE).
72
+ * Feeding it arbitrary non-segmented bytes will fail at `appendBuffer()`,
73
+ * which surfaces as a `DECODER`-category `NgxMediaError`, not silently.
74
+ *
75
+ * `load()` resolves as soon as the element has enough data to start
76
+ * playback (`loadedmetadata`) rather than waiting for the entire response
77
+ * to be read — the background pump keeps appending segments after `load()`
78
+ * has already resolved, which is the point of "progressive" in the name.
79
+ */
80
+ class MseMediaEngine {
81
+ requestHandler;
82
+ id = 'mse';
83
+ kind;
84
+ _state = signal(initialMediaState(), /* @ts-ignore */
85
+ ...(ngDevMode ? [{ debugName: "_state" }] : /* istanbul ignore next */ []));
86
+ state = this._state.asReadonly();
87
+ el;
88
+ mediaSource = null;
89
+ sourceBuffer = null;
90
+ reader = null;
91
+ objectUrl = null;
92
+ loadController = null;
93
+ destroyed = false;
94
+ cleanupFns = [];
95
+ constructor(kind, requestHandler, existingElement) {
96
+ this.requestHandler = requestHandler;
97
+ if (!hasMediaSource()) {
98
+ throw NgxMediaError.unsupported('MediaSource Extensions are not supported in this browser.');
99
+ }
100
+ this.kind = kind;
101
+ this.el = existingElement ?? document.createElement(kind);
102
+ this.el.setAttribute('playsinline', 'true');
103
+ this.cleanupFns.push(bindMediaElementEvents(this.el, (p) => this.patch(p), () => this._state(), (fn) => fn()));
104
+ }
105
+ get mediaElement() {
106
+ return this.el;
107
+ }
108
+ async load(source, signal) {
109
+ if (this.destroyed)
110
+ throw new NgxMediaError('ABORTED', 'MSE engine has been destroyed.');
111
+ // A new source supersedes any previous stream. Without this, the old
112
+ // reader can continue fetching/appending while the new MediaSource is
113
+ // being opened, causing duplicate network traffic and leaked resources.
114
+ this.loadController?.abort();
115
+ this.loadController = null;
116
+ this.reader?.cancel().catch(() => { });
117
+ this.reader = null;
118
+ this.releaseObjectUrl();
119
+ const controller = new AbortController();
120
+ const forwardAbort = () => controller.abort();
121
+ if (signal?.aborted)
122
+ controller.abort();
123
+ else
124
+ signal?.addEventListener('abort', forwardAbort, { once: true });
125
+ this.loadController = controller;
126
+ const activeSignal = controller.signal;
127
+ this.patch({ playback: 'loading', currentTime: 0, duration: 0, buffered: [] });
128
+ const mediaSource = new MediaSource();
129
+ this.mediaSource = mediaSource;
130
+ this.objectUrl = URL.createObjectURL(mediaSource);
131
+ this.el.src = this.objectUrl;
132
+ const metadataOrError = deferred();
133
+ const onMetadata = () => metadataOrError.resolveIfPending();
134
+ this.el.addEventListener('loadedmetadata', onMetadata, { once: true });
135
+ const abortPromise = new Promise((_, reject) => {
136
+ if (activeSignal.aborted) {
137
+ reject(new NgxMediaError('ABORTED', 'MSE load aborted.'));
138
+ return;
139
+ }
140
+ activeSignal.addEventListener('abort', () => reject(new NgxMediaError('ABORTED', 'MSE load aborted.')), { once: true });
141
+ });
142
+ try {
143
+ await Promise.race([
144
+ new Promise((resolve, reject) => {
145
+ mediaSource.addEventListener('sourceopen', async () => {
146
+ try {
147
+ if (this.destroyed || activeSignal.aborted || this.mediaSource !== mediaSource) {
148
+ throw new NgxMediaError('ABORTED', 'MSE load superseded.');
149
+ }
150
+ const mime = source.type
151
+ ? source.codecs
152
+ ? `${source.type}; codecs="${source.codecs}"`
153
+ : source.type
154
+ : 'video/mp4';
155
+ if (!MediaSource.isTypeSupported(mime)) {
156
+ throw NgxMediaError.unsupported(`MSE: unsupported mime/codec combination "${mime}".`);
157
+ }
158
+ this.sourceBuffer = mediaSource.addSourceBuffer(mime);
159
+ this.streamInto(this.sourceBuffer, source, activeSignal)
160
+ .then(() => metadataOrError.resolveIfPending())
161
+ .catch((err) => {
162
+ if (!this.destroyed && this.mediaSource === mediaSource)
163
+ this.patch({ playback: 'error' });
164
+ metadataOrError.rejectIfPending(err);
165
+ });
166
+ resolve();
167
+ }
168
+ catch (err) {
169
+ reject(err);
170
+ }
171
+ }, { once: true });
172
+ }),
173
+ abortPromise,
174
+ ]);
175
+ await Promise.race([metadataOrError.promise, abortPromise]);
176
+ if (this.destroyed || this.mediaSource !== mediaSource) {
177
+ throw new NgxMediaError('ABORTED', 'MSE load was superseded.');
178
+ }
179
+ this.patch({ playback: 'ready' });
180
+ }
181
+ finally {
182
+ this.el.removeEventListener('loadedmetadata', onMetadata);
183
+ signal?.removeEventListener('abort', forwardAbort);
184
+ if (this.loadController === controller)
185
+ this.loadController = null;
186
+ }
187
+ }
188
+ async streamInto(buffer, source, signal) {
189
+ const response = await this.requestHandler.request(source, signal);
190
+ if (!response.ok) {
191
+ throw new NgxMediaError('NETWORK', `MSE: server responded ${response.status} for the media source.`);
192
+ }
193
+ if (!response.body) {
194
+ throw new NgxMediaError('NETWORK', 'Response has no readable body for MSE streaming.');
195
+ }
196
+ this.reader = response.body.getReader();
197
+ const pump = async () => {
198
+ if (this.destroyed)
199
+ return;
200
+ const { done, value } = await this.reader.read();
201
+ if (this.destroyed)
202
+ return;
203
+ if (done) {
204
+ if (this.mediaSource?.readyState === 'open')
205
+ this.mediaSource.endOfStream();
206
+ return;
207
+ }
208
+ await this.appendWhenReady(buffer, value);
209
+ return pump();
210
+ };
211
+ await pump();
212
+ }
213
+ appendWhenReady(buffer, chunk) {
214
+ return new Promise((resolve, reject) => {
215
+ if (this.destroyed) {
216
+ resolve();
217
+ return;
218
+ }
219
+ const append = () => {
220
+ if (this.destroyed) {
221
+ resolve();
222
+ return;
223
+ }
224
+ try {
225
+ buffer.appendBuffer(chunk);
226
+ }
227
+ catch (err) {
228
+ reject(new NgxMediaError('DECODER', 'MSE: appendBuffer() rejected a chunk — the response body is not a sequence of valid media segments for this mime/codecs.', err));
229
+ return;
230
+ }
231
+ const onDone = () => {
232
+ buffer.removeEventListener('updateend', onDone);
233
+ resolve();
234
+ };
235
+ buffer.addEventListener('updateend', onDone, { once: true });
236
+ };
237
+ if (buffer.updating) {
238
+ buffer.addEventListener('updateend', append, { once: true });
239
+ }
240
+ else {
241
+ append();
242
+ }
243
+ });
244
+ }
245
+ async play() {
246
+ if (this.destroyed)
247
+ throw new NgxMediaError('ABORTED', 'MSE engine has been destroyed.');
248
+ try {
249
+ await this.el.play();
250
+ }
251
+ catch (err) {
252
+ if (err instanceof DOMException && err.name === 'NotAllowedError') {
253
+ throw NgxMediaError.autoplayBlocked(err);
254
+ }
255
+ throw err;
256
+ }
257
+ }
258
+ pause() {
259
+ this.el.pause();
260
+ }
261
+ seek(time) {
262
+ this.el.currentTime = time;
263
+ }
264
+ setVolume(volume) {
265
+ this.el.volume = volume;
266
+ }
267
+ setMuted(muted) {
268
+ this.el.muted = muted;
269
+ }
270
+ setPlaybackRate(rate) {
271
+ this.el.playbackRate = rate;
272
+ }
273
+ destroy() {
274
+ if (this.destroyed)
275
+ return;
276
+ this.destroyed = true;
277
+ this.loadController?.abort();
278
+ this.loadController = null;
279
+ this.reader?.cancel().catch(() => { });
280
+ this.reader = null;
281
+ this.cleanupFns.forEach((fn) => fn());
282
+ this.cleanupFns.length = 0;
283
+ this.el.pause();
284
+ this.releaseObjectUrl();
285
+ this.el.removeAttribute('src');
286
+ this.mediaSource = null;
287
+ this.sourceBuffer = null;
288
+ this.patch({ playback: 'destroyed' });
289
+ }
290
+ releaseObjectUrl() {
291
+ if (this.objectUrl) {
292
+ URL.revokeObjectURL(this.objectUrl);
293
+ this.objectUrl = null;
294
+ }
295
+ }
296
+ patch(partial) {
297
+ this._state.update((s) => ({ ...s, ...partial }));
298
+ }
299
+ }
300
+ function deferred() {
301
+ let settled = false;
302
+ let resolveFn;
303
+ let rejectFn;
304
+ const promise = new Promise((res, rej) => {
305
+ resolveFn = res;
306
+ rejectFn = rej;
307
+ });
308
+ return {
309
+ promise,
310
+ resolveIfPending: (v) => {
311
+ if (!settled) {
312
+ settled = true;
313
+ resolveFn(v);
314
+ }
315
+ },
316
+ rejectIfPending: (e) => {
317
+ if (!settled) {
318
+ settled = true;
319
+ rejectFn(e);
320
+ }
321
+ },
322
+ };
323
+ }
324
+
325
+ export { MseMediaEngine };
326
+ //# sourceMappingURL=ngx-kit-media-control-mse-media-engine-CtP97cb9.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ngx-kit-media-control-mse-media-engine-CtP97cb9.mjs","sources":["../../../projects/libs/media-control/engines/media-element-events.ts","../../../projects/libs/media-control/engines/mse-media-engine.ts"],"sourcesContent":["import { NgxMediaState, NgxTimeRange } from '../contracts/media-state';\n\nfunction rangesEqual(a: readonly NgxTimeRange[], b: readonly NgxTimeRange[]): boolean {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i].start !== b[i].start || a[i].end !== b[i].end) return false;\n }\n return true;\n}\n\nfunction bufferedRanges(el: HTMLMediaElement): NgxTimeRange[] {\n const ranges: NgxTimeRange[] = [];\n const b = el.buffered;\n for (let i = 0; i < b.length; i++) {\n ranges.push({ start: b.start(i), end: b.end(i) });\n }\n return ranges;\n}\n\n/**\n * Wires the standard set of `HTMLMediaElement` events into `patch()` the\n * same way for every engine that ultimately plays through a real media\n * element (native, MSE, ...) — extracted so the MSE engine doesn't drift\n * from the native engine's state-reporting behavior (buffering, seeking,\n * volumechange, ratechange, etc. all need to reach the UI the same way\n * regardless of which engine is currently active). Returns a cleanup\n * function that removes every listener it added.\n */\nexport function bindMediaElementEvents(\n el: HTMLMediaElement,\n patch: (partial: Partial<NgxMediaState>) => void,\n getState: () => NgxMediaState,\n runOutsideAngular: <T>(fn: () => T) => T = (fn) => fn(),\n): () => void {\n const cleanupFns: Array<() => void> = [];\n runOutsideAngular(() => {\n const on = <K extends keyof HTMLMediaElementEventMap>(\n type: K,\n handler: (ev: HTMLMediaElementEventMap[K]) => void,\n ) => {\n el.addEventListener(type, handler as EventListener);\n cleanupFns.push(() => el.removeEventListener(type, handler as EventListener));\n };\n\n on('waiting', () => patch({ playback: 'buffering' }));\n on('playing', () => patch({ playback: 'playing' }));\n on('pause', () => {\n if (getState().playback !== 'ended') patch({ playback: 'paused' });\n });\n on('ended', () => patch({ playback: 'ended' }));\n on('seeked', () => patch({ playback: el.paused ? 'paused' : 'playing', currentTime: el.currentTime }));\n on('timeupdate', () => patch({ currentTime: el.currentTime }));\n on('durationchange', () => {\n if (Number.isFinite(el.duration)) patch({ duration: el.duration });\n });\n on('progress', () => {\n const ranges = bufferedRanges(el);\n if (!rangesEqual(ranges, getState().buffered)) patch({ buffered: ranges });\n });\n on('volumechange', () => patch({ volume: el.volume, muted: el.muted }));\n on('ratechange', () => patch({ playbackRate: el.playbackRate }));\n });\n\n return () => cleanupFns.forEach((fn) => fn());\n}\n","import { signal, Signal } from '@angular/core';\nimport { NgxMediaSource } from '../contracts/media-source';\nimport { initialMediaState, NgxMediaState } from '../contracts/media-state';\nimport { NgxMediaError } from '../contracts/media-error';\nimport { NgxMediaEngine, NgxMediaKind } from './media-engine.interface';\nimport { hasMediaSource } from '../utils/capabilities';\nimport { NgxMediaRequestHandler } from '../decoders/decoder.tokens';\nimport { bindMediaElementEvents } from './media-element-events';\n\n/**\n * Advanced backend for progressive/segmented delivery via MediaSource\n * Extensions. This module is only ever reached through a dynamic `import()`\n * so ordinary file playback never pulls it into the initial bundle.\n *\n * Scope note (unchanged, worth restating): this is a real, working\n * single-SourceBuffer progressive-fetch engine — it is NOT a full\n * adaptive-bitrate/DASH-HLS manifest player, and it does not demux/transmux\n * arbitrary bytes into valid media segments. It assumes the response body\n * is already a sequence of valid segments for the given mime/codecs (e.g. a\n * server that already serves fragmented MP4/WebM appropriate for MSE).\n * Feeding it arbitrary non-segmented bytes will fail at `appendBuffer()`,\n * which surfaces as a `DECODER`-category `NgxMediaError`, not silently.\n *\n * `load()` resolves as soon as the element has enough data to start\n * playback (`loadedmetadata`) rather than waiting for the entire response\n * to be read — the background pump keeps appending segments after `load()`\n * has already resolved, which is the point of \"progressive\" in the name.\n */\nexport class MseMediaEngine implements NgxMediaEngine {\n readonly id = 'mse';\n readonly kind: NgxMediaKind;\n\n private readonly _state = signal<NgxMediaState>(initialMediaState());\n readonly state: Signal<NgxMediaState> = this._state.asReadonly();\n\n private readonly el: HTMLMediaElement;\n private mediaSource: MediaSource | null = null;\n private sourceBuffer: SourceBuffer | null = null;\n private reader: ReadableStreamDefaultReader<Uint8Array> | null = null;\n private objectUrl: string | null = null;\n private loadController: AbortController | null = null;\n private destroyed = false;\n private readonly cleanupFns: Array<() => void> = [];\n\n constructor(\n kind: NgxMediaKind,\n private readonly requestHandler: NgxMediaRequestHandler,\n existingElement?: HTMLMediaElement,\n ) {\n if (!hasMediaSource()) {\n throw NgxMediaError.unsupported('MediaSource Extensions are not supported in this browser.');\n }\n this.kind = kind;\n this.el = existingElement ?? (document.createElement(kind) as HTMLMediaElement);\n this.el.setAttribute('playsinline', 'true');\n this.cleanupFns.push(bindMediaElementEvents(this.el, (p) => this.patch(p), () => this._state(), (fn) => fn()));\n }\n\n get mediaElement(): HTMLMediaElement {\n return this.el;\n }\n\n async load(source: NgxMediaSource, signal?: AbortSignal): Promise<void> {\n if (this.destroyed) throw new NgxMediaError('ABORTED', 'MSE engine has been destroyed.');\n\n // A new source supersedes any previous stream. Without this, the old\n // reader can continue fetching/appending while the new MediaSource is\n // being opened, causing duplicate network traffic and leaked resources.\n this.loadController?.abort();\n this.loadController = null;\n this.reader?.cancel().catch(() => {});\n this.reader = null;\n this.releaseObjectUrl();\n\n const controller = new AbortController();\n const forwardAbort = () => controller.abort();\n if (signal?.aborted) controller.abort();\n else signal?.addEventListener('abort', forwardAbort, { once: true });\n this.loadController = controller;\n const activeSignal = controller.signal;\n\n this.patch({ playback: 'loading', currentTime: 0, duration: 0, buffered: [] });\n const mediaSource = new MediaSource();\n this.mediaSource = mediaSource;\n this.objectUrl = URL.createObjectURL(mediaSource);\n this.el.src = this.objectUrl;\n\n const metadataOrError = deferred<void>();\n const onMetadata = () => metadataOrError.resolveIfPending();\n this.el.addEventListener('loadedmetadata', onMetadata, { once: true });\n\n const abortPromise = new Promise<never>((_, reject) => {\n if (activeSignal.aborted) {\n reject(new NgxMediaError('ABORTED', 'MSE load aborted.'));\n return;\n }\n activeSignal.addEventListener('abort', () => reject(new NgxMediaError('ABORTED', 'MSE load aborted.')), { once: true });\n });\n\n try {\n await Promise.race([\n new Promise<void>((resolve, reject) => {\n mediaSource.addEventListener(\n 'sourceopen',\n async () => {\n try {\n if (this.destroyed || activeSignal.aborted || this.mediaSource !== mediaSource) {\n throw new NgxMediaError('ABORTED', 'MSE load superseded.');\n }\n const mime = source.type\n ? source.codecs\n ? `${source.type}; codecs=\"${source.codecs}\"`\n : source.type\n : 'video/mp4';\n if (!MediaSource.isTypeSupported(mime)) {\n throw NgxMediaError.unsupported(`MSE: unsupported mime/codec combination \"${mime}\".`);\n }\n this.sourceBuffer = mediaSource.addSourceBuffer(mime);\n this.streamInto(this.sourceBuffer, source, activeSignal)\n .then(() => metadataOrError.resolveIfPending())\n .catch((err) => {\n if (!this.destroyed && this.mediaSource === mediaSource) this.patch({ playback: 'error' });\n metadataOrError.rejectIfPending(err);\n });\n resolve();\n } catch (err) {\n reject(err);\n }\n },\n { once: true },\n );\n }),\n abortPromise,\n ]);\n\n await Promise.race([metadataOrError.promise, abortPromise]);\n if (this.destroyed || this.mediaSource !== mediaSource) {\n throw new NgxMediaError('ABORTED', 'MSE load was superseded.');\n }\n this.patch({ playback: 'ready' });\n } finally {\n this.el.removeEventListener('loadedmetadata', onMetadata);\n signal?.removeEventListener('abort', forwardAbort);\n if (this.loadController === controller) this.loadController = null;\n }\n }\n\n private async streamInto(buffer: SourceBuffer, source: NgxMediaSource, signal?: AbortSignal): Promise<void> {\n const response = await this.requestHandler.request(source, signal);\n if (!response.ok) {\n throw new NgxMediaError('NETWORK', `MSE: server responded ${response.status} for the media source.`);\n }\n if (!response.body) {\n throw new NgxMediaError('NETWORK', 'Response has no readable body for MSE streaming.');\n }\n\n this.reader = response.body.getReader();\n const pump = async (): Promise<void> => {\n if (this.destroyed) return;\n const { done, value } = await this.reader!.read();\n if (this.destroyed) return;\n if (done) {\n if (this.mediaSource?.readyState === 'open') this.mediaSource.endOfStream();\n return;\n }\n await this.appendWhenReady(buffer, value);\n return pump();\n };\n await pump();\n }\n\n private appendWhenReady(buffer: SourceBuffer, chunk: Uint8Array): Promise<void> {\n return new Promise((resolve, reject) => {\n if (this.destroyed) {\n resolve();\n return;\n }\n const append = () => {\n if (this.destroyed) {\n resolve();\n return;\n }\n try {\n buffer.appendBuffer(chunk as BufferSource);\n } catch (err) {\n reject(new NgxMediaError('DECODER', 'MSE: appendBuffer() rejected a chunk — the response body is not a sequence of valid media segments for this mime/codecs.', err));\n return;\n }\n const onDone = () => {\n buffer.removeEventListener('updateend', onDone);\n resolve();\n };\n buffer.addEventListener('updateend', onDone, { once: true });\n };\n if (buffer.updating) {\n buffer.addEventListener('updateend', append, { once: true });\n } else {\n append();\n }\n });\n }\n\n async play(): Promise<void> {\n if (this.destroyed) throw new NgxMediaError('ABORTED', 'MSE engine has been destroyed.');\n try {\n await this.el.play();\n } catch (err) {\n if (err instanceof DOMException && err.name === 'NotAllowedError') {\n throw NgxMediaError.autoplayBlocked(err);\n }\n throw err;\n }\n }\n pause(): void {\n this.el.pause();\n }\n seek(time: number): void {\n this.el.currentTime = time;\n }\n setVolume(volume: number): void {\n this.el.volume = volume;\n }\n setMuted(muted: boolean): void {\n this.el.muted = muted;\n }\n setPlaybackRate(rate: number): void {\n this.el.playbackRate = rate;\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n this.loadController?.abort();\n this.loadController = null;\n this.reader?.cancel().catch(() => {});\n this.reader = null;\n this.cleanupFns.forEach((fn) => fn());\n this.cleanupFns.length = 0;\n this.el.pause();\n this.releaseObjectUrl();\n this.el.removeAttribute('src');\n this.mediaSource = null;\n this.sourceBuffer = null;\n this.patch({ playback: 'destroyed' });\n }\n\n private releaseObjectUrl(): void {\n if (this.objectUrl) {\n URL.revokeObjectURL(this.objectUrl);\n this.objectUrl = null;\n }\n }\n\n private patch(partial: Partial<NgxMediaState>): void {\n this._state.update((s) => ({ ...s, ...partial }));\n }\n}\n\nfunction deferred<T>(): { promise: Promise<T>; resolveIfPending: (v: T) => void; rejectIfPending: (e: unknown) => void } {\n let settled = false;\n let resolveFn!: (v: T) => void;\n let rejectFn!: (e: unknown) => void;\n const promise = new Promise<T>((res, rej) => {\n resolveFn = res;\n rejectFn = rej;\n });\n return {\n promise,\n resolveIfPending: (v) => {\n if (!settled) {\n settled = true;\n resolveFn(v);\n }\n },\n rejectIfPending: (e) => {\n if (!settled) {\n settled = true;\n rejectFn(e);\n }\n },\n };\n}\n"],"names":[],"mappings":"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"}