@candy-kingdom/bonnie 0.26.15 → 0.27.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.
@@ -1,9 +1,284 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Injectable, EventEmitter, signal, inject, ChangeDetectorRef, effect, Output, Directive, ElementRef, Input, Component, Pipe, ViewChild, ViewContainerRef, ChangeDetectionStrategy } from '@angular/core';
3
- import { Subject, takeUntil, NEVER, fromEvent, merge, BehaviorSubject, filter } from 'rxjs';
2
+ import { Injectable, Pipe, output, input, inject, ElementRef, signal, effect, DestroyRef, Component, Directive, model, viewChild, ViewContainerRef, ChangeDetectionStrategy } from '@angular/core';
3
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
4
+ import { Subject, NEVER, takeUntil, fromEvent, merge } from 'rxjs';
4
5
  import { DomSanitizer } from '@angular/platform-browser';
5
- import * as i1 from '@angular/common';
6
- import { CommonModule, AsyncPipe, JsonPipe } from '@angular/common';
6
+ import { NgTemplateOutlet, JsonPipe } from '@angular/common';
7
+
8
+ class DeviceService {
9
+ devicePixelRatio = typeof window === "undefined" ? 1 : window.devicePixelRatio;
10
+ isSSR = typeof window === "undefined";
11
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DeviceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
12
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DeviceService });
13
+ }
14
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DeviceService, decorators: [{
15
+ type: Injectable
16
+ }] });
17
+
18
+ class DeviceServiceBase {
19
+ }
20
+
21
+ function emptyBone() {
22
+ return {
23
+ style: "",
24
+ mediaQuery: "",
25
+ enabled: true,
26
+ type: "",
27
+ };
28
+ }
29
+
30
+ function emptyImage() {
31
+ return {
32
+ $type: "image", // todo: remove
33
+ type: "image",
34
+ sources: [],
35
+ };
36
+ }
37
+
38
+ function emptyLocalizedString() {
39
+ return {};
40
+ }
41
+
42
+ function emptyVideo() {
43
+ return {
44
+ $type: "video", // todo: remove
45
+ type: "video",
46
+ sources: [],
47
+ };
48
+ }
49
+
50
+ class EncodeURIComponentPipe {
51
+ transform(value) {
52
+ return encodeURIComponent(value);
53
+ }
54
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EncodeURIComponentPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
55
+ static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: EncodeURIComponentPipe, isStandalone: true, name: "encodeURIComponent" });
56
+ }
57
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EncodeURIComponentPipe, decorators: [{
58
+ type: Pipe,
59
+ args: [{ name: "encodeURIComponent", pure: true }]
60
+ }] });
61
+
62
+ class IntersectionComponent {
63
+ intersected = output();
64
+ session = input(...(ngDevMode ? [undefined, { debugName: "session" }] : []));
65
+ _hostRef = inject(ElementRef);
66
+ _intersectionObserver;
67
+ _isIntersected = signal(false, ...(ngDevMode ? [{ debugName: "_isIntersected" }] : []));
68
+ isIntersected = this._isIntersected.asReadonly();
69
+ _session; // todo: remove
70
+ constructor() {
71
+ if (typeof window === "undefined" || typeof IntersectionObserver === "undefined") {
72
+ return;
73
+ }
74
+ this._intersectionObserver = new IntersectionObserver(this.onIntersection.bind(this));
75
+ effect(() => {
76
+ if (this._isIntersected()) {
77
+ this.intersected.emit();
78
+ }
79
+ });
80
+ effect(() => {
81
+ const newSession = this.session();
82
+ if (this._session === newSession)
83
+ return;
84
+ console.log("reset intersection Observer");
85
+ this._session = newSession;
86
+ this.reset();
87
+ });
88
+ inject(DestroyRef).onDestroy(() => this._intersectionObserver?.disconnect());
89
+ }
90
+ reset() {
91
+ if (this._intersectionObserver === undefined || this._intersectionObserver === null)
92
+ return;
93
+ this._intersectionObserver.unobserve(this._hostRef.nativeElement);
94
+ this._isIntersected.set(false);
95
+ this._intersectionObserver.observe(this._hostRef.nativeElement);
96
+ }
97
+ onIntersection(entries, observer) {
98
+ if (entries.length > 1) {
99
+ console.warn("multi entries!");
100
+ }
101
+ const isIntersecting = entries[0].isIntersecting;
102
+ this._isIntersected.set(isIntersecting);
103
+ console.log(`intersected ${isIntersecting}`, this._hostRef.nativeElement);
104
+ // only once will recieve intersection
105
+ if (isIntersecting) {
106
+ observer.unobserve(this._hostRef.nativeElement);
107
+ }
108
+ }
109
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IntersectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
110
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "21.0.6", type: IntersectionComponent, isStandalone: true, selector: "bon-intersection", inputs: { session: { classPropertyName: "session", publicName: "session", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { intersected: "intersected" }, ngImport: i0, template: "<ng-content></ng-content>", isInline: true, styles: [":host{display:block}\n"] });
111
+ }
112
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IntersectionComponent, decorators: [{
113
+ type: Component,
114
+ args: [{ selector: "bon-intersection", template: "<ng-content></ng-content>", styles: [":host{display:block}\n"] }]
115
+ }], ctorParameters: () => [], propDecorators: { intersected: [{ type: i0.Output, args: ["intersected"] }], session: [{ type: i0.Input, args: [{ isSignal: true, alias: "session", required: false }] }] } });
116
+
117
+ var MediaObjectFit;
118
+ (function (MediaObjectFit) {
119
+ MediaObjectFit["Original"] = "Original";
120
+ MediaObjectFit["Cover"] = "Cover";
121
+ MediaObjectFit["Contain"] = "Contain";
122
+ })(MediaObjectFit || (MediaObjectFit = {}));
123
+
124
+ var MediaStatus;
125
+ (function (MediaStatus) {
126
+ MediaStatus["NotSet"] = "NotSet";
127
+ MediaStatus["NotLoaded"] = "NotLoaded";
128
+ MediaStatus["Loading"] = "Loading";
129
+ MediaStatus["Loaded"] = "Loaded";
130
+ })(MediaStatus || (MediaStatus = {}));
131
+
132
+ // https://stackoverflow.com/questions/42136098/array-groupby-in-typescript
133
+ const groupBy = (arr, key) => arr.reduce((groups, item) => {
134
+ (groups[key(item)] ||= []).push(item);
135
+ return groups;
136
+ }, {});
137
+ function distinct(value, index, array) {
138
+ return array.indexOf(value) === index;
139
+ }
140
+ function ascending(a, b) {
141
+ return a - b;
142
+ }
143
+ function ascendingT(sel) {
144
+ return (a, b) => ascending(sel(a), sel(b));
145
+ }
146
+ function descending(a, b) {
147
+ return b - a;
148
+ }
149
+ function descendingT(sel) {
150
+ return (a, b) => descending(sel(a), sel(b));
151
+ }
152
+ function generateSizesString(sizes) {
153
+ const sizesString = sizes
154
+ .sort((x) => x.width)
155
+ .map((x) => `${x.mediaQuery} ${x.width}${x.unit.toLowerCase()}`.trim())
156
+ .join(",");
157
+ return sizesString;
158
+ }
159
+ function matchesMediaQuery(mediaQuery) {
160
+ const isEmptyQuery = mediaQuery === null || mediaQuery === undefined || mediaQuery.trim().length === 0;
161
+ // work for SSR and browser
162
+ if (isEmptyQuery)
163
+ return true;
164
+ // other queries disallowed in SSR
165
+ if (typeof window === "undefined")
166
+ return false;
167
+ const mediaQueryList = window.matchMedia(mediaQuery);
168
+ return mediaQueryList.matches;
169
+ }
170
+ function isLocalUrlString(url) {
171
+ if (url === undefined || url === null || url.trim().length === 0)
172
+ return true;
173
+ if (url.startsWith("//"))
174
+ return false;
175
+ if (url.startsWith("./") || url.startsWith("/"))
176
+ return true;
177
+ return false;
178
+ }
179
+
180
+ class SrcBaseDirective {
181
+ ratioChange = output();
182
+ _ratio = signal(0, ...(ngDevMode ? [{ debugName: "_ratio" }] : []));
183
+ ratio = this._ratio.asReadonly();
184
+ _queryChangeClearSubject = new Subject();
185
+ _destroyRef = inject(DestroyRef);
186
+ constructor() {
187
+ effect(() => {
188
+ const ratio = this._ratio();
189
+ this.ratioChange.emit(ratio);
190
+ });
191
+ effect(() => {
192
+ const val = this.data();
193
+ this.onSrcChange(val);
194
+ });
195
+ }
196
+ onSrcChange(val) {
197
+ if (val !== undefined && val !== null && val.sources.length === 0) {
198
+ console.warn(`image should have sources!`);
199
+ this.data.set(undefined);
200
+ return;
201
+ }
202
+ // clear mediaQuery subscriptions
203
+ this._queryChangeClearSubject.next();
204
+ // ratio
205
+ this._ratio.set(0);
206
+ if (val === undefined || val.sources.length === 0) {
207
+ return;
208
+ }
209
+ const allRatios = val.sources
210
+ .flatMap((x) => x.srcSet)
211
+ .map((x) => x.meta.ratio)
212
+ .filter(distinct);
213
+ if (allRatios.length === 1) {
214
+ // same ratio for all
215
+ this._ratio.set(allRatios[0]);
216
+ return;
217
+ }
218
+ // todo: check if this needed to be unsubscribed
219
+ this.watchMediaQueries().subscribe(() => {
220
+ this.calcRatio();
221
+ console.log("watchMediaQueries calcRatio");
222
+ });
223
+ this.calcRatio();
224
+ }
225
+ calcRatio() {
226
+ const data = this.data();
227
+ if (data === undefined || data === null || data.sources.length === 0)
228
+ return;
229
+ for (let i = 0; i < data.sources.length; i++) {
230
+ const source = data.sources[i];
231
+ const srcRatios = source.srcSet
232
+ .sort(descendingT((x) => x.meta.width))
233
+ .map((x) => x.meta.ratio)
234
+ .filter(distinct);
235
+ if (srcRatios.length === 0) {
236
+ return;
237
+ }
238
+ if (srcRatios.length > 1) {
239
+ console.warn(`each source should have srcSet with same ratio. founded: ${srcRatios.join(", ")}`);
240
+ }
241
+ const ratio = srcRatios[0]; // most accurate ratio in biggest image
242
+ if (source.mediaQuery.length === 0) {
243
+ this._ratio.set(ratio);
244
+ return;
245
+ }
246
+ if (typeof window === "undefined" || typeof window.matchMedia === "undefined")
247
+ return;
248
+ const mediaQueryList = window.matchMedia(source.mediaQuery);
249
+ if (mediaQueryList.matches) {
250
+ this._ratio.set(ratio);
251
+ return;
252
+ }
253
+ }
254
+ }
255
+ watchMediaQueries() {
256
+ console.log("watchMediaQueries");
257
+ const src = this.data();
258
+ if (src === undefined ||
259
+ src === null ||
260
+ typeof window === "undefined" ||
261
+ typeof window.matchMedia === "undefined")
262
+ return NEVER.pipe(takeUntilDestroyed(this._destroyRef), takeUntil(this._queryChangeClearSubject));
263
+ const mediaQueries = src.sources
264
+ .map((x) => x.mediaQuery)
265
+ .filter(distinct)
266
+ .filter((x) => x.length > 0);
267
+ console.log("watchMediaQueries mediaQueries", mediaQueries);
268
+ const queryObservables = mediaQueries.map((media) => {
269
+ const queryList = window.matchMedia(media);
270
+ const observable = fromEvent(queryList, "change").pipe(takeUntilDestroyed(this._destroyRef), takeUntil(this._queryChangeClearSubject));
271
+ return observable;
272
+ });
273
+ const combinedObservable = merge(...queryObservables);
274
+ return combinedObservable;
275
+ }
276
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SrcBaseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
277
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: SrcBaseDirective, isStandalone: true, outputs: { ratioChange: "ratioChange" }, ngImport: i0 });
278
+ }
279
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SrcBaseDirective, decorators: [{
280
+ type: Directive
281
+ }], ctorParameters: () => [], propDecorators: { ratioChange: [{ type: i0.Output, args: ["ratioChange"] }] } });
7
282
 
8
283
  /**
9
284
  * This is a TypeGen auto-generated file.
@@ -178,336 +453,6 @@ var SizesWidthUnit;
178
453
  * Any changes made to this file can be lost when this file is regenerated.
179
454
  */
180
455
 
181
- // https://stackoverflow.com/questions/42136098/array-groupby-in-typescript
182
- const groupBy = (arr, key) => arr.reduce((groups, item) => {
183
- (groups[key(item)] ||= []).push(item);
184
- return groups;
185
- }, {});
186
- function distinct(value, index, array) {
187
- return array.indexOf(value) === index;
188
- }
189
- function ascending(a, b) {
190
- return a - b;
191
- }
192
- function ascendingT(sel) {
193
- return function (a, b) { return ascending(sel(a), sel(b)); };
194
- }
195
- function descending(a, b) {
196
- return b - a;
197
- }
198
- function descendingT(sel) {
199
- return function (a, b) { return descending(sel(a), sel(b)); };
200
- }
201
- function generateSizesString(sizes) {
202
- const sizesString = sizes
203
- .sort(x => x.width)
204
- .map(x => `${x.mediaQuery} ${x.width}${x.unit.toLowerCase()}`.trim())
205
- .join(',');
206
- return sizesString;
207
- }
208
- function matchesMediaQuery(mediaQuery) {
209
- const isEmptyQuery = mediaQuery === null || mediaQuery === undefined || mediaQuery.trim().length === 0;
210
- // work for SSR and browser
211
- if (isEmptyQuery)
212
- return true;
213
- // other queries disallowed in SSR
214
- if (typeof window === 'undefined')
215
- return false;
216
- const mediaQueryList = window.matchMedia(mediaQuery);
217
- return mediaQueryList.matches;
218
- }
219
- function isLocalUrlString(url) {
220
- if (url === undefined || url === null || url.trim().length === 0)
221
- return true;
222
- if (url.startsWith('//'))
223
- return false;
224
- if (url.startsWith('./') || url.startsWith('/'))
225
- return true;
226
- return false;
227
- }
228
-
229
- class UnsubscriberService {
230
- _destroy$ = new Subject();
231
- takeUntilDestroy = (origin) => origin.pipe(takeUntil(this._destroy$));
232
- ngOnDestroy() {
233
- this._destroy$.next();
234
- this._destroy$.complete();
235
- }
236
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UnsubscriberService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
237
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UnsubscriberService });
238
- }
239
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UnsubscriberService, decorators: [{
240
- type: Injectable
241
- }] });
242
-
243
- class SrcBaseDirective {
244
- ratioChange = new EventEmitter();
245
- srcChange = new EventEmitter();
246
- _ratio = signal(0, ...(ngDevMode ? [{ debugName: "_ratio" }] : []));
247
- ratio = this._ratio.asReadonly();
248
- _queryChangeClearSubject = new Subject();
249
- _data;
250
- _u = inject(UnsubscriberService);
251
- cd = inject(ChangeDetectorRef);
252
- _effectCleanup;
253
- constructor() {
254
- console.log('SrcBaseDirective ctor');
255
- this.cd.detach();
256
- // Watch for ratio changes and emit
257
- this._effectCleanup = effect(() => {
258
- const ratio = this._ratio();
259
- this.ratioChange.next(ratio);
260
- this.cd.detectChanges(); // todo: verify, do i need it here
261
- }, ...(ngDevMode ? [{ debugName: "_effectCleanup" }] : []));
262
- }
263
- ngOnInit() {
264
- console.log('SrcBaseDirective ngOnInit');
265
- this.cd.detectChanges();
266
- }
267
- get data() {
268
- return this._data;
269
- }
270
- set data(val) {
271
- console.log('set data', val);
272
- if (val !== undefined && val !== null && val.sources.length === 0) {
273
- console.warn(`image should have sources!`);
274
- val = undefined;
275
- }
276
- this._data = val;
277
- console.log('calling src change ', this._data);
278
- // clear mediaQuery subscriptions
279
- this._queryChangeClearSubject.next();
280
- // ratio
281
- this._ratio.set(0);
282
- this.srcChange.next(this._data);
283
- if (this._data === undefined || this._data.sources.length === 0) {
284
- return;
285
- }
286
- const allRatios = this._data.sources
287
- .flatMap((x) => x.srcSet)
288
- .map((x) => x.meta.ratio)
289
- .filter(distinct);
290
- if (allRatios.length === 1) {
291
- // same ratio for all
292
- this._ratio.set(allRatios[0]);
293
- return;
294
- }
295
- this.watchMediaQueries().subscribe(() => {
296
- this.calcRatio();
297
- console.log('watchMediaQueries calcRatio');
298
- });
299
- this.calcRatio();
300
- }
301
- calcRatio() {
302
- if (this._data === undefined ||
303
- this._data === null ||
304
- this._data.sources.length === 0)
305
- return;
306
- for (let i = 0; i < this._data.sources.length; i++) {
307
- const source = this._data.sources[i];
308
- const srcRatios = source.srcSet
309
- .sort(descendingT((x) => x.meta.width))
310
- .map((x) => x.meta.ratio)
311
- .filter(distinct);
312
- if (srcRatios.length === 0) {
313
- // console.warn(`each source should have srcSet with same ratio. founded: ${srcRatios.join(', ')}`);
314
- return;
315
- }
316
- if (srcRatios.length > 1) {
317
- console.warn(`each source should have srcSet with same ratio. founded: ${srcRatios.join(', ')}`);
318
- }
319
- const ratio = srcRatios[0]; // most accurate ratio in biggest image
320
- if (source.mediaQuery.length === 0) {
321
- this._ratio.set(ratio);
322
- return;
323
- }
324
- if (typeof window === 'undefined' ||
325
- typeof window.matchMedia === 'undefined')
326
- return;
327
- const mediaQueryList = window.matchMedia(source.mediaQuery);
328
- if (mediaQueryList.matches) {
329
- this._ratio.set(ratio);
330
- return;
331
- }
332
- }
333
- }
334
- watchMediaQueries() {
335
- console.log('watchMediaQueries');
336
- if (this._data === undefined ||
337
- this._data === null ||
338
- typeof window === 'undefined' ||
339
- typeof window.matchMedia === 'undefined')
340
- return NEVER.pipe(this._u.takeUntilDestroy, takeUntil(this._queryChangeClearSubject));
341
- const mediaQueries = this._data.sources
342
- .map((x) => x.mediaQuery)
343
- .filter(distinct)
344
- .filter((x) => x.length > 0);
345
- console.log('watchMediaQueries mediaQueries', mediaQueries);
346
- const queryObservables = mediaQueries.map((media) => {
347
- const queryList = window.matchMedia(media);
348
- const observable = fromEvent(queryList, 'change').pipe(this._u.takeUntilDestroy, takeUntil(this._queryChangeClearSubject));
349
- return observable;
350
- });
351
- const combinedObservable = merge(...queryObservables);
352
- return combinedObservable;
353
- }
354
- ngOnDestroy() {
355
- this._effectCleanup?.destroy();
356
- }
357
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SrcBaseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
358
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: SrcBaseDirective, isStandalone: true, selector: "[bonSrcBase]", outputs: { ratioChange: "ratioChange", srcChange: "srcChange" }, providers: [UnsubscriberService], ngImport: i0 });
359
- }
360
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SrcBaseDirective, decorators: [{
361
- type: Directive,
362
- args: [{
363
- standalone: true,
364
- selector: '[bonSrcBase]',
365
- providers: [UnsubscriberService],
366
- }]
367
- }], ctorParameters: () => [], propDecorators: { ratioChange: [{
368
- type: Output
369
- }], srcChange: [{
370
- type: Output
371
- }] } });
372
-
373
- var MediaStatus;
374
- (function (MediaStatus) {
375
- MediaStatus["NotSet"] = "NotSet";
376
- MediaStatus["NotLoaded"] = "NotLoaded";
377
- MediaStatus["Loading"] = "Loading";
378
- MediaStatus["Loaded"] = "Loaded";
379
- })(MediaStatus || (MediaStatus = {}));
380
-
381
- var MediaObjectFit;
382
- (function (MediaObjectFit) {
383
- MediaObjectFit["Original"] = "Original";
384
- MediaObjectFit["Cover"] = "Cover";
385
- MediaObjectFit["Contain"] = "Contain";
386
- })(MediaObjectFit || (MediaObjectFit = {}));
387
-
388
- class DeviceService {
389
- devicePixelRatio = typeof window === 'undefined' ? 1 : window.devicePixelRatio;
390
- isSSR = typeof window === 'undefined';
391
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DeviceService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
392
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DeviceService });
393
- }
394
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: DeviceService, decorators: [{
395
- type: Injectable
396
- }] });
397
-
398
- class DeviceServiceBase {
399
- }
400
-
401
- class IntersectionComponent {
402
- intersected = new EventEmitter();
403
- _hostRef = inject(ElementRef);
404
- _u = inject(UnsubscriberService);
405
- _cd = inject(ChangeDetectorRef);
406
- intersectionObserver;
407
- _intersected = signal(false, ...(ngDevMode ? [{ debugName: "_intersected" }] : []));
408
- intersectedOnce = this._intersected.asReadonly();
409
- _session;
410
- _effectCleanup;
411
- constructor() {
412
- this._cd.detach();
413
- // no template with variables, so we don't need to call changeDetection
414
- if (typeof window === 'undefined' || typeof IntersectionObserver === 'undefined') {
415
- // call intersection without any
416
- return;
417
- }
418
- this.intersectionObserver = new IntersectionObserver(this.onIntersection.bind(this));
419
- // Watch for intersection changes and emit when it becomes true
420
- this._effectCleanup = effect(() => {
421
- if (this._intersected()) {
422
- this.intersected.next();
423
- }
424
- }, ...(ngDevMode ? [{ debugName: "_effectCleanup" }] : []));
425
- }
426
- ngOnInit() {
427
- }
428
- set session(newSession) {
429
- if (this._session === newSession)
430
- return;
431
- console.log('reset intersection Observer');
432
- this._session = newSession;
433
- this.reset();
434
- }
435
- reset() {
436
- if (this.intersectionObserver === undefined || this.intersectionObserver === null)
437
- return;
438
- this.intersectionObserver.unobserve(this._hostRef.nativeElement);
439
- this._intersected.set(false);
440
- this.intersectionObserver.observe(this._hostRef.nativeElement);
441
- }
442
- onIntersection(entries, observer) {
443
- if (entries.length > 1) {
444
- console.warn('multi entries!');
445
- }
446
- const isIntersecting = entries[0].isIntersecting;
447
- this._intersected.set(isIntersecting);
448
- console.log(`intersected ${isIntersecting}`, this._hostRef.nativeElement);
449
- // only once will recieve intersection
450
- if (isIntersecting) {
451
- observer.unobserve(this._hostRef.nativeElement);
452
- }
453
- }
454
- ngOnDestroy() {
455
- this._effectCleanup?.destroy();
456
- this.intersectionObserver?.disconnect();
457
- }
458
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IntersectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
459
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: IntersectionComponent, isStandalone: true, selector: "bon-intersection", inputs: { session: "session" }, outputs: { intersected: "intersected" }, providers: [UnsubscriberService], ngImport: i0, template: '<ng-content></ng-content>', isInline: true, styles: [":host{display:block}\n"] });
460
- }
461
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IntersectionComponent, decorators: [{
462
- type: Component,
463
- args: [{ selector: 'bon-intersection', standalone: true, template: '<ng-content></ng-content>', providers: [UnsubscriberService], styles: [":host{display:block}\n"] }]
464
- }], ctorParameters: () => [], propDecorators: { intersected: [{
465
- type: Output
466
- }], session: [{
467
- type: Input
468
- }] } });
469
-
470
- class EncodeURIComponentPipe {
471
- transform(value) {
472
- return encodeURIComponent(value);
473
- }
474
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EncodeURIComponentPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
475
- static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: EncodeURIComponentPipe, isStandalone: true, name: "encodeURIComponent" });
476
- }
477
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: EncodeURIComponentPipe, decorators: [{
478
- type: Pipe,
479
- args: [{ name: 'encodeURIComponent', standalone: true, pure: true }]
480
- }] });
481
-
482
- function emptyImage() {
483
- return {
484
- $type: 'image', // todo: remove
485
- type: 'image',
486
- sources: [],
487
- };
488
- }
489
-
490
- function emptyVideo() {
491
- return {
492
- $type: 'video', // todo: remove
493
- type: 'video',
494
- sources: [],
495
- };
496
- }
497
-
498
- function emptyBone() {
499
- return {
500
- style: '',
501
- mediaQuery: '',
502
- enabled: true,
503
- type: ''
504
- };
505
- }
506
-
507
- function emptyLocalizedString() {
508
- return {};
509
- }
510
-
511
456
  class LocalizeServiceBase {
512
457
  getLocalized(value, defaultValue, locale) {
513
458
  if (value === undefined)
@@ -517,9 +462,8 @@ class LocalizeServiceBase {
517
462
  return obj;
518
463
  }
519
464
  getLocalizedText(value, locale) {
520
- return this.getLocalized(value, '', locale);
465
+ return this.getLocalized(value, "", locale);
521
466
  }
522
- ;
523
467
  isLocalUrl(value, locale) {
524
468
  const url = this.getLocalizedText(value, locale);
525
469
  return isLocalUrlString(url);
@@ -527,39 +471,39 @@ class LocalizeServiceBase {
527
471
  }
528
472
 
529
473
  class LocalizePipe {
530
- localizeService = inject(LocalizeServiceBase);
474
+ _localizeService = inject(LocalizeServiceBase);
531
475
  transform(value, locale) {
532
476
  if (value === undefined || value === null)
533
- return '';
534
- return this.localizeService.getLocalizedText(value, locale);
477
+ return "";
478
+ return this._localizeService.getLocalizedText(value, locale);
535
479
  }
536
480
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
537
481
  static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: LocalizePipe, isStandalone: true, name: "localize", pure: false });
538
482
  }
539
483
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizePipe, decorators: [{
540
484
  type: Pipe,
541
- args: [{ name: 'localize', standalone: true, pure: false }]
485
+ args: [{ name: "localize", pure: false }]
542
486
  }] });
543
487
  class LocalizeObjectPipe {
544
- localizeService = inject(LocalizeServiceBase);
488
+ _localizeService = inject(LocalizeServiceBase);
545
489
  transform(object, locale) {
546
490
  if (object === undefined || object === null)
547
491
  return undefined;
548
- return this.localizeService.getLocalized(object, undefined, locale);
492
+ return this._localizeService.getLocalized(object, undefined, locale);
549
493
  }
550
494
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizeObjectPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
551
495
  static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: LocalizeObjectPipe, isStandalone: true, name: "localizeObject", pure: false });
552
496
  }
553
497
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizeObjectPipe, decorators: [{
554
498
  type: Pipe,
555
- args: [{ name: 'localizeObject', standalone: true, pure: false }]
499
+ args: [{ name: "localizeObject", pure: false }]
556
500
  }] });
557
501
  class LocalizationIsNotEmptyPipe {
558
- localizeService = inject(LocalizeServiceBase);
502
+ _localizeService = inject(LocalizeServiceBase);
559
503
  transform(value, locale) {
560
504
  if (value === undefined || value === null)
561
505
  return false;
562
- const text = this.localizeService.getLocalizedText(value, locale);
506
+ const text = this._localizeService.getLocalizedText(value, locale);
563
507
  const isNotEmpty = text.trim().length > 0;
564
508
  return isNotEmpty;
565
509
  }
@@ -568,14 +512,14 @@ class LocalizationIsNotEmptyPipe {
568
512
  }
569
513
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizationIsNotEmptyPipe, decorators: [{
570
514
  type: Pipe,
571
- args: [{ name: 'localizationIsNotEmpty', standalone: true, pure: false }]
515
+ args: [{ name: "localizationIsNotEmpty", pure: false }]
572
516
  }] });
573
517
  class LocalizationIsEmptyPipe {
574
- localizeService = inject(LocalizeServiceBase);
518
+ _localizeService = inject(LocalizeServiceBase);
575
519
  transform(value, locale) {
576
520
  if (value === undefined || value === null)
577
521
  return true;
578
- const text = this.localizeService.getLocalizedText(value, locale);
522
+ const text = this._localizeService.getLocalizedText(value, locale);
579
523
  const isEmpty = text.trim().length === 0;
580
524
  return isEmpty;
581
525
  }
@@ -584,16 +528,16 @@ class LocalizationIsEmptyPipe {
584
528
  }
585
529
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizationIsEmptyPipe, decorators: [{
586
530
  type: Pipe,
587
- args: [{ name: 'localizationIsEmpty', standalone: true, pure: false }]
531
+ args: [{ name: "localizationIsEmpty", pure: false }]
588
532
  }] });
589
533
  class LocalizeUrlPipe {
590
- localizeService = inject(LocalizeServiceBase);
591
- domSanitizer = inject(DomSanitizer);
534
+ _localizeService = inject(LocalizeServiceBase);
535
+ _domSanitizer = inject(DomSanitizer);
592
536
  transform(value, locale) {
593
537
  if (value === undefined || value === null)
594
- return '';
595
- const urlString = this.localizeService.getLocalizedText(value, locale);
596
- const safeUrl = this.domSanitizer.bypassSecurityTrustResourceUrl(urlString);
538
+ return "";
539
+ const urlString = this._localizeService.getLocalizedText(value, locale);
540
+ const safeUrl = this._domSanitizer.bypassSecurityTrustResourceUrl(urlString);
597
541
  return safeUrl;
598
542
  }
599
543
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizeUrlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
@@ -601,14 +545,14 @@ class LocalizeUrlPipe {
601
545
  }
602
546
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizeUrlPipe, decorators: [{
603
547
  type: Pipe,
604
- args: [{ name: 'localizeUrl', standalone: true, pure: false }]
548
+ args: [{ name: "localizeUrl", pure: false }]
605
549
  }] });
606
550
  class IsLocalUrlPipe {
607
- localizeService = inject(LocalizeServiceBase);
551
+ _localizeService = inject(LocalizeServiceBase);
608
552
  transform(value, locale) {
609
553
  if (value === undefined || value === null)
610
554
  return false;
611
- const isLocal = this.localizeService.isLocalUrl(value, locale);
555
+ const isLocal = this._localizeService.isLocalUrl(value, locale);
612
556
  return isLocal;
613
557
  }
614
558
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IsLocalUrlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
@@ -616,14 +560,14 @@ class IsLocalUrlPipe {
616
560
  }
617
561
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IsLocalUrlPipe, decorators: [{
618
562
  type: Pipe,
619
- args: [{ name: 'isLocalUrl', standalone: true, pure: false }]
563
+ args: [{ name: "isLocalUrl", pure: false }]
620
564
  }] });
621
565
  class IsNotLocalUrlPipe {
622
- localizeService = inject(LocalizeServiceBase);
566
+ _localizeService = inject(LocalizeServiceBase);
623
567
  transform(value, locale) {
624
568
  if (value === undefined || value === null)
625
569
  return false;
626
- const isLocal = this.localizeService.isLocalUrl(value, locale);
570
+ const isLocal = this._localizeService.isLocalUrl(value, locale);
627
571
  return !isLocal;
628
572
  }
629
573
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IsNotLocalUrlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
@@ -631,233 +575,165 @@ class IsNotLocalUrlPipe {
631
575
  }
632
576
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IsNotLocalUrlPipe, decorators: [{
633
577
  type: Pipe,
634
- args: [{ name: 'isNotLocalUrl', standalone: true, pure: false }]
578
+ args: [{ name: "isNotLocalUrl", pure: false }]
635
579
  }] });
636
580
 
581
+ function getDefaultSrc(image) {
582
+ if (image === undefined || image === null)
583
+ return undefined;
584
+ const files = image.sources.flatMap((x) => x.srcSet).sort(descendingT((x) => x.meta.width));
585
+ const prefferedFiles = files.filter((x) => x.mimeType === "image/jpeg" || x.mimeType === "image/png" || x.mimeType === "image/gif");
586
+ if (prefferedFiles.length > 0)
587
+ return prefferedFiles[0];
588
+ if (files.length > 0)
589
+ return files[0];
590
+ return undefined;
591
+ }
592
+
637
593
  class ImageSrcDirective extends SrcBaseDirective {
638
- set imgsrc(value) {
639
- console.log('set imgsrc', value);
640
- this.data = value;
641
- }
594
+ data = model(undefined, { ...(ngDevMode ? { debugName: "data" } : {}), alias: "imgsrc" });
642
595
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ImageSrcDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
643
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: ImageSrcDirective, isStandalone: true, selector: "[imgsrc]", inputs: { imgsrc: "imgsrc" }, usesInheritance: true, ngImport: i0 });
596
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: ImageSrcDirective, isStandalone: true, selector: "[imgsrc]", inputs: { data: { classPropertyName: "data", publicName: "imgsrc", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { data: "imgsrcChange" }, usesInheritance: true, ngImport: i0 });
644
597
  }
645
598
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ImageSrcDirective, decorators: [{
646
599
  type: Directive,
647
600
  args: [{
648
- standalone: true,
649
- selector: '[imgsrc]',
601
+ selector: "[imgsrc]",
650
602
  }]
651
- }], propDecorators: { imgsrc: [{
652
- type: Input
653
- }] } });
603
+ }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "imgsrc", required: false }] }, { type: i0.Output, args: ["imgsrcChange"] }] } });
654
604
 
655
605
  function toHtmlPictureSources(imageSource) {
656
606
  const sizes = generateSizesString(imageSource.sizes);
657
- const groupedByMime = groupBy(imageSource.srcSet, x => x.mimeType);
607
+ const groupedByMime = groupBy(imageSource.srcSet, (x) => x.mimeType);
658
608
  const simpleSources = [];
659
609
  for (const mime in groupedByMime) {
660
- const fileSrcs = groupedByMime[mime].sort(ascendingT(x => x.meta.width));
661
- const srcSet = fileSrcs
662
- .map(x => `${x.url} ${x.meta.width}w`)
663
- .join(',');
610
+ const fileSrcs = groupedByMime[mime].sort(ascendingT((x) => x.meta.width));
611
+ const srcSet = fileSrcs.map((x) => `${x.url} ${x.meta.width}w`).join(",");
664
612
  const source = { mime, sizes, srcSet, media: imageSource.mediaQuery };
665
613
  simpleSources.push(source);
666
614
  }
667
615
  return simpleSources;
668
616
  }
669
617
 
670
- function getDefaultSrc(image) {
671
- if (image === undefined || image === null)
672
- return undefined;
673
- const files = image.sources
674
- .flatMap(x => x.srcSet)
675
- .sort(descendingT(x => x.meta.width));
676
- const prefferedFiles = files.filter(x => x.mimeType === 'image/jpeg'
677
- || x.mimeType === 'image/png'
678
- || x.mimeType === 'image/gif');
679
- if (prefferedFiles.length > 0)
680
- return prefferedFiles[0];
681
- if (files.length > 0)
682
- return files[0];
683
- return undefined;
684
- }
685
-
686
618
  class MarcyImageComponent {
687
619
  MediaStatus = MediaStatus;
688
620
  MarcyObjectFit = MediaObjectFit;
689
- isLoaded = new EventEmitter();
690
- sources = [];
691
- $status = new BehaviorSubject(MediaStatus.NotSet);
692
- defaultSrc = '';
693
- _objectFit = MediaObjectFit.Original;
694
621
  src;
622
+ isLoaded = output();
623
+ objectFit = input(MediaObjectFit.Original, ...(ngDevMode ? [{ debugName: "objectFit" }] : []));
624
+ sources = signal([], ...(ngDevMode ? [{ debugName: "sources" }] : []));
625
+ status = signal(MediaStatus.NotSet, ...(ngDevMode ? [{ debugName: "status" }] : []));
626
+ defaultSrc = signal("", ...(ngDevMode ? [{ debugName: "defaultSrc" }] : []));
695
627
  device = inject(DeviceServiceBase);
696
- cd = inject(ChangeDetectorRef);
697
- _u = inject(UnsubscriberService);
698
- _srcDir = inject(ImageSrcDirective, { optional: true });
699
628
  constructor() {
700
- console.log('MarcyImageComponent ctor');
701
- if (this._srcDir === undefined || this._srcDir === null)
629
+ const src = inject(ImageSrcDirective, { optional: true });
630
+ if (src === undefined || src === null)
702
631
  throw new Error(`${MarcyImageComponent.name} should have [imgsrc] directive as source object`);
703
- this.src = this._srcDir;
704
- // bind src changes
705
- this.src.srcChange
706
- .pipe(this._u.takeUntilDestroy)
707
- .subscribe(this.onSrcChange.bind(this));
708
- this.cd.detach();
709
- }
710
- ngOnInit() {
711
- // bind loaded event
712
- this.$status
713
- .pipe(this._u.takeUntilDestroy, filter(status => status === MediaStatus.Loaded))
714
- .subscribe(x => this.isLoaded.next());
715
- this.cd.detectChanges();
632
+ this.src = src;
633
+ effect(() => {
634
+ this.onSrcChange(this.src.data());
635
+ });
636
+ effect(() => {
637
+ if (this.status() === MediaStatus.Loaded) {
638
+ this.isLoaded.emit();
639
+ }
640
+ });
716
641
  }
717
642
  onSrcChange(val) {
718
- console.log('MarcyImageComponent onSrcChange', val);
719
- this.defaultSrc = getDefaultSrc(val)?.url ?? '';
720
- this.sources.splice(0, this.sources.length);
643
+ this.defaultSrc.set(getDefaultSrc(val)?.url ?? "");
721
644
  if (val === undefined || val === null || val.sources.length === 0) {
722
- this.$status.next(MediaStatus.NotSet);
723
- this.cd.detectChanges();
645
+ this.sources.set([]);
646
+ this.status.set(MediaStatus.NotSet);
724
647
  return;
725
648
  }
726
649
  const newSources = val.sources.flatMap(toHtmlPictureSources);
727
- console.log('MarcyImageComponent newSources', newSources);
728
- this.sources.push(...newSources);
729
- this.$status.next(MediaStatus.NotLoaded);
730
- this.cd.detectChanges();
731
- }
732
- set objectFit(val) {
733
- this._objectFit = val ?? MediaObjectFit.Original;
734
- this.cd.detectChanges();
735
- }
736
- get objectFit() {
737
- return this._objectFit;
650
+ this.sources.set(newSources);
651
+ this.status.set(MediaStatus.NotLoaded);
738
652
  }
739
653
  onLoad() {
740
- this.$status.next(MediaStatus.Loaded);
654
+ this.status.set(MediaStatus.Loaded);
741
655
  }
742
656
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MarcyImageComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
743
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: MarcyImageComponent, isStandalone: true, selector: "bon-image", inputs: { objectFit: "objectFit" }, outputs: { isLoaded: "isLoaded" }, providers: [UnsubscriberService], ngImport: i0, template: "<div *ngIf=\"sources.length > 0\"\n [class.knownRatio]=\"src.ratio() > 0 && objectFit === MarcyObjectFit.Original\"\n [class.cover]=\"objectFit === MarcyObjectFit.Cover\"\n [class.contain]=\"objectFit === MarcyObjectFit.Contain\"\n [class.loaded]=\"($status | async) === MediaStatus.Loaded\"\n class=\"picture-container\">\n\n <ng-template #pictureTemplate>\n <picture>\n <source *ngFor=\"let source of sources\"\n [srcset]=\"source.srcSet\"\n [attr.media]=\"source.media.length > 0 ? source.media : undefined\"\n [attr.type]=\"source.mime.length > 0 ? source.mime : undefined\"\n [attr.sizes]=\"source.sizes.length > 0 ? source.sizes : undefined\" />\n\n <img [src]=\"defaultSrc\" (load)=\"onLoad()\" />\n </picture>\n </ng-template>\n\n <noscript *ngIf=\"device.isSSR\">\n <ng-container *ngTemplateOutlet=\"pictureTemplate\"></ng-container>\n </noscript>\n\n <bon-intersection #intersectionZone *ngIf=\"!device.isSSR\" [session]=\"src\" (intersected)=\"cd.detectChanges()\">\n\n <ng-container *ngIf=\"intersectionZone.intersectedOnce()\">\n <ng-container *ngTemplateOutlet=\"pictureTemplate\"></ng-container>\n </ng-container>\n\n </bon-intersection>\n\n <div *ngIf=\"src.ratio() > 0 && objectFit === MarcyObjectFit.Original\" [style.padding-top]=\"100 / src.ratio() +'%'\"></div>\n</div>\n", styles: [":host{display:block}.picture-container{overflow:hidden}.picture-container.cover picture,.picture-container.cover bon-intersection,.picture-container.contain picture,.picture-container.contain bon-intersection,.picture-container.knownRatio picture,.picture-container.knownRatio bon-intersection{width:100%;height:100%}.picture-container.cover picture>img,.picture-container.cover bon-intersection>img,.picture-container.contain picture>img,.picture-container.contain bon-intersection>img,.picture-container.knownRatio picture>img,.picture-container.knownRatio bon-intersection>img{height:100%}.picture-container.cover{height:100%}.picture-container.cover picture>img{object-fit:cover}.picture-container.contain{height:100%}.picture-container.contain picture>img{object-fit:contain}.picture-container.knownRatio{position:relative}.picture-container.knownRatio picture{position:absolute}.picture-container.knownRatio picture>img{object-fit:fill}picture{display:block;backface-visibility:hidden}picture>img{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IntersectionComponent, selector: "bon-intersection", inputs: ["session"], outputs: ["intersected"] }, { kind: "pipe", type: i1.AsyncPipe, name: "async" }] });
657
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: MarcyImageComponent, isStandalone: true, selector: "bon-image", inputs: { objectFit: { classPropertyName: "objectFit", publicName: "objectFit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isLoaded: "isLoaded" }, ngImport: i0, template: "@if (sources().length > 0) {\n <div [class.knownRatio]=\"src.ratio() > 0 && objectFit() === MarcyObjectFit.Original\"\n [class.cover]=\"objectFit() === MarcyObjectFit.Cover\"\n [class.contain]=\"objectFit() === MarcyObjectFit.Contain\"\n [class.loaded]=\"status() === MediaStatus.Loaded\"\n class=\"picture-container\">\n\n <ng-template #pictureTemplate>\n <picture>\n @for (source of sources(); track $index) {\n <source [srcset]=\"source.srcSet\"\n [attr.media]=\"source.media.length > 0 ? source.media : undefined\"\n [attr.type]=\"source.mime.length > 0 ? source.mime : undefined\"\n [attr.sizes]=\"source.sizes.length > 0 ? source.sizes : undefined\" />\n }\n <img [src]=\"defaultSrc()\" (load)=\"onLoad()\" alt=\"\" />\n </picture>\n </ng-template>\n\n @if (device.isSSR) {\n <noscript>\n <ng-container *ngTemplateOutlet=\"pictureTemplate\"></ng-container>\n </noscript>\n } @else {\n <bon-intersection #intersectionZone [session]=\"src\">\n @if (intersectionZone.isIntersected()) {\n <ng-container *ngTemplateOutlet=\"pictureTemplate\"></ng-container>\n }\n </bon-intersection>\n }\n\n @if (src.ratio() > 0 && objectFit() === MarcyObjectFit.Original) {\n <div [style.padding-top]=\"100 / src.ratio() +'%'\"></div>\n }\n </div>\n}\n", styles: [":host{display:block}.picture-container{overflow:hidden}.picture-container.cover picture,.picture-container.cover bon-intersection,.picture-container.contain picture,.picture-container.contain bon-intersection,.picture-container.knownRatio picture,.picture-container.knownRatio bon-intersection{width:100%;height:100%}.picture-container.cover picture>img,.picture-container.cover bon-intersection>img,.picture-container.contain picture>img,.picture-container.contain bon-intersection>img,.picture-container.knownRatio picture>img,.picture-container.knownRatio bon-intersection>img{height:100%}.picture-container.cover{height:100%}.picture-container.cover picture>img{object-fit:cover}.picture-container.contain{height:100%}.picture-container.contain picture>img{object-fit:contain}.picture-container.knownRatio{position:relative}.picture-container.knownRatio picture{position:absolute}.picture-container.knownRatio picture>img{object-fit:fill}picture{display:block;backface-visibility:hidden}picture>img{display:block;width:100%}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IntersectionComponent, selector: "bon-intersection", inputs: ["session"], outputs: ["intersected"] }] });
744
658
  }
745
659
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MarcyImageComponent, decorators: [{
746
660
  type: Component,
747
- args: [{ selector: 'bon-image', standalone: true, imports: [CommonModule, AsyncPipe, IntersectionComponent], providers: [UnsubscriberService], template: "<div *ngIf=\"sources.length > 0\"\n [class.knownRatio]=\"src.ratio() > 0 && objectFit === MarcyObjectFit.Original\"\n [class.cover]=\"objectFit === MarcyObjectFit.Cover\"\n [class.contain]=\"objectFit === MarcyObjectFit.Contain\"\n [class.loaded]=\"($status | async) === MediaStatus.Loaded\"\n class=\"picture-container\">\n\n <ng-template #pictureTemplate>\n <picture>\n <source *ngFor=\"let source of sources\"\n [srcset]=\"source.srcSet\"\n [attr.media]=\"source.media.length > 0 ? source.media : undefined\"\n [attr.type]=\"source.mime.length > 0 ? source.mime : undefined\"\n [attr.sizes]=\"source.sizes.length > 0 ? source.sizes : undefined\" />\n\n <img [src]=\"defaultSrc\" (load)=\"onLoad()\" />\n </picture>\n </ng-template>\n\n <noscript *ngIf=\"device.isSSR\">\n <ng-container *ngTemplateOutlet=\"pictureTemplate\"></ng-container>\n </noscript>\n\n <bon-intersection #intersectionZone *ngIf=\"!device.isSSR\" [session]=\"src\" (intersected)=\"cd.detectChanges()\">\n\n <ng-container *ngIf=\"intersectionZone.intersectedOnce()\">\n <ng-container *ngTemplateOutlet=\"pictureTemplate\"></ng-container>\n </ng-container>\n\n </bon-intersection>\n\n <div *ngIf=\"src.ratio() > 0 && objectFit === MarcyObjectFit.Original\" [style.padding-top]=\"100 / src.ratio() +'%'\"></div>\n</div>\n", styles: [":host{display:block}.picture-container{overflow:hidden}.picture-container.cover picture,.picture-container.cover bon-intersection,.picture-container.contain picture,.picture-container.contain bon-intersection,.picture-container.knownRatio picture,.picture-container.knownRatio bon-intersection{width:100%;height:100%}.picture-container.cover picture>img,.picture-container.cover bon-intersection>img,.picture-container.contain picture>img,.picture-container.contain bon-intersection>img,.picture-container.knownRatio picture>img,.picture-container.knownRatio bon-intersection>img{height:100%}.picture-container.cover{height:100%}.picture-container.cover picture>img{object-fit:cover}.picture-container.contain{height:100%}.picture-container.contain picture>img{object-fit:contain}.picture-container.knownRatio{position:relative}.picture-container.knownRatio picture{position:absolute}.picture-container.knownRatio picture>img{object-fit:fill}picture{display:block;backface-visibility:hidden}picture>img{display:block;width:100%}\n"] }]
748
- }], ctorParameters: () => [], propDecorators: { isLoaded: [{
749
- type: Output
750
- }], objectFit: [{
751
- type: Input
752
- }] } });
661
+ args: [{ selector: "bon-image", imports: [NgTemplateOutlet, IntersectionComponent], template: "@if (sources().length > 0) {\n <div [class.knownRatio]=\"src.ratio() > 0 && objectFit() === MarcyObjectFit.Original\"\n [class.cover]=\"objectFit() === MarcyObjectFit.Cover\"\n [class.contain]=\"objectFit() === MarcyObjectFit.Contain\"\n [class.loaded]=\"status() === MediaStatus.Loaded\"\n class=\"picture-container\">\n\n <ng-template #pictureTemplate>\n <picture>\n @for (source of sources(); track $index) {\n <source [srcset]=\"source.srcSet\"\n [attr.media]=\"source.media.length > 0 ? source.media : undefined\"\n [attr.type]=\"source.mime.length > 0 ? source.mime : undefined\"\n [attr.sizes]=\"source.sizes.length > 0 ? source.sizes : undefined\" />\n }\n <img [src]=\"defaultSrc()\" (load)=\"onLoad()\" alt=\"\" />\n </picture>\n </ng-template>\n\n @if (device.isSSR) {\n <noscript>\n <ng-container *ngTemplateOutlet=\"pictureTemplate\"></ng-container>\n </noscript>\n } @else {\n <bon-intersection #intersectionZone [session]=\"src\">\n @if (intersectionZone.isIntersected()) {\n <ng-container *ngTemplateOutlet=\"pictureTemplate\"></ng-container>\n }\n </bon-intersection>\n }\n\n @if (src.ratio() > 0 && objectFit() === MarcyObjectFit.Original) {\n <div [style.padding-top]=\"100 / src.ratio() +'%'\"></div>\n }\n </div>\n}\n", styles: [":host{display:block}.picture-container{overflow:hidden}.picture-container.cover picture,.picture-container.cover bon-intersection,.picture-container.contain picture,.picture-container.contain bon-intersection,.picture-container.knownRatio picture,.picture-container.knownRatio bon-intersection{width:100%;height:100%}.picture-container.cover picture>img,.picture-container.cover bon-intersection>img,.picture-container.contain picture>img,.picture-container.contain bon-intersection>img,.picture-container.knownRatio picture>img,.picture-container.knownRatio bon-intersection>img{height:100%}.picture-container.cover{height:100%}.picture-container.cover picture>img{object-fit:cover}.picture-container.contain{height:100%}.picture-container.contain picture>img{object-fit:contain}.picture-container.knownRatio{position:relative}.picture-container.knownRatio picture{position:absolute}.picture-container.knownRatio picture>img{object-fit:fill}picture{display:block;backface-visibility:hidden}picture>img{display:block;width:100%}\n"] }]
662
+ }], ctorParameters: () => [], propDecorators: { isLoaded: [{ type: i0.Output, args: ["isLoaded"] }], objectFit: [{ type: i0.Input, args: [{ isSignal: true, alias: "objectFit", required: false }] }] } });
753
663
 
754
664
  class VideoSrcDirective extends SrcBaseDirective {
755
- set vidsrc(value) {
756
- this.data = value;
757
- console.log('set vidsrc', value);
758
- }
665
+ data = model(undefined, { ...(ngDevMode ? { debugName: "data" } : {}), alias: "vidsrc" });
759
666
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: VideoSrcDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive });
760
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: VideoSrcDirective, isStandalone: true, selector: "[vidsrc]", inputs: { vidsrc: "vidsrc" }, usesInheritance: true, ngImport: i0 });
667
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: VideoSrcDirective, isStandalone: true, selector: "[vidsrc]", inputs: { data: { classPropertyName: "data", publicName: "vidsrc", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { data: "vidsrcChange" }, usesInheritance: true, ngImport: i0 });
761
668
  }
762
669
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: VideoSrcDirective, decorators: [{
763
670
  type: Directive,
764
671
  args: [{
765
- standalone: true,
766
- selector: '[vidsrc]',
672
+ selector: "[vidsrc]",
767
673
  }]
768
- }], propDecorators: { vidsrc: [{
769
- type: Input
770
- }] } });
674
+ }], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "vidsrc", required: false }] }, { type: i0.Output, args: ["vidsrcChange"] }] } });
771
675
 
772
676
  function isWebM(src) {
773
- return src.mimeType === 'video/webm';
677
+ return src.mimeType === "video/webm";
774
678
  }
775
679
  class MarcyVideoComponent {
776
680
  MediaStatus = MediaStatus;
777
681
  MarcyObjectFit = MediaObjectFit;
778
- videoRef;
779
- isLoaded = new EventEmitter();
780
- $status = signal(MediaStatus.NotSet, ...(ngDevMode ? [{ debugName: "$status" }] : []));
781
682
  src;
782
- _effectCleanup;
783
- source;
784
- _objectFit = MediaObjectFit.Original;
683
+ isLoaded = output();
684
+ objectFit = input(MediaObjectFit.Original, ...(ngDevMode ? [{ debugName: "objectFit" }] : []));
685
+ videoRef = viewChild("video", ...(ngDevMode ? [{ debugName: "videoRef" }] : []));
686
+ status = signal(MediaStatus.NotSet, ...(ngDevMode ? [{ debugName: "status" }] : []));
687
+ source = signal(undefined, ...(ngDevMode ? [{ debugName: "source" }] : []));
785
688
  device = inject(DeviceServiceBase);
786
- cd = inject(ChangeDetectorRef);
787
- _u = inject(UnsubscriberService);
788
689
  _srcDir = inject(VideoSrcDirective, { optional: true });
789
690
  constructor() {
790
- console.log('MarcyVideoComponent ctor');
791
691
  if (this._srcDir === undefined || this._srcDir === null)
792
692
  throw new Error(`${MarcyVideoComponent.name} should have [vidsrc] directive as source object`);
793
693
  this.src = this._srcDir;
794
- this.cd.detach();
795
- // Watch for status changes and emit when loaded
796
- this._effectCleanup = effect(() => {
797
- if (this.$status() === MediaStatus.Loaded) {
798
- this.isLoaded.next();
799
- }
800
- }, ...(ngDevMode ? [{ debugName: "_effectCleanup" }] : []));
801
- }
802
- ngOnInit() {
803
- console.log('MarcyVideoComponent ngOnInit');
804
- this.cd.detectChanges();
805
- }
806
- ngAfterViewInit() {
807
- console.log('MarcyVideoComponent ngAfterViewInit');
808
- // bind src changes
809
- this.src.srcChange
810
- .pipe(this._u.takeUntilDestroy)
811
- .subscribe((val) => {
812
- console.log('MarcyVideoComponent onSrcChange', val);
694
+ effect(() => {
695
+ this.src.data();
696
+ this.videoRef();
813
697
  this.updateSources();
814
- // resubscribe because its updated with src
815
698
  this.subscribeToMediaQueryChange();
816
699
  });
817
- this.updateSources();
818
- // initial, for src added before init
819
- this.subscribeToMediaQueryChange();
700
+ effect(() => {
701
+ if (this.status() === MediaStatus.Loaded) {
702
+ this.isLoaded.emit();
703
+ }
704
+ });
820
705
  }
821
706
  subscribeToMediaQueryChange() {
822
- this.src
823
- .watchMediaQueries()
824
- .subscribe(() => {
825
- console.log('MarcyVideoComponent watchMediaQueries');
707
+ this.src.watchMediaQueries().subscribe(() => {
708
+ console.log("MarcyVideoComponent watchMediaQueries");
826
709
  this.updateSources();
827
710
  });
828
711
  }
829
712
  updateSources() {
830
- console.log('MarcyVideoComponent updateSources');
831
- this.source = this.findMoreSuitableSource();
832
- console.log('MarcyVideoComponent new source', this.source);
833
- if (this.$status() === MediaStatus.NotSet && this.source === undefined) {
713
+ console.log("MarcyVideoComponent updateSources");
714
+ this.source.set(this.findMoreSuitableSource());
715
+ console.log("MarcyVideoComponent new source", this.source());
716
+ const src = this.source();
717
+ if (this.status() === MediaStatus.NotSet && src === undefined) {
834
718
  return;
835
719
  }
836
- if (this.source === undefined) {
837
- this.$status.set(MediaStatus.NotSet);
838
- this.cd.detectChanges();
720
+ if (src === undefined) {
721
+ this.status.set(MediaStatus.NotSet);
839
722
  return;
840
723
  }
841
- this.$status.set(MediaStatus.NotLoaded);
842
- this.cd.detectChanges();
843
- }
844
- set objectFit(val) {
845
- this._objectFit = val ?? MediaObjectFit.Original;
846
- this.cd.detectChanges();
847
- }
848
- get objectFit() {
849
- return this._objectFit;
724
+ this.status.set(MediaStatus.NotLoaded);
850
725
  }
851
726
  onLoad() {
852
- this.$status.set(MediaStatus.Loaded);
727
+ this.status.set(MediaStatus.Loaded);
853
728
  }
854
729
  findMoreSuitableSource() {
855
- if (this.videoRef === undefined) {
856
- console.log('skipping findMoreSuitableSource. videoRef is empty still');
730
+ const ref = this.videoRef();
731
+ if (ref === undefined) {
732
+ console.log("skipping findMoreSuitableSource. videoRef is empty still");
857
733
  return;
858
734
  }
859
- const videoSources = this.src.data?.sources ?? [];
860
- const currentVideoWidth = this.videoRef.nativeElement.clientWidth;
735
+ const videoSources = this.src.data()?.sources ?? [];
736
+ const currentVideoWidth = ref.nativeElement.clientWidth;
861
737
  const realPixelsVideoWidth = this.device.devicePixelRatio * currentVideoWidth;
862
738
  console.log(`MarcyVideoComponent currentVideoWidth ${currentVideoWidth}`);
863
739
  console.log(`MarcyVideoComponent realPixelsVideoWidth ${realPixelsVideoWidth}`);
@@ -866,19 +742,14 @@ class MarcyVideoComponent {
866
742
  if (!matchesMediaQuery(videoSource.mediaQuery))
867
743
  continue;
868
744
  // SSR
869
- if (typeof this.videoRef.nativeElement?.canPlayType !== 'function') {
870
- // return first mp4, because all players can play them
871
- const mp4Srcs = videoSource
872
- .srcSet
873
- .filter(x => x.mimeType === 'video/mp4')
874
- .sort(descendingT(x => x.meta.width)); // bigest video
875
- // console.log(`ssr found video ${mp4Srcs[0].url}`)
876
- // element or undefined
745
+ if (typeof ref.nativeElement.canPlayType !== "function") {
746
+ const mp4Srcs = videoSource.srcSet
747
+ .filter((x) => x.mimeType === "video/mp4")
748
+ .sort(descendingT((x) => x.meta.width));
877
749
  return mp4Srcs[0];
878
750
  }
879
- const fileSrcs = videoSource
880
- .srcSet
881
- .filter(x => this.videoRef.nativeElement.canPlayType(x.mimeType))
751
+ const fileSrcs = videoSource.srcSet
752
+ .filter((x) => ref.nativeElement.canPlayType(x.mimeType))
882
753
  .sort((a, b) => {
883
754
  if (a.meta.width === b.meta.width) {
884
755
  return isWebM(a) ? -1 : 1; // if same width prefer webM
@@ -904,111 +775,51 @@ class MarcyVideoComponent {
904
775
  }
905
776
  return undefined;
906
777
  }
907
- ngOnDestroy() {
908
- this._effectCleanup?.destroy();
909
- }
910
778
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MarcyVideoComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
911
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: MarcyVideoComponent, isStandalone: true, selector: "bon-video", inputs: { objectFit: "objectFit" }, outputs: { isLoaded: "isLoaded" }, providers: [UnsubscriberService], viewQueries: [{ propertyName: "videoRef", first: true, predicate: ["video"], descendants: true }], ngImport: i0, template: "<div [class.knownRatio]=\"src.ratio() > 0 && objectFit === MarcyObjectFit.Original\"\n [class.cover]=\"objectFit === MarcyObjectFit.Cover\"\n [class.contain]=\"objectFit === MarcyObjectFit.Contain\"\n [class.loaded]=\"$status() === MediaStatus.Loaded\"\n class=\"video-container\">\n\n <ng-container *ngIf=\"device.isSSR ; then ssrTemplate else browserTemplate\"></ng-container>\n\n <ng-template #videoTemplate>\n <video #video\n [src]=\"source !== undefined ? source.url :'' \"\n (load)=\"onLoad()\"\n (canplay)=\"video.muted=true;video.play();\"\n playsInline\n autoplay\n loop\n muted> </video>\n </ng-template>\n\n <ng-template #ssrTemplate>\n <noscript *ngIf=\"device.isSSR\">\n <ng-container *ngTemplateOutlet=\"videoTemplate\"></ng-container>\n </noscript>\n </ng-template>\n\n <ng-template #browserTemplate>\n <bon-intersection #intersectionZone [session]=\"src\" (intersected)=\"cd.detectChanges()\">\n <ng-container *ngTemplateOutlet=\"videoTemplate\"></ng-container>\n </bon-intersection>\n </ng-template>\n\n <div *ngIf=\"src.ratio() > 0 && objectFit === MarcyObjectFit.Original\" [style.padding-top]=\"100 / src.ratio() +'%'\"></div>\n</div>\n", styles: [":host{display:block}.video-container{background-color:#000;overflow:hidden}.video-container.cover video,.video-container.cover bon-intersection,.video-container.contain video,.video-container.contain bon-intersection,.video-container.knownRatio video,.video-container.knownRatio bon-intersection{width:100%;height:100%}.video-container.cover{height:100%}.video-container.cover video{object-fit:cover}.video-container.contain{height:100%}.video-container.contain video{object-fit:contain}.video-container.knownRatio{position:relative}.video-container.knownRatio video{position:absolute;object-fit:fill}video{display:block;width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IntersectionComponent, selector: "bon-intersection", inputs: ["session"], outputs: ["intersected"] }] });
779
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: MarcyVideoComponent, isStandalone: true, selector: "bon-video", inputs: { objectFit: { classPropertyName: "objectFit", publicName: "objectFit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isLoaded: "isLoaded" }, viewQueries: [{ propertyName: "videoRef", first: true, predicate: ["video"], descendants: true, isSignal: true }], ngImport: i0, template: "<div\n [class.knownRatio]=\"\n src.ratio() > 0 && objectFit() === MarcyObjectFit.Original\n \"\n [class.cover]=\"objectFit() === MarcyObjectFit.Cover\"\n [class.contain]=\"objectFit() === MarcyObjectFit.Contain\"\n [class.loaded]=\"status() === MediaStatus.Loaded\"\n class=\"video-container\"\n>\n @if (device.isSSR) {\n <ng-container *ngTemplateOutlet=\"ssrTemplate\"></ng-container>\n } @else {\n <ng-container *ngTemplateOutlet=\"browserTemplate\"></ng-container>\n }\n\n <ng-template #videoTemplate>\n <video\n #video\n [src]=\"source()?.url ?? ''\"\n (load)=\"onLoad()\"\n (canplay)=\"video.muted = true; video.play()\"\n playsInline\n autoplay\n loop\n muted\n ></video>\n </ng-template>\n\n <ng-template #ssrTemplate>\n @if (device.isSSR) {\n <noscript>\n <ng-container *ngTemplateOutlet=\"videoTemplate\"></ng-container>\n </noscript>\n }\n </ng-template>\n\n <ng-template #browserTemplate>\n <bon-intersection #intersectionZone [session]=\"src\">\n <ng-container *ngTemplateOutlet=\"videoTemplate\"></ng-container>\n </bon-intersection>\n </ng-template>\n\n @if (src.ratio() > 0 && objectFit() === MarcyObjectFit.Original) {\n <div [style.padding-top]=\"100 / src.ratio() + '%'\"></div>\n }\n</div>\n", styles: [":host{display:block}.video-container{background-color:#000;overflow:hidden}.video-container.cover video,.video-container.cover bon-intersection,.video-container.contain video,.video-container.contain bon-intersection,.video-container.knownRatio video,.video-container.knownRatio bon-intersection{width:100%;height:100%}.video-container.cover{height:100%}.video-container.cover video{object-fit:cover}.video-container.contain{height:100%}.video-container.contain video{object-fit:contain}.video-container.knownRatio{position:relative}.video-container.knownRatio video{position:absolute;object-fit:fill}video{display:block;width:100%}\n"], dependencies: [{ kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: IntersectionComponent, selector: "bon-intersection", inputs: ["session"], outputs: ["intersected"] }] });
912
780
  }
913
781
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MarcyVideoComponent, decorators: [{
914
782
  type: Component,
915
- args: [{ selector: 'bon-video', standalone: true, imports: [CommonModule, IntersectionComponent], providers: [UnsubscriberService], template: "<div [class.knownRatio]=\"src.ratio() > 0 && objectFit === MarcyObjectFit.Original\"\n [class.cover]=\"objectFit === MarcyObjectFit.Cover\"\n [class.contain]=\"objectFit === MarcyObjectFit.Contain\"\n [class.loaded]=\"$status() === MediaStatus.Loaded\"\n class=\"video-container\">\n\n <ng-container *ngIf=\"device.isSSR ; then ssrTemplate else browserTemplate\"></ng-container>\n\n <ng-template #videoTemplate>\n <video #video\n [src]=\"source !== undefined ? source.url :'' \"\n (load)=\"onLoad()\"\n (canplay)=\"video.muted=true;video.play();\"\n playsInline\n autoplay\n loop\n muted> </video>\n </ng-template>\n\n <ng-template #ssrTemplate>\n <noscript *ngIf=\"device.isSSR\">\n <ng-container *ngTemplateOutlet=\"videoTemplate\"></ng-container>\n </noscript>\n </ng-template>\n\n <ng-template #browserTemplate>\n <bon-intersection #intersectionZone [session]=\"src\" (intersected)=\"cd.detectChanges()\">\n <ng-container *ngTemplateOutlet=\"videoTemplate\"></ng-container>\n </bon-intersection>\n </ng-template>\n\n <div *ngIf=\"src.ratio() > 0 && objectFit === MarcyObjectFit.Original\" [style.padding-top]=\"100 / src.ratio() +'%'\"></div>\n</div>\n", styles: [":host{display:block}.video-container{background-color:#000;overflow:hidden}.video-container.cover video,.video-container.cover bon-intersection,.video-container.contain video,.video-container.contain bon-intersection,.video-container.knownRatio video,.video-container.knownRatio bon-intersection{width:100%;height:100%}.video-container.cover{height:100%}.video-container.cover video{object-fit:cover}.video-container.contain{height:100%}.video-container.contain video{object-fit:contain}.video-container.knownRatio{position:relative}.video-container.knownRatio video{position:absolute;object-fit:fill}video{display:block;width:100%}\n"] }]
916
- }], ctorParameters: () => [], propDecorators: { videoRef: [{
917
- type: ViewChild,
918
- args: ['video']
919
- }], isLoaded: [{
920
- type: Output
921
- }], objectFit: [{
922
- type: Input
923
- }] } });
783
+ args: [{ selector: "bon-video", imports: [NgTemplateOutlet, IntersectionComponent], template: "<div\n [class.knownRatio]=\"\n src.ratio() > 0 && objectFit() === MarcyObjectFit.Original\n \"\n [class.cover]=\"objectFit() === MarcyObjectFit.Cover\"\n [class.contain]=\"objectFit() === MarcyObjectFit.Contain\"\n [class.loaded]=\"status() === MediaStatus.Loaded\"\n class=\"video-container\"\n>\n @if (device.isSSR) {\n <ng-container *ngTemplateOutlet=\"ssrTemplate\"></ng-container>\n } @else {\n <ng-container *ngTemplateOutlet=\"browserTemplate\"></ng-container>\n }\n\n <ng-template #videoTemplate>\n <video\n #video\n [src]=\"source()?.url ?? ''\"\n (load)=\"onLoad()\"\n (canplay)=\"video.muted = true; video.play()\"\n playsInline\n autoplay\n loop\n muted\n ></video>\n </ng-template>\n\n <ng-template #ssrTemplate>\n @if (device.isSSR) {\n <noscript>\n <ng-container *ngTemplateOutlet=\"videoTemplate\"></ng-container>\n </noscript>\n }\n </ng-template>\n\n <ng-template #browserTemplate>\n <bon-intersection #intersectionZone [session]=\"src\">\n <ng-container *ngTemplateOutlet=\"videoTemplate\"></ng-container>\n </bon-intersection>\n </ng-template>\n\n @if (src.ratio() > 0 && objectFit() === MarcyObjectFit.Original) {\n <div [style.padding-top]=\"100 / src.ratio() + '%'\"></div>\n }\n</div>\n", styles: [":host{display:block}.video-container{background-color:#000;overflow:hidden}.video-container.cover video,.video-container.cover bon-intersection,.video-container.contain video,.video-container.contain bon-intersection,.video-container.knownRatio video,.video-container.knownRatio bon-intersection{width:100%;height:100%}.video-container.cover{height:100%}.video-container.cover video{object-fit:cover}.video-container.contain{height:100%}.video-container.contain video{object-fit:contain}.video-container.knownRatio{position:relative}.video-container.knownRatio video{position:absolute;object-fit:fill}video{display:block;width:100%}\n"] }]
784
+ }], ctorParameters: () => [], propDecorators: { isLoaded: [{ type: i0.Output, args: ["isLoaded"] }], objectFit: [{ type: i0.Input, args: [{ isSignal: true, alias: "objectFit", required: false }] }], videoRef: [{ type: i0.ViewChild, args: ["video", { isSignal: true }] }] } });
924
785
 
925
786
  class MarcyMediaComponent {
926
- cd = inject(ChangeDetectorRef);
927
787
  MarcyObjectFit = MediaObjectFit;
928
- isLoaded = new EventEmitter();
929
- _objectFit = MediaObjectFit.Original;
930
- _src;
931
- constructor() {
932
- const cd = this.cd;
933
- console.log('MarcyMediaComponent ctor');
934
- cd.detach();
935
- }
936
- ngOnInit() {
937
- console.log('MarcyMediaComponent ngOnInit');
938
- this.cd.detectChanges();
939
- }
940
- get src() {
941
- return this._src;
942
- }
943
- set src(val) {
944
- console.log('set data', val);
945
- this._src = val;
946
- this.cd.detectChanges();
947
- }
948
- set objectFit(val) {
949
- this._objectFit = val ?? MediaObjectFit.Original;
950
- this.cd.detectChanges();
951
- }
952
- get objectFit() {
953
- return this._objectFit;
954
- }
788
+ isLoaded = output();
789
+ src = input(...(ngDevMode ? [undefined, { debugName: "src" }] : []));
790
+ objectFit = input(MediaObjectFit.Original, ...(ngDevMode ? [{ debugName: "objectFit" }] : []));
955
791
  onLoad() {
956
- this.isLoaded.next();
792
+ this.isLoaded.emit();
957
793
  }
958
794
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MarcyMediaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
959
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: MarcyMediaComponent, isStandalone: true, selector: "bon-media", inputs: { src: "src", objectFit: "objectFit" }, outputs: { isLoaded: "isLoaded" }, providers: [UnsubscriberService], ngImport: i0, template: "<bon-image *ngIf=\"src && src.type==='image'\"\n [imgsrc]=\"src\"\n [objectFit]=\"objectFit\"\n (isLoaded)=\"onLoad()\"></bon-image>\n\n<bon-video *ngIf=\"src && src.type==='video'\"\n [vidsrc]=\"src\"\n [objectFit]=\"objectFit\"\n (isLoaded)=\"onLoad()\"></bon-video>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: MarcyImageComponent, selector: "bon-image", inputs: ["objectFit"], outputs: ["isLoaded"] }, { kind: "component", type: MarcyVideoComponent, selector: "bon-video", inputs: ["objectFit"], outputs: ["isLoaded"] }, { kind: "directive", type: VideoSrcDirective, selector: "[vidsrc]", inputs: ["vidsrc"] }, { kind: "directive", type: ImageSrcDirective, selector: "[imgsrc]", inputs: ["imgsrc"] }] });
795
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: MarcyMediaComponent, isStandalone: true, selector: "bon-media", inputs: { src: { classPropertyName: "src", publicName: "src", isSignal: true, isRequired: false, transformFunction: null }, objectFit: { classPropertyName: "objectFit", publicName: "objectFit", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { isLoaded: "isLoaded" }, ngImport: i0, template: "@if (src(); as mediaSrc) {\n @if (mediaSrc.type === 'image') {\n <bon-image\n [imgsrc]=\"mediaSrc\"\n [objectFit]=\"objectFit()\"\n (isLoaded)=\"onLoad()\"\n ></bon-image>\n } @else if (mediaSrc.type === 'video') {\n <bon-video\n [vidsrc]=\"mediaSrc\"\n [objectFit]=\"objectFit()\"\n (isLoaded)=\"onLoad()\"\n ></bon-video>\n }\n}\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: MarcyImageComponent, selector: "bon-image", inputs: ["objectFit"], outputs: ["isLoaded"] }, { kind: "component", type: MarcyVideoComponent, selector: "bon-video", inputs: ["objectFit"], outputs: ["isLoaded"] }, { kind: "directive", type: VideoSrcDirective, selector: "[vidsrc]", inputs: ["vidsrc"], outputs: ["vidsrcChange"] }, { kind: "directive", type: ImageSrcDirective, selector: "[imgsrc]", inputs: ["imgsrc"], outputs: ["imgsrcChange"] }] });
960
796
  }
961
797
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MarcyMediaComponent, decorators: [{
962
798
  type: Component,
963
- args: [{ selector: 'bon-media', standalone: true, imports: [CommonModule, MarcyImageComponent, MarcyVideoComponent, VideoSrcDirective, ImageSrcDirective], providers: [UnsubscriberService], template: "<bon-image *ngIf=\"src && src.type==='image'\"\n [imgsrc]=\"src\"\n [objectFit]=\"objectFit\"\n (isLoaded)=\"onLoad()\"></bon-image>\n\n<bon-video *ngIf=\"src && src.type==='video'\"\n [vidsrc]=\"src\"\n [objectFit]=\"objectFit\"\n (isLoaded)=\"onLoad()\"></bon-video>\n", styles: [":host{display:block}\n"] }]
964
- }], ctorParameters: () => [], propDecorators: { isLoaded: [{
965
- type: Output
966
- }], src: [{
967
- type: Input
968
- }], objectFit: [{
969
- type: Input
970
- }] } });
799
+ args: [{ selector: "bon-media", imports: [MarcyImageComponent, MarcyVideoComponent, VideoSrcDirective, ImageSrcDirective], template: "@if (src(); as mediaSrc) {\n @if (mediaSrc.type === 'image') {\n <bon-image\n [imgsrc]=\"mediaSrc\"\n [objectFit]=\"objectFit()\"\n (isLoaded)=\"onLoad()\"\n ></bon-image>\n } @else if (mediaSrc.type === 'video') {\n <bon-video\n [vidsrc]=\"mediaSrc\"\n [objectFit]=\"objectFit()\"\n (isLoaded)=\"onLoad()\"\n ></bon-video>\n }\n}\n", styles: [":host{display:block}\n"] }]
800
+ }], propDecorators: { isLoaded: [{ type: i0.Output, args: ["isLoaded"] }], src: [{ type: i0.Input, args: [{ isSignal: true, alias: "src", required: false }] }], objectFit: [{ type: i0.Input, args: [{ isSignal: true, alias: "objectFit", required: false }] }] } });
971
801
 
972
- class BoneDirective {
973
- _bone;
974
- cd = inject(ChangeDetectorRef);
975
- localizationService = inject(LocalizeServiceBase);
976
- _effectCleanup;
977
- constructor() {
978
- this.cd.detach();
979
- // todo: check if this is needed
980
- // Watch locale changes using signal
981
- this._effectCleanup = effect(() => {
982
- // Access the signal to track changes
983
- this.localizationService.locale();
984
- // need to detect changes in our detached components
985
- this.cd.detectChanges();
986
- }, ...(ngDevMode ? [{ debugName: "_effectCleanup" }] : []));
987
- }
988
- ngOnInit() {
989
- }
990
- set bone(value) {
991
- this._bone = value;
992
- this.cd.detectChanges();
993
- }
994
- get bone() {
995
- if (this._bone === undefined || this._bone === null)
996
- throw new Error('The property "bone" should be set at least once. For example in skeleton');
997
- return this._bone;
998
- }
999
- ngOnDestroy() {
1000
- this._effectCleanup?.destroy();
802
+ class BoneMap extends Map {
803
+ getRequired(key) {
804
+ const value = this.get(key);
805
+ if (value === undefined || value === null) {
806
+ throw Error(`BoneMap doesn't contain type for key = ${key}`);
807
+ }
808
+ return value;
1001
809
  }
810
+ }
811
+
812
+ class BoneDirective {
813
+ bone = model.required(...(ngDevMode ? [{ debugName: "bone" }] : []));
1002
814
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BoneDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
1003
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: BoneDirective, isStandalone: true, selector: "[bonBoneDir]", ngImport: i0 });
815
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "17.1.0", version: "21.0.6", type: BoneDirective, isStandalone: true, selector: "[bonBoneDir]", inputs: { bone: { classPropertyName: "bone", publicName: "bone", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { bone: "boneChange" }, ngImport: i0 });
1004
816
  }
1005
817
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BoneDirective, decorators: [{
1006
818
  type: Directive,
1007
819
  args: [{
1008
- selector: '[bonBoneDir]',
1009
- standalone: true
820
+ selector: "[bonBoneDir]",
1010
821
  }]
1011
- }], ctorParameters: () => [] });
822
+ }], propDecorators: { bone: [{ type: i0.Input, args: [{ isSignal: true, alias: "bone", required: true }] }, { type: i0.Output, args: ["boneChange"] }] } });
1012
823
 
1013
824
  class SkeletonAnchorDirective {
1014
825
  viewContainerRef = inject(ViewContainerRef);
@@ -1018,92 +829,64 @@ class SkeletonAnchorDirective {
1018
829
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SkeletonAnchorDirective, decorators: [{
1019
830
  type: Directive,
1020
831
  args: [{
1021
- selector: '[bonSkeletonAnchor]',
1022
- standalone: true
832
+ selector: "[bonSkeletonAnchor]",
1023
833
  }]
1024
834
  }] });
1025
835
 
1026
836
  class UnknownBoneComponent {
1027
- cd = inject(ChangeDetectorRef);
1028
837
  bd = inject((BoneDirective), { host: true });
1029
- constructor() {
1030
- console.log('BoneDirective', this.bd);
1031
- this.cd.detach();
1032
- }
1033
- ngOnInit() {
1034
- this.cd.detectChanges();
1035
- }
1036
838
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UnknownBoneComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1037
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: UnknownBoneComponent, isStandalone: true, selector: "bon-unknown-bone", hostDirectives: [{ directive: BoneDirective }], ngImport: i0, template: `<h2>unknown bone {{bd.bone.type}}</h2>
1038
- <div>{{bd.bone | json}}</div>`, isInline: true, styles: [":host{display:block;border:2px solid red;box-sizing:border-box}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1.JsonPipe, name: "json" }] });
839
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: UnknownBoneComponent, isStandalone: true, selector: "bon-unknown-bone", hostDirectives: [{ directive: BoneDirective, inputs: ["bone", "bone"], outputs: ["boneChange", "boneChange"] }], ngImport: i0, template: `@if (bd.bone(); as bone) {
840
+ <h2>unknown bone {{bone.type}}</h2>
841
+ <div>{{bone | json}}</div>
842
+ } @else{
843
+ bone is undefined
844
+ }`, isInline: true, styles: [":host{display:block;border:2px solid red;box-sizing:border-box}\n"], dependencies: [{ kind: "pipe", type: JsonPipe, name: "json" }] });
1039
845
  }
1040
846
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UnknownBoneComponent, decorators: [{
1041
847
  type: Component,
1042
- args: [{ selector: 'bon-unknown-bone', standalone: true, imports: [CommonModule, JsonPipe], hostDirectives: [BoneDirective], template: `<h2>unknown bone {{bd.bone.type}}</h2>
1043
- <div>{{bd.bone | json}}</div>`, styles: [":host{display:block;border:2px solid red;box-sizing:border-box}\n"] }]
1044
- }], ctorParameters: () => [] });
848
+ args: [{ selector: "bon-unknown-bone", imports: [JsonPipe], hostDirectives: [{ directive: BoneDirective, inputs: ["bone"], outputs: ["boneChange"] }], template: `@if (bd.bone(); as bone) {
849
+ <h2>unknown bone {{bone.type}}</h2>
850
+ <div>{{bone | json}}</div>
851
+ } @else{
852
+ bone is undefined
853
+ }`, styles: [":host{display:block;border:2px solid red;box-sizing:border-box}\n"] }]
854
+ }] });
1045
855
 
1046
856
  class SkeletonComponent {
1047
- skeletonAnchor;
1048
- map;
1049
- _bones = [];
1050
- iniailized = false;
1051
- cd = inject(ChangeDetectorRef);
1052
- ngOnInit() {
1053
- this.iniailized = true;
1054
- this.fillComponentFromBones();
1055
- }
1056
- set bones(newValue) {
1057
- this._bones.splice(0, this._bones.length);
1058
- this._bones.push(...newValue ?? []);
1059
- this.fillComponentFromBones();
1060
- }
1061
- fillComponentFromBones() {
1062
- if (this.iniailized === false)
1063
- return;
1064
- const viewContainerRef = this.skeletonAnchor.viewContainerRef;
1065
- viewContainerRef.clear();
1066
- if (this.map === undefined || this.map === null)
1067
- throw new Error('add type map with input: [map]="..."');
1068
- for (const bone of this._bones) {
1069
- let componentType = this.map.get(bone.type);
1070
- if (componentType === undefined || componentType === null) {
1071
- console.warn(`Mapping type for ${bone.type} not found`);
1072
- componentType = UnknownBoneComponent;
857
+ skeletonAnchor = viewChild.required(SkeletonAnchorDirective);
858
+ map = input.required(...(ngDevMode ? [{ debugName: "map" }] : []));
859
+ bones = input.required(...(ngDevMode ? [{ debugName: "bones" }] : []));
860
+ constructor() {
861
+ effect(() => {
862
+ const anchor = this.skeletonAnchor();
863
+ const bones = this.bones();
864
+ const mapVal = this.map();
865
+ const viewContainerRef = anchor.viewContainerRef;
866
+ viewContainerRef.clear();
867
+ if (mapVal === undefined || mapVal === null)
868
+ throw new Error('add type map with input: [map]="..."');
869
+ for (const bone of bones) {
870
+ let componentType = mapVal.get(bone.type);
871
+ if (componentType === undefined || componentType === null) {
872
+ console.warn(`Mapping type for ${bone.type} not found`);
873
+ componentType = UnknownBoneComponent;
874
+ }
875
+ viewContainerRef.createComponent(componentType).setInput("bone", bone);
1073
876
  }
1074
- const boneComponentRef = viewContainerRef.createComponent(componentType);
1075
- boneComponentRef.instance.bd.bone = bone;
1076
- }
877
+ });
1077
878
  }
1078
879
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SkeletonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1079
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.0.6", type: SkeletonComponent, isStandalone: true, selector: "bon-skeleton", inputs: { map: "map", bones: "bones" }, viewQueries: [{ propertyName: "skeletonAnchor", first: true, predicate: SkeletonAnchorDirective, descendants: true, static: true }], ngImport: i0, template: "<ng-template bonSkeletonAnchor></ng-template>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: SkeletonAnchorDirective, selector: "[bonSkeletonAnchor]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
880
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.0.6", type: SkeletonComponent, isStandalone: true, selector: "bon-skeleton", inputs: { map: { classPropertyName: "map", publicName: "map", isSignal: true, isRequired: true, transformFunction: null }, bones: { classPropertyName: "bones", publicName: "bones", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "skeletonAnchor", first: true, predicate: SkeletonAnchorDirective, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-template bonSkeletonAnchor></ng-template>\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "directive", type: SkeletonAnchorDirective, selector: "[bonSkeletonAnchor]" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1080
881
  }
1081
882
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SkeletonComponent, decorators: [{
1082
883
  type: Component,
1083
- args: [{ selector: 'bon-skeleton', standalone: true, imports: [SkeletonAnchorDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template bonSkeletonAnchor></ng-template>\n", styles: [":host{display:block}\n"] }]
1084
- }], propDecorators: { skeletonAnchor: [{
1085
- type: ViewChild,
1086
- args: [SkeletonAnchorDirective, { static: true }]
1087
- }], map: [{
1088
- type: Input,
1089
- args: [{ required: true }]
1090
- }], bones: [{
1091
- type: Input
1092
- }] } });
1093
-
1094
- class BoneMap extends Map {
1095
- getRequired(key) {
1096
- const value = this.get(key);
1097
- if (value === undefined || value === null) {
1098
- throw Error(`BoneMap doesn't contain type for key = ${key}`);
1099
- }
1100
- return value;
1101
- }
1102
- }
884
+ args: [{ selector: "bon-skeleton", imports: [SkeletonAnchorDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template bonSkeletonAnchor></ng-template>\n", styles: [":host{display:block}\n"] }]
885
+ }], ctorParameters: () => [], propDecorators: { skeletonAnchor: [{ type: i0.ViewChild, args: [i0.forwardRef(() => SkeletonAnchorDirective), { isSignal: true }] }], map: [{ type: i0.Input, args: [{ isSignal: true, alias: "map", required: true }] }], bones: [{ type: i0.Input, args: [{ isSignal: true, alias: "bones", required: true }] }] } });
1103
886
 
1104
887
  /**
1105
888
  * Generated bundle index. Do not edit.
1106
889
  */
1107
890
 
1108
- export { BoneDirective, BoneMap, DeviceService, DeviceServiceBase, EncodeURIComponentPipe, ImageSrcDirective, IntersectionComponent, IsLocalUrlPipe, IsNotLocalUrlPipe, LocalizationIsEmptyPipe, LocalizationIsNotEmptyPipe, LocalizeObjectPipe, LocalizePipe, LocalizeServiceBase, LocalizeUrlPipe, MarcyImageComponent, MarcyMediaComponent, MarcyVideoComponent, MediaObjectFit, MediaStatus, PublishStatus, SizesWidthUnit, SkeletonAnchorDirective, SkeletonComponent, SrcBaseDirective, UnknownBoneComponent, UnsubscriberService, VideoSrcDirective, emptyBone, emptyImage, emptyLocalizedString, emptyVideo, getDefaultSrc, toHtmlPictureSources };
891
+ export { BoneDirective, BoneMap, DeviceService, DeviceServiceBase, EncodeURIComponentPipe, ImageSrcDirective, IntersectionComponent, IsLocalUrlPipe, IsNotLocalUrlPipe, LocalizationIsEmptyPipe, LocalizationIsNotEmptyPipe, LocalizeObjectPipe, LocalizePipe, LocalizeServiceBase, LocalizeUrlPipe, MarcyImageComponent, MarcyMediaComponent, MarcyVideoComponent, MediaObjectFit, MediaStatus, PublishStatus, SizesWidthUnit, SkeletonAnchorDirective, SkeletonComponent, SrcBaseDirective, UnknownBoneComponent, VideoSrcDirective, emptyBone, emptyImage, emptyLocalizedString, emptyVideo, getDefaultSrc, toHtmlPictureSources };
1109
892
  //# sourceMappingURL=candy-kingdom-bonnie.mjs.map