@candy-kingdom/bonnie 0.26.16 → 0.27.1
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,294 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { Injectable,
|
|
3
|
-
import {
|
|
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
|
|
6
|
-
|
|
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
|
+
}
|
|
85
|
+
console.log("reset intersection Observer");
|
|
86
|
+
this._session = newSession;
|
|
87
|
+
this.reset();
|
|
88
|
+
});
|
|
89
|
+
inject(DestroyRef).onDestroy(() => this._intersectionObserver?.disconnect());
|
|
90
|
+
}
|
|
91
|
+
reset() {
|
|
92
|
+
if (this._intersectionObserver === undefined || this._intersectionObserver === null) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
this._intersectionObserver.unobserve(this._hostRef.nativeElement);
|
|
96
|
+
this._isIntersected.set(false);
|
|
97
|
+
this._intersectionObserver.observe(this._hostRef.nativeElement);
|
|
98
|
+
}
|
|
99
|
+
onIntersection(entries, observer) {
|
|
100
|
+
if (entries.length > 1) {
|
|
101
|
+
console.warn("multi entries!");
|
|
102
|
+
}
|
|
103
|
+
const isIntersecting = entries[0].isIntersecting;
|
|
104
|
+
this._isIntersected.set(isIntersecting);
|
|
105
|
+
console.log(`intersected ${isIntersecting}`, this._hostRef.nativeElement);
|
|
106
|
+
// only once will recieve intersection
|
|
107
|
+
if (isIntersecting) {
|
|
108
|
+
observer.unobserve(this._hostRef.nativeElement);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IntersectionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
112
|
+
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"] });
|
|
113
|
+
}
|
|
114
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IntersectionComponent, decorators: [{
|
|
115
|
+
type: Component,
|
|
116
|
+
args: [{ selector: "bon-intersection", template: "<ng-content></ng-content>", styles: [":host{display:block}\n"] }]
|
|
117
|
+
}], ctorParameters: () => [], propDecorators: { intersected: [{ type: i0.Output, args: ["intersected"] }], session: [{ type: i0.Input, args: [{ isSignal: true, alias: "session", required: false }] }] } });
|
|
118
|
+
|
|
119
|
+
var MediaObjectFit;
|
|
120
|
+
(function (MediaObjectFit) {
|
|
121
|
+
MediaObjectFit["Original"] = "Original";
|
|
122
|
+
MediaObjectFit["Cover"] = "Cover";
|
|
123
|
+
MediaObjectFit["Contain"] = "Contain";
|
|
124
|
+
})(MediaObjectFit || (MediaObjectFit = {}));
|
|
125
|
+
|
|
126
|
+
var MediaStatus;
|
|
127
|
+
(function (MediaStatus) {
|
|
128
|
+
MediaStatus["NotSet"] = "NotSet";
|
|
129
|
+
MediaStatus["NotLoaded"] = "NotLoaded";
|
|
130
|
+
MediaStatus["Loading"] = "Loading";
|
|
131
|
+
MediaStatus["Loaded"] = "Loaded";
|
|
132
|
+
})(MediaStatus || (MediaStatus = {}));
|
|
133
|
+
|
|
134
|
+
// https://stackoverflow.com/questions/42136098/array-groupby-in-typescript
|
|
135
|
+
const groupBy = (arr, key) => arr.reduce((groups, item) => {
|
|
136
|
+
(groups[key(item)] ||= []).push(item);
|
|
137
|
+
return groups;
|
|
138
|
+
}, {});
|
|
139
|
+
function distinct(value, index, array) {
|
|
140
|
+
return array.indexOf(value) === index;
|
|
141
|
+
}
|
|
142
|
+
function ascending(a, b) {
|
|
143
|
+
return a - b;
|
|
144
|
+
}
|
|
145
|
+
function ascendingT(sel) {
|
|
146
|
+
return (a, b) => ascending(sel(a), sel(b));
|
|
147
|
+
}
|
|
148
|
+
function descending(a, b) {
|
|
149
|
+
return b - a;
|
|
150
|
+
}
|
|
151
|
+
function descendingT(sel) {
|
|
152
|
+
return (a, b) => descending(sel(a), sel(b));
|
|
153
|
+
}
|
|
154
|
+
function generateSizesString(sizes) {
|
|
155
|
+
const sizesString = sizes
|
|
156
|
+
.sort((x) => x.width)
|
|
157
|
+
.map((x) => `${x.mediaQuery} ${x.width}${x.unit.toLowerCase()}`.trim())
|
|
158
|
+
.join(",");
|
|
159
|
+
return sizesString;
|
|
160
|
+
}
|
|
161
|
+
function matchesMediaQuery(mediaQuery) {
|
|
162
|
+
const isEmptyQuery = mediaQuery === null || mediaQuery === undefined || mediaQuery.trim().length === 0;
|
|
163
|
+
// work for SSR and browser
|
|
164
|
+
if (isEmptyQuery) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
// other queries disallowed in SSR
|
|
168
|
+
if (typeof window === "undefined") {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
const mediaQueryList = window.matchMedia(mediaQuery);
|
|
172
|
+
return mediaQueryList.matches;
|
|
173
|
+
}
|
|
174
|
+
function isLocalUrlString(url) {
|
|
175
|
+
if (url === undefined || url === null || url.trim().length === 0) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
if (url.startsWith("//")) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
if (url.startsWith("./") || url.startsWith("/")) {
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
class SrcBaseDirective {
|
|
188
|
+
ratioChange = output();
|
|
189
|
+
_ratio = signal(0, ...(ngDevMode ? [{ debugName: "_ratio" }] : []));
|
|
190
|
+
ratio = this._ratio.asReadonly();
|
|
191
|
+
_queryChangeClearSubject = new Subject();
|
|
192
|
+
_destroyRef = inject(DestroyRef);
|
|
193
|
+
constructor() {
|
|
194
|
+
effect(() => {
|
|
195
|
+
const ratio = this._ratio();
|
|
196
|
+
this.ratioChange.emit(ratio);
|
|
197
|
+
});
|
|
198
|
+
effect(() => {
|
|
199
|
+
const val = this.data();
|
|
200
|
+
this.onSrcChange(val);
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
onSrcChange(val) {
|
|
204
|
+
if (val !== undefined && val !== null && val.sources.length === 0) {
|
|
205
|
+
console.warn("image should have sources!");
|
|
206
|
+
this.data.set(undefined);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
// clear mediaQuery subscriptions
|
|
210
|
+
this._queryChangeClearSubject.next();
|
|
211
|
+
// ratio
|
|
212
|
+
this._ratio.set(0);
|
|
213
|
+
if (val === undefined || val.sources.length === 0) {
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
const allRatios = val.sources
|
|
217
|
+
.flatMap((x) => x.srcSet)
|
|
218
|
+
.map((x) => x.meta.ratio)
|
|
219
|
+
.filter(distinct);
|
|
220
|
+
if (allRatios.length === 1) {
|
|
221
|
+
// same ratio for all
|
|
222
|
+
this._ratio.set(allRatios[0]);
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
// todo: check if this needed to be unsubscribed
|
|
226
|
+
this.watchMediaQueries().subscribe(() => {
|
|
227
|
+
this.calcRatio();
|
|
228
|
+
console.log("watchMediaQueries calcRatio");
|
|
229
|
+
});
|
|
230
|
+
this.calcRatio();
|
|
231
|
+
}
|
|
232
|
+
calcRatio() {
|
|
233
|
+
const data = this.data();
|
|
234
|
+
if (data === undefined || data === null || data.sources.length === 0) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
for (let i = 0; i < data.sources.length; i++) {
|
|
238
|
+
const source = data.sources[i];
|
|
239
|
+
const srcRatios = source.srcSet
|
|
240
|
+
.sort(descendingT((x) => x.meta.width))
|
|
241
|
+
.map((x) => x.meta.ratio)
|
|
242
|
+
.filter(distinct);
|
|
243
|
+
if (srcRatios.length === 0) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (srcRatios.length > 1) {
|
|
247
|
+
console.warn(`each source should have srcSet with same ratio. founded: ${srcRatios.join(", ")}`);
|
|
248
|
+
}
|
|
249
|
+
const ratio = srcRatios[0]; // most accurate ratio in biggest image
|
|
250
|
+
if (source.mediaQuery.length === 0) {
|
|
251
|
+
this._ratio.set(ratio);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
if (typeof window === "undefined" || typeof window.matchMedia === "undefined") {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const mediaQueryList = window.matchMedia(source.mediaQuery);
|
|
258
|
+
if (mediaQueryList.matches) {
|
|
259
|
+
this._ratio.set(ratio);
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
watchMediaQueries() {
|
|
265
|
+
console.log("watchMediaQueries");
|
|
266
|
+
const src = this.data();
|
|
267
|
+
if (src === undefined ||
|
|
268
|
+
src === null ||
|
|
269
|
+
typeof window === "undefined" ||
|
|
270
|
+
typeof window.matchMedia === "undefined") {
|
|
271
|
+
return NEVER.pipe(takeUntilDestroyed(this._destroyRef), takeUntil(this._queryChangeClearSubject));
|
|
272
|
+
}
|
|
273
|
+
const mediaQueries = src.sources
|
|
274
|
+
.map((x) => x.mediaQuery)
|
|
275
|
+
.filter(distinct)
|
|
276
|
+
.filter((x) => x.length > 0);
|
|
277
|
+
console.log("watchMediaQueries mediaQueries", mediaQueries);
|
|
278
|
+
const queryObservables = mediaQueries.map((media) => {
|
|
279
|
+
const queryList = window.matchMedia(media);
|
|
280
|
+
const observable = fromEvent(queryList, "change").pipe(takeUntilDestroyed(this._destroyRef), takeUntil(this._queryChangeClearSubject));
|
|
281
|
+
return observable;
|
|
282
|
+
});
|
|
283
|
+
const combinedObservable = merge(...queryObservables);
|
|
284
|
+
return combinedObservable;
|
|
285
|
+
}
|
|
286
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SrcBaseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
|
|
287
|
+
static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.0.6", type: SrcBaseDirective, isStandalone: true, outputs: { ratioChange: "ratioChange" }, ngImport: i0 });
|
|
288
|
+
}
|
|
289
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SrcBaseDirective, decorators: [{
|
|
290
|
+
type: Directive
|
|
291
|
+
}], ctorParameters: () => [], propDecorators: { ratioChange: [{ type: i0.Output, args: ["ratioChange"] }] } });
|
|
7
292
|
|
|
8
293
|
/**
|
|
9
294
|
* This is a TypeGen auto-generated file.
|
|
@@ -178,348 +463,18 @@ var SizesWidthUnit;
|
|
|
178
463
|
* Any changes made to this file can be lost when this file is regenerated.
|
|
179
464
|
*/
|
|
180
465
|
|
|
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
466
|
class LocalizeServiceBase {
|
|
512
467
|
getLocalized(value, defaultValue, locale) {
|
|
513
|
-
if (value === undefined)
|
|
468
|
+
if (value === undefined) {
|
|
514
469
|
return defaultValue;
|
|
470
|
+
}
|
|
515
471
|
locale = locale ?? this.locale();
|
|
516
472
|
const obj = value[locale] ?? defaultValue;
|
|
517
473
|
return obj;
|
|
518
474
|
}
|
|
519
475
|
getLocalizedText(value, locale) {
|
|
520
|
-
return this.getLocalized(value,
|
|
476
|
+
return this.getLocalized(value, "", locale);
|
|
521
477
|
}
|
|
522
|
-
;
|
|
523
478
|
isLocalUrl(value, locale) {
|
|
524
479
|
const url = this.getLocalizedText(value, locale);
|
|
525
480
|
return isLocalUrlString(url);
|
|
@@ -527,39 +482,42 @@ class LocalizeServiceBase {
|
|
|
527
482
|
}
|
|
528
483
|
|
|
529
484
|
class LocalizePipe {
|
|
530
|
-
|
|
485
|
+
_localizeService = inject(LocalizeServiceBase);
|
|
531
486
|
transform(value, locale) {
|
|
532
|
-
if (value === undefined || value === null)
|
|
533
|
-
return
|
|
534
|
-
|
|
487
|
+
if (value === undefined || value === null) {
|
|
488
|
+
return "";
|
|
489
|
+
}
|
|
490
|
+
return this._localizeService.getLocalizedText(value, locale);
|
|
535
491
|
}
|
|
536
492
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
537
493
|
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: LocalizePipe, isStandalone: true, name: "localize", pure: false });
|
|
538
494
|
}
|
|
539
495
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizePipe, decorators: [{
|
|
540
496
|
type: Pipe,
|
|
541
|
-
args: [{ name:
|
|
497
|
+
args: [{ name: "localize", pure: false }]
|
|
542
498
|
}] });
|
|
543
499
|
class LocalizeObjectPipe {
|
|
544
|
-
|
|
500
|
+
_localizeService = inject(LocalizeServiceBase);
|
|
545
501
|
transform(object, locale) {
|
|
546
|
-
if (object === undefined || object === null)
|
|
502
|
+
if (object === undefined || object === null) {
|
|
547
503
|
return undefined;
|
|
548
|
-
|
|
504
|
+
}
|
|
505
|
+
return this._localizeService.getLocalized(object, undefined, locale);
|
|
549
506
|
}
|
|
550
507
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizeObjectPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
551
508
|
static ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "21.0.6", ngImport: i0, type: LocalizeObjectPipe, isStandalone: true, name: "localizeObject", pure: false });
|
|
552
509
|
}
|
|
553
510
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizeObjectPipe, decorators: [{
|
|
554
511
|
type: Pipe,
|
|
555
|
-
args: [{ name:
|
|
512
|
+
args: [{ name: "localizeObject", pure: false }]
|
|
556
513
|
}] });
|
|
557
514
|
class LocalizationIsNotEmptyPipe {
|
|
558
|
-
|
|
515
|
+
_localizeService = inject(LocalizeServiceBase);
|
|
559
516
|
transform(value, locale) {
|
|
560
|
-
if (value === undefined || value === null)
|
|
517
|
+
if (value === undefined || value === null) {
|
|
561
518
|
return false;
|
|
562
|
-
|
|
519
|
+
}
|
|
520
|
+
const text = this._localizeService.getLocalizedText(value, locale);
|
|
563
521
|
const isNotEmpty = text.trim().length > 0;
|
|
564
522
|
return isNotEmpty;
|
|
565
523
|
}
|
|
@@ -568,14 +526,15 @@ class LocalizationIsNotEmptyPipe {
|
|
|
568
526
|
}
|
|
569
527
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizationIsNotEmptyPipe, decorators: [{
|
|
570
528
|
type: Pipe,
|
|
571
|
-
args: [{ name:
|
|
529
|
+
args: [{ name: "localizationIsNotEmpty", pure: false }]
|
|
572
530
|
}] });
|
|
573
531
|
class LocalizationIsEmptyPipe {
|
|
574
|
-
|
|
532
|
+
_localizeService = inject(LocalizeServiceBase);
|
|
575
533
|
transform(value, locale) {
|
|
576
|
-
if (value === undefined || value === null)
|
|
534
|
+
if (value === undefined || value === null) {
|
|
577
535
|
return true;
|
|
578
|
-
|
|
536
|
+
}
|
|
537
|
+
const text = this._localizeService.getLocalizedText(value, locale);
|
|
579
538
|
const isEmpty = text.trim().length === 0;
|
|
580
539
|
return isEmpty;
|
|
581
540
|
}
|
|
@@ -584,16 +543,17 @@ class LocalizationIsEmptyPipe {
|
|
|
584
543
|
}
|
|
585
544
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizationIsEmptyPipe, decorators: [{
|
|
586
545
|
type: Pipe,
|
|
587
|
-
args: [{ name:
|
|
546
|
+
args: [{ name: "localizationIsEmpty", pure: false }]
|
|
588
547
|
}] });
|
|
589
548
|
class LocalizeUrlPipe {
|
|
590
|
-
|
|
591
|
-
|
|
549
|
+
_localizeService = inject(LocalizeServiceBase);
|
|
550
|
+
_domSanitizer = inject(DomSanitizer);
|
|
592
551
|
transform(value, locale) {
|
|
593
|
-
if (value === undefined || value === null)
|
|
594
|
-
return
|
|
595
|
-
|
|
596
|
-
const
|
|
552
|
+
if (value === undefined || value === null) {
|
|
553
|
+
return "";
|
|
554
|
+
}
|
|
555
|
+
const urlString = this._localizeService.getLocalizedText(value, locale);
|
|
556
|
+
const safeUrl = this._domSanitizer.bypassSecurityTrustResourceUrl(urlString);
|
|
597
557
|
return safeUrl;
|
|
598
558
|
}
|
|
599
559
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizeUrlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
@@ -601,14 +561,15 @@ class LocalizeUrlPipe {
|
|
|
601
561
|
}
|
|
602
562
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: LocalizeUrlPipe, decorators: [{
|
|
603
563
|
type: Pipe,
|
|
604
|
-
args: [{ name:
|
|
564
|
+
args: [{ name: "localizeUrl", pure: false }]
|
|
605
565
|
}] });
|
|
606
566
|
class IsLocalUrlPipe {
|
|
607
|
-
|
|
567
|
+
_localizeService = inject(LocalizeServiceBase);
|
|
608
568
|
transform(value, locale) {
|
|
609
|
-
if (value === undefined || value === null)
|
|
569
|
+
if (value === undefined || value === null) {
|
|
610
570
|
return false;
|
|
611
|
-
|
|
571
|
+
}
|
|
572
|
+
const isLocal = this._localizeService.isLocalUrl(value, locale);
|
|
612
573
|
return isLocal;
|
|
613
574
|
}
|
|
614
575
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IsLocalUrlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
@@ -616,14 +577,15 @@ class IsLocalUrlPipe {
|
|
|
616
577
|
}
|
|
617
578
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IsLocalUrlPipe, decorators: [{
|
|
618
579
|
type: Pipe,
|
|
619
|
-
args: [{ name:
|
|
580
|
+
args: [{ name: "isLocalUrl", pure: false }]
|
|
620
581
|
}] });
|
|
621
582
|
class IsNotLocalUrlPipe {
|
|
622
|
-
|
|
583
|
+
_localizeService = inject(LocalizeServiceBase);
|
|
623
584
|
transform(value, locale) {
|
|
624
|
-
if (value === undefined || value === null)
|
|
585
|
+
if (value === undefined || value === null) {
|
|
625
586
|
return false;
|
|
626
|
-
|
|
587
|
+
}
|
|
588
|
+
const isLocal = this._localizeService.isLocalUrl(value, locale);
|
|
627
589
|
return !isLocal;
|
|
628
590
|
}
|
|
629
591
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IsNotLocalUrlPipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe });
|
|
@@ -631,254 +593,187 @@ class IsNotLocalUrlPipe {
|
|
|
631
593
|
}
|
|
632
594
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: IsNotLocalUrlPipe, decorators: [{
|
|
633
595
|
type: Pipe,
|
|
634
|
-
args: [{ name:
|
|
596
|
+
args: [{ name: "isNotLocalUrl", pure: false }]
|
|
635
597
|
}] });
|
|
636
598
|
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
this.data = value;
|
|
599
|
+
function getDefaultSrc(image) {
|
|
600
|
+
if (image === undefined || image === null) {
|
|
601
|
+
return undefined;
|
|
641
602
|
}
|
|
603
|
+
const files = image.sources.flatMap((x) => x.srcSet).sort(descendingT((x) => x.meta.width));
|
|
604
|
+
const prefferedFiles = files.filter((x) => x.mimeType === "image/jpeg" || x.mimeType === "image/png" || x.mimeType === "image/gif");
|
|
605
|
+
if (prefferedFiles.length > 0) {
|
|
606
|
+
return prefferedFiles[0];
|
|
607
|
+
}
|
|
608
|
+
if (files.length > 0) {
|
|
609
|
+
return files[0];
|
|
610
|
+
}
|
|
611
|
+
return undefined;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
class ImageSrcDirective extends SrcBaseDirective {
|
|
615
|
+
data = model(undefined, { ...(ngDevMode ? { debugName: "data" } : {}), alias: "imgsrc" });
|
|
642
616
|
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: "
|
|
617
|
+
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
618
|
}
|
|
645
619
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ImageSrcDirective, decorators: [{
|
|
646
620
|
type: Directive,
|
|
647
621
|
args: [{
|
|
648
|
-
|
|
649
|
-
selector: '[imgsrc]',
|
|
622
|
+
selector: "[imgsrc]",
|
|
650
623
|
}]
|
|
651
|
-
}], propDecorators: { imgsrc: [
|
|
652
|
-
type: Input
|
|
653
|
-
}] } });
|
|
624
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "imgsrc", required: false }] }, { type: i0.Output, args: ["imgsrcChange"] }] } });
|
|
654
625
|
|
|
655
626
|
function toHtmlPictureSources(imageSource) {
|
|
656
627
|
const sizes = generateSizesString(imageSource.sizes);
|
|
657
|
-
const groupedByMime = groupBy(imageSource.srcSet, x => x.mimeType);
|
|
628
|
+
const groupedByMime = groupBy(imageSource.srcSet, (x) => x.mimeType);
|
|
658
629
|
const simpleSources = [];
|
|
659
630
|
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(',');
|
|
631
|
+
const fileSrcs = groupedByMime[mime].sort(ascendingT((x) => x.meta.width));
|
|
632
|
+
const srcSet = fileSrcs.map((x) => `${x.url} ${x.meta.width}w`).join(",");
|
|
664
633
|
const source = { mime, sizes, srcSet, media: imageSource.mediaQuery };
|
|
665
634
|
simpleSources.push(source);
|
|
666
635
|
}
|
|
667
636
|
return simpleSources;
|
|
668
637
|
}
|
|
669
638
|
|
|
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
639
|
class MarcyImageComponent {
|
|
687
640
|
MediaStatus = MediaStatus;
|
|
688
641
|
MarcyObjectFit = MediaObjectFit;
|
|
689
|
-
isLoaded = new EventEmitter();
|
|
690
|
-
sources = [];
|
|
691
|
-
$status = new BehaviorSubject(MediaStatus.NotSet);
|
|
692
|
-
defaultSrc = '';
|
|
693
|
-
_objectFit = MediaObjectFit.Original;
|
|
694
642
|
src;
|
|
643
|
+
isLoaded = output();
|
|
644
|
+
objectFit = input(MediaObjectFit.Original, ...(ngDevMode ? [{ debugName: "objectFit" }] : []));
|
|
645
|
+
sources = signal([], ...(ngDevMode ? [{ debugName: "sources" }] : []));
|
|
646
|
+
status = signal(MediaStatus.NotSet, ...(ngDevMode ? [{ debugName: "status" }] : []));
|
|
647
|
+
defaultSrc = signal("", ...(ngDevMode ? [{ debugName: "defaultSrc" }] : []));
|
|
695
648
|
device = inject(DeviceServiceBase);
|
|
696
|
-
cd = inject(ChangeDetectorRef);
|
|
697
|
-
_u = inject(UnsubscriberService);
|
|
698
|
-
_srcDir = inject(ImageSrcDirective, { optional: true });
|
|
699
649
|
constructor() {
|
|
700
|
-
|
|
701
|
-
if (
|
|
650
|
+
const src = inject(ImageSrcDirective, { optional: true });
|
|
651
|
+
if (src === undefined || src === null) {
|
|
702
652
|
throw new Error(`${MarcyImageComponent.name} should have [imgsrc] directive as source object`);
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
.
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
.pipe(this._u.takeUntilDestroy, filter(status => status === MediaStatus.Loaded))
|
|
714
|
-
.subscribe(x => this.isLoaded.next());
|
|
715
|
-
this.cd.detectChanges();
|
|
653
|
+
}
|
|
654
|
+
this.src = src;
|
|
655
|
+
effect(() => {
|
|
656
|
+
this.onSrcChange(this.src.data());
|
|
657
|
+
});
|
|
658
|
+
effect(() => {
|
|
659
|
+
if (this.status() === MediaStatus.Loaded) {
|
|
660
|
+
this.isLoaded.emit();
|
|
661
|
+
}
|
|
662
|
+
});
|
|
716
663
|
}
|
|
717
664
|
onSrcChange(val) {
|
|
718
|
-
|
|
719
|
-
this.defaultSrc = getDefaultSrc(val)?.url ?? '';
|
|
720
|
-
this.sources.splice(0, this.sources.length);
|
|
665
|
+
this.defaultSrc.set(getDefaultSrc(val)?.url ?? "");
|
|
721
666
|
if (val === undefined || val === null || val.sources.length === 0) {
|
|
722
|
-
this
|
|
723
|
-
this.
|
|
667
|
+
this.sources.set([]);
|
|
668
|
+
this.status.set(MediaStatus.NotSet);
|
|
724
669
|
return;
|
|
725
670
|
}
|
|
726
671
|
const newSources = val.sources.flatMap(toHtmlPictureSources);
|
|
727
|
-
|
|
728
|
-
this.
|
|
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;
|
|
672
|
+
this.sources.set(newSources);
|
|
673
|
+
this.status.set(MediaStatus.NotLoaded);
|
|
738
674
|
}
|
|
739
675
|
onLoad() {
|
|
740
|
-
this
|
|
676
|
+
this.status.set(MediaStatus.Loaded);
|
|
741
677
|
}
|
|
742
678
|
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: "
|
|
679
|
+
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
680
|
}
|
|
745
681
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MarcyImageComponent, decorators: [{
|
|
746
682
|
type: Component,
|
|
747
|
-
args: [{ selector:
|
|
748
|
-
}], ctorParameters: () => [], propDecorators: { isLoaded: [{
|
|
749
|
-
type: Output
|
|
750
|
-
}], objectFit: [{
|
|
751
|
-
type: Input
|
|
752
|
-
}] } });
|
|
683
|
+
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"] }]
|
|
684
|
+
}], ctorParameters: () => [], propDecorators: { isLoaded: [{ type: i0.Output, args: ["isLoaded"] }], objectFit: [{ type: i0.Input, args: [{ isSignal: true, alias: "objectFit", required: false }] }] } });
|
|
753
685
|
|
|
754
686
|
class VideoSrcDirective extends SrcBaseDirective {
|
|
755
|
-
|
|
756
|
-
this.data = value;
|
|
757
|
-
console.log('set vidsrc', value);
|
|
758
|
-
}
|
|
687
|
+
data = model(undefined, { ...(ngDevMode ? { debugName: "data" } : {}), alias: "vidsrc" });
|
|
759
688
|
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: "
|
|
689
|
+
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
690
|
}
|
|
762
691
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: VideoSrcDirective, decorators: [{
|
|
763
692
|
type: Directive,
|
|
764
693
|
args: [{
|
|
765
|
-
|
|
766
|
-
selector: '[vidsrc]',
|
|
694
|
+
selector: "[vidsrc]",
|
|
767
695
|
}]
|
|
768
|
-
}], propDecorators: { vidsrc: [
|
|
769
|
-
type: Input
|
|
770
|
-
}] } });
|
|
696
|
+
}], propDecorators: { data: [{ type: i0.Input, args: [{ isSignal: true, alias: "vidsrc", required: false }] }, { type: i0.Output, args: ["vidsrcChange"] }] } });
|
|
771
697
|
|
|
772
698
|
function isWebM(src) {
|
|
773
|
-
return src.mimeType ===
|
|
699
|
+
return src.mimeType === "video/webm";
|
|
774
700
|
}
|
|
775
701
|
class MarcyVideoComponent {
|
|
776
702
|
MediaStatus = MediaStatus;
|
|
777
703
|
MarcyObjectFit = MediaObjectFit;
|
|
778
|
-
videoRef;
|
|
779
|
-
isLoaded = new EventEmitter();
|
|
780
|
-
$status = signal(MediaStatus.NotSet, ...(ngDevMode ? [{ debugName: "$status" }] : []));
|
|
781
704
|
src;
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
705
|
+
isLoaded = output();
|
|
706
|
+
objectFit = input(MediaObjectFit.Original, ...(ngDevMode ? [{ debugName: "objectFit" }] : []));
|
|
707
|
+
videoRef = viewChild("video", ...(ngDevMode ? [{ debugName: "videoRef" }] : []));
|
|
708
|
+
status = signal(MediaStatus.NotSet, ...(ngDevMode ? [{ debugName: "status" }] : []));
|
|
709
|
+
source = signal(undefined, ...(ngDevMode ? [{ debugName: "source" }] : []));
|
|
785
710
|
device = inject(DeviceServiceBase);
|
|
786
|
-
cd = inject(ChangeDetectorRef);
|
|
787
|
-
_u = inject(UnsubscriberService);
|
|
788
711
|
_srcDir = inject(VideoSrcDirective, { optional: true });
|
|
789
712
|
constructor() {
|
|
790
|
-
|
|
791
|
-
if (this._srcDir === undefined || this._srcDir === null)
|
|
713
|
+
if (this._srcDir === undefined || this._srcDir === null) {
|
|
792
714
|
throw new Error(`${MarcyVideoComponent.name} should have [vidsrc] directive as source object`);
|
|
715
|
+
}
|
|
793
716
|
this.src = this._srcDir;
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
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);
|
|
717
|
+
effect(() => {
|
|
718
|
+
this.src.data();
|
|
719
|
+
this.videoRef();
|
|
813
720
|
this.updateSources();
|
|
814
|
-
// resubscribe because its updated with src
|
|
815
721
|
this.subscribeToMediaQueryChange();
|
|
816
722
|
});
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
723
|
+
effect(() => {
|
|
724
|
+
if (this.status() === MediaStatus.Loaded) {
|
|
725
|
+
this.isLoaded.emit();
|
|
726
|
+
}
|
|
727
|
+
});
|
|
820
728
|
}
|
|
821
729
|
subscribeToMediaQueryChange() {
|
|
822
|
-
this.src
|
|
823
|
-
.watchMediaQueries
|
|
824
|
-
.subscribe(() => {
|
|
825
|
-
console.log('MarcyVideoComponent watchMediaQueries');
|
|
730
|
+
this.src.watchMediaQueries().subscribe(() => {
|
|
731
|
+
console.log("MarcyVideoComponent watchMediaQueries");
|
|
826
732
|
this.updateSources();
|
|
827
733
|
});
|
|
828
734
|
}
|
|
829
735
|
updateSources() {
|
|
830
|
-
console.log(
|
|
831
|
-
this.source
|
|
832
|
-
console.log(
|
|
833
|
-
|
|
736
|
+
console.log("MarcyVideoComponent updateSources");
|
|
737
|
+
this.source.set(this.findMoreSuitableSource());
|
|
738
|
+
console.log("MarcyVideoComponent new source", this.source());
|
|
739
|
+
const src = this.source();
|
|
740
|
+
if (this.status() === MediaStatus.NotSet && src === undefined) {
|
|
834
741
|
return;
|
|
835
742
|
}
|
|
836
|
-
if (
|
|
837
|
-
this
|
|
838
|
-
this.cd.detectChanges();
|
|
743
|
+
if (src === undefined) {
|
|
744
|
+
this.status.set(MediaStatus.NotSet);
|
|
839
745
|
return;
|
|
840
746
|
}
|
|
841
|
-
this
|
|
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;
|
|
747
|
+
this.status.set(MediaStatus.NotLoaded);
|
|
850
748
|
}
|
|
851
749
|
onLoad() {
|
|
852
|
-
this
|
|
750
|
+
this.status.set(MediaStatus.Loaded);
|
|
853
751
|
}
|
|
854
752
|
findMoreSuitableSource() {
|
|
855
|
-
|
|
856
|
-
|
|
753
|
+
const ref = this.videoRef();
|
|
754
|
+
if (ref === undefined) {
|
|
755
|
+
console.log("skipping findMoreSuitableSource. videoRef is empty still");
|
|
857
756
|
return;
|
|
858
757
|
}
|
|
859
|
-
const videoSources = this.src.data?.sources ?? [];
|
|
860
|
-
const currentVideoWidth =
|
|
758
|
+
const videoSources = this.src.data()?.sources ?? [];
|
|
759
|
+
const currentVideoWidth = ref.nativeElement.clientWidth;
|
|
861
760
|
const realPixelsVideoWidth = this.device.devicePixelRatio * currentVideoWidth;
|
|
862
761
|
console.log(`MarcyVideoComponent currentVideoWidth ${currentVideoWidth}`);
|
|
863
762
|
console.log(`MarcyVideoComponent realPixelsVideoWidth ${realPixelsVideoWidth}`);
|
|
864
763
|
for (let i = 0; i < videoSources.length; i++) {
|
|
865
764
|
const videoSource = videoSources[i];
|
|
866
|
-
if (!matchesMediaQuery(videoSource.mediaQuery))
|
|
765
|
+
if (!matchesMediaQuery(videoSource.mediaQuery)) {
|
|
867
766
|
continue;
|
|
767
|
+
}
|
|
868
768
|
// SSR
|
|
869
|
-
if (typeof
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
.
|
|
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
|
|
769
|
+
if (typeof ref.nativeElement.canPlayType !== "function") {
|
|
770
|
+
const mp4Srcs = videoSource.srcSet
|
|
771
|
+
.filter((x) => x.mimeType === "video/mp4")
|
|
772
|
+
.sort(descendingT((x) => x.meta.width));
|
|
877
773
|
return mp4Srcs[0];
|
|
878
774
|
}
|
|
879
|
-
const fileSrcs = videoSource
|
|
880
|
-
.
|
|
881
|
-
.filter(x => this.videoRef.nativeElement.canPlayType(x.mimeType))
|
|
775
|
+
const fileSrcs = videoSource.srcSet
|
|
776
|
+
.filter((x) => ref.nativeElement.canPlayType(x.mimeType))
|
|
882
777
|
.sort((a, b) => {
|
|
883
778
|
if (a.meta.width === b.meta.width) {
|
|
884
779
|
return isWebM(a) ? -1 : 1; // if same width prefer webM
|
|
@@ -886,8 +781,9 @@ class MarcyVideoComponent {
|
|
|
886
781
|
// else prefer smallest
|
|
887
782
|
return a.meta.width <= b.meta.width ? -1 : 1;
|
|
888
783
|
}); // smallest video
|
|
889
|
-
if (fileSrcs.length === 0)
|
|
784
|
+
if (fileSrcs.length === 0) {
|
|
890
785
|
continue;
|
|
786
|
+
}
|
|
891
787
|
// console.log('sources ', fileSrcs);
|
|
892
788
|
let bestSrc = fileSrcs[0];
|
|
893
789
|
for (let i = 1; i < fileSrcs.length; i++) {
|
|
@@ -895,8 +791,9 @@ class MarcyVideoComponent {
|
|
|
895
791
|
const currentDiff = fileSrc.meta.width - realPixelsVideoWidth;
|
|
896
792
|
// console.log(`browser video currentDiff ${currentDiff}`)
|
|
897
793
|
// too big video source width
|
|
898
|
-
if (currentDiff > 0)
|
|
794
|
+
if (currentDiff > 0) {
|
|
899
795
|
break;
|
|
796
|
+
}
|
|
900
797
|
bestSrc = fileSrc;
|
|
901
798
|
}
|
|
902
799
|
console.log(`browser found suitable video ${bestSrc.url}`);
|
|
@@ -904,111 +801,56 @@ class MarcyVideoComponent {
|
|
|
904
801
|
}
|
|
905
802
|
return undefined;
|
|
906
803
|
}
|
|
907
|
-
ngOnDestroy() {
|
|
908
|
-
this._effectCleanup?.destroy();
|
|
909
|
-
}
|
|
910
804
|
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: "
|
|
805
|
+
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
806
|
}
|
|
913
807
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MarcyVideoComponent, decorators: [{
|
|
914
808
|
type: Component,
|
|
915
|
-
args: [{ selector:
|
|
916
|
-
}], ctorParameters: () => [], propDecorators: { videoRef: [{
|
|
917
|
-
type: ViewChild,
|
|
918
|
-
args: ['video']
|
|
919
|
-
}], isLoaded: [{
|
|
920
|
-
type: Output
|
|
921
|
-
}], objectFit: [{
|
|
922
|
-
type: Input
|
|
923
|
-
}] } });
|
|
809
|
+
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"] }]
|
|
810
|
+
}], 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
811
|
|
|
925
812
|
class MarcyMediaComponent {
|
|
926
|
-
cd = inject(ChangeDetectorRef);
|
|
927
813
|
MarcyObjectFit = MediaObjectFit;
|
|
928
|
-
isLoaded =
|
|
929
|
-
|
|
930
|
-
|
|
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
|
-
}
|
|
814
|
+
isLoaded = output();
|
|
815
|
+
src = input(...(ngDevMode ? [undefined, { debugName: "src" }] : []));
|
|
816
|
+
objectFit = input(MediaObjectFit.Original, ...(ngDevMode ? [{ debugName: "objectFit" }] : []));
|
|
955
817
|
onLoad() {
|
|
956
|
-
this.isLoaded.
|
|
818
|
+
this.isLoaded.emit();
|
|
957
819
|
}
|
|
958
820
|
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: "
|
|
821
|
+
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
822
|
}
|
|
961
823
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: MarcyMediaComponent, decorators: [{
|
|
962
824
|
type: Component,
|
|
963
|
-
args: [{ selector:
|
|
964
|
-
}],
|
|
965
|
-
type: Output
|
|
966
|
-
}], src: [{
|
|
967
|
-
type: Input
|
|
968
|
-
}], objectFit: [{
|
|
969
|
-
type: Input
|
|
970
|
-
}] } });
|
|
825
|
+
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"] }]
|
|
826
|
+
}], 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
827
|
|
|
972
|
-
class
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
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();
|
|
828
|
+
class BoneMap extends Map {
|
|
829
|
+
getRequired(key) {
|
|
830
|
+
const value = this.get(key);
|
|
831
|
+
if (value === undefined || value === null) {
|
|
832
|
+
throw new Error(`BoneMap doesn't contain type for key = ${key}`);
|
|
833
|
+
}
|
|
834
|
+
return value;
|
|
1001
835
|
}
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
class BoneDirective {
|
|
839
|
+
bone = model.required(...(ngDevMode ? [{ debugName: "bone" }] : []));
|
|
1002
840
|
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: "
|
|
841
|
+
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
842
|
}
|
|
1005
843
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: BoneDirective, decorators: [{
|
|
1006
844
|
type: Directive,
|
|
1007
845
|
args: [{
|
|
1008
|
-
selector:
|
|
1009
|
-
standalone: true
|
|
846
|
+
selector: "[bonBoneDir]",
|
|
1010
847
|
}]
|
|
1011
|
-
}],
|
|
848
|
+
}], propDecorators: { bone: [{ type: i0.Input, args: [{ isSignal: true, alias: "bone", required: true }] }, { type: i0.Output, args: ["boneChange"] }] } });
|
|
849
|
+
const BONE_DIRECTIVE_WITH_INPUTS_AND_OUTPUTS = {
|
|
850
|
+
directive: BoneDirective,
|
|
851
|
+
inputs: ["bone"],
|
|
852
|
+
outputs: ["boneChange"],
|
|
853
|
+
};
|
|
1012
854
|
|
|
1013
855
|
class SkeletonAnchorDirective {
|
|
1014
856
|
viewContainerRef = inject(ViewContainerRef);
|
|
@@ -1018,92 +860,65 @@ class SkeletonAnchorDirective {
|
|
|
1018
860
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SkeletonAnchorDirective, decorators: [{
|
|
1019
861
|
type: Directive,
|
|
1020
862
|
args: [{
|
|
1021
|
-
selector:
|
|
1022
|
-
standalone: true
|
|
863
|
+
selector: "[bonSkeletonAnchor]",
|
|
1023
864
|
}]
|
|
1024
865
|
}] });
|
|
1025
866
|
|
|
1026
867
|
class UnknownBoneComponent {
|
|
1027
|
-
cd = inject(ChangeDetectorRef);
|
|
1028
868
|
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
869
|
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: "
|
|
1038
|
-
|
|
870
|
+
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) {
|
|
871
|
+
<h2>unknown bone {{bone.type}}</h2>
|
|
872
|
+
<div>{{bone | json}}</div>
|
|
873
|
+
} @else{
|
|
874
|
+
bone is undefined
|
|
875
|
+
}`, isInline: true, styles: [":host{display:block;border:2px solid red;box-sizing:border-box}\n"], dependencies: [{ kind: "pipe", type: JsonPipe, name: "json" }] });
|
|
1039
876
|
}
|
|
1040
877
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: UnknownBoneComponent, decorators: [{
|
|
1041
878
|
type: Component,
|
|
1042
|
-
args: [{ selector:
|
|
1043
|
-
|
|
1044
|
-
|
|
879
|
+
args: [{ selector: "bon-unknown-bone", imports: [JsonPipe], hostDirectives: [{ directive: BoneDirective, inputs: ["bone"], outputs: ["boneChange"] }], template: `@if (bd.bone(); as bone) {
|
|
880
|
+
<h2>unknown bone {{bone.type}}</h2>
|
|
881
|
+
<div>{{bone | json}}</div>
|
|
882
|
+
} @else{
|
|
883
|
+
bone is undefined
|
|
884
|
+
}`, styles: [":host{display:block;border:2px solid red;box-sizing:border-box}\n"] }]
|
|
885
|
+
}] });
|
|
1045
886
|
|
|
1046
887
|
class SkeletonComponent {
|
|
1047
|
-
skeletonAnchor;
|
|
1048
|
-
map;
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
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;
|
|
888
|
+
skeletonAnchor = viewChild.required(SkeletonAnchorDirective);
|
|
889
|
+
map = input.required(...(ngDevMode ? [{ debugName: "map" }] : []));
|
|
890
|
+
bones = input.required(...(ngDevMode ? [{ debugName: "bones" }] : []));
|
|
891
|
+
constructor() {
|
|
892
|
+
effect(() => {
|
|
893
|
+
const anchor = this.skeletonAnchor();
|
|
894
|
+
const bones = this.bones();
|
|
895
|
+
const mapVal = this.map();
|
|
896
|
+
const viewContainerRef = anchor.viewContainerRef;
|
|
897
|
+
viewContainerRef.clear();
|
|
898
|
+
if (mapVal === undefined || mapVal === null) {
|
|
899
|
+
throw new Error('add type map with input: [map]="..."');
|
|
1073
900
|
}
|
|
1074
|
-
const
|
|
1075
|
-
|
|
1076
|
-
|
|
901
|
+
for (const bone of bones) {
|
|
902
|
+
let componentType = mapVal.get(bone.type);
|
|
903
|
+
if (componentType === undefined || componentType === null) {
|
|
904
|
+
console.warn(`Mapping type for ${bone.type} not found`);
|
|
905
|
+
componentType = UnknownBoneComponent;
|
|
906
|
+
}
|
|
907
|
+
viewContainerRef.createComponent(componentType).setInput("bone", bone);
|
|
908
|
+
}
|
|
909
|
+
});
|
|
1077
910
|
}
|
|
1078
911
|
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: "
|
|
912
|
+
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
913
|
}
|
|
1081
914
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: SkeletonComponent, decorators: [{
|
|
1082
915
|
type: Component,
|
|
1083
|
-
args: [{ selector:
|
|
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
|
-
}
|
|
916
|
+
args: [{ selector: "bon-skeleton", imports: [SkeletonAnchorDirective], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template bonSkeletonAnchor></ng-template>\n", styles: [":host{display:block}\n"] }]
|
|
917
|
+
}], 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
918
|
|
|
1104
919
|
/**
|
|
1105
920
|
* Generated bundle index. Do not edit.
|
|
1106
921
|
*/
|
|
1107
922
|
|
|
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,
|
|
923
|
+
export { BONE_DIRECTIVE_WITH_INPUTS_AND_OUTPUTS, 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
924
|
//# sourceMappingURL=candy-kingdom-bonnie.mjs.map
|