@progress/kendo-angular-utils 19.0.0-develop.9 → 19.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adaptive-breakpoints/adaptive.service.d.ts +10 -3
- package/drag-and-drop/dragtarget.directive.d.ts +1 -0
- package/esm2022/adaptive-breakpoints/adaptive.service.mjs +26 -6
- package/esm2022/drag-and-drop/dragtarget.directive.mjs +9 -3
- package/esm2022/package-metadata.mjs +2 -2
- package/fesm2022/progress-kendo-angular-utils.mjs +36 -10
- package/package.json +4 -4
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Copyright © 2025 Progress Software Corporation. All rights reserved.
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { OnDestroy } from '@angular/core';
|
|
5
|
+
import { NgZone, OnDestroy } from '@angular/core';
|
|
6
6
|
import { Subject } from 'rxjs';
|
|
7
7
|
import { AdaptiveSettings } from './models/adaptive-settings';
|
|
8
8
|
import { AdaptiveSettingsService } from './adaptive-settings.service';
|
|
@@ -30,13 +30,20 @@ import * as i0 from "@angular/core";
|
|
|
30
30
|
*/
|
|
31
31
|
export declare class AdaptiveService implements OnDestroy {
|
|
32
32
|
private _adaptiveSettings;
|
|
33
|
+
private zone;
|
|
33
34
|
/**
|
|
34
35
|
* Notifies subscribers of the initial adaptive settings, and upon each call to `notify`.
|
|
35
36
|
* @hidden
|
|
36
37
|
*/
|
|
37
38
|
readonly changes: Subject<AdaptiveSettings>;
|
|
39
|
+
/**
|
|
40
|
+
* Notifies subscribers when the window size changes to any of small, medium, or large depending on the set adaptive size breakpoints.
|
|
41
|
+
* @hidden
|
|
42
|
+
*/
|
|
43
|
+
readonly sizeChanges: Subject<AdaptiveSize>;
|
|
38
44
|
private subs;
|
|
39
|
-
|
|
45
|
+
private previousSize;
|
|
46
|
+
constructor(_adaptiveSettings: AdaptiveSettings, adaptiveSettingsService: AdaptiveSettingsService, zone: NgZone);
|
|
40
47
|
/**
|
|
41
48
|
* @hidden
|
|
42
49
|
*/
|
|
@@ -46,6 +53,6 @@ export declare class AdaptiveService implements OnDestroy {
|
|
|
46
53
|
*/
|
|
47
54
|
get size(): AdaptiveSize;
|
|
48
55
|
ngOnDestroy(): void;
|
|
49
|
-
static ɵfac: i0.ɵɵFactoryDeclaration<AdaptiveService, [{ optional: true; }, { optional: true; }]>;
|
|
56
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AdaptiveService, [{ optional: true; }, { optional: true; }, null]>;
|
|
50
57
|
static ɵprov: i0.ɵɵInjectableDeclaration<AdaptiveService>;
|
|
51
58
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Copyright © 2025 Progress Software Corporation. All rights reserved.
|
|
3
3
|
* Licensed under commercial license. See LICENSE.md in the project root for more information
|
|
4
4
|
*-------------------------------------------------------------------------------------------*/
|
|
5
|
-
import { Inject, Injectable, Optional } from '@angular/core';
|
|
6
|
-
import { BehaviorSubject, Subscription } from 'rxjs';
|
|
7
|
-
import { map, tap } from 'rxjs/operators';
|
|
5
|
+
import { Inject, Injectable, NgZone, Optional } from '@angular/core';
|
|
6
|
+
import { BehaviorSubject, fromEvent, Subscription } from 'rxjs';
|
|
7
|
+
import { filter, map, tap } from 'rxjs/operators';
|
|
8
8
|
import { AdaptiveSettingsService } from './adaptive-settings.service';
|
|
9
9
|
import { ADAPTIVE_SETTINGS } from './adaptive-settings';
|
|
10
10
|
import { areObjectsEqual, isDocumentAvailable, isPresent } from '@progress/kendo-angular-common';
|
|
@@ -36,14 +36,22 @@ const DEFAULT_ADAPTIVE_SETTINGS = {
|
|
|
36
36
|
*/
|
|
37
37
|
export class AdaptiveService {
|
|
38
38
|
_adaptiveSettings;
|
|
39
|
+
zone;
|
|
39
40
|
/**
|
|
40
41
|
* Notifies subscribers of the initial adaptive settings, and upon each call to `notify`.
|
|
41
42
|
* @hidden
|
|
42
43
|
*/
|
|
43
44
|
changes = new BehaviorSubject(this.adaptiveSettings || { small: 500, medium: 700 });
|
|
45
|
+
/**
|
|
46
|
+
* Notifies subscribers when the window size changes to any of small, medium, or large depending on the set adaptive size breakpoints.
|
|
47
|
+
* @hidden
|
|
48
|
+
*/
|
|
49
|
+
sizeChanges = new BehaviorSubject(this.size);
|
|
44
50
|
subs = new Subscription();
|
|
45
|
-
|
|
51
|
+
previousSize;
|
|
52
|
+
constructor(_adaptiveSettings, adaptiveSettingsService, zone) {
|
|
46
53
|
this._adaptiveSettings = _adaptiveSettings;
|
|
54
|
+
this.zone = zone;
|
|
47
55
|
if (adaptiveSettingsService) {
|
|
48
56
|
this.subs.add(adaptiveSettingsService.changes
|
|
49
57
|
.pipe(map(adaptiveSettings => isPresent(adaptiveSettings) ? adaptiveSettings : this._adaptiveSettings), tap(adaptiveSettings => this._adaptiveSettings = adaptiveSettings))
|
|
@@ -52,6 +60,18 @@ export class AdaptiveService {
|
|
|
52
60
|
if (isPresent(this.adaptiveSettings) && !areObjectsEqual(this.adaptiveSettings, DEFAULT_ADAPTIVE_SETTINGS)) {
|
|
53
61
|
this.changes.next(this.adaptiveSettings);
|
|
54
62
|
}
|
|
63
|
+
if (isDocumentAvailable()) {
|
|
64
|
+
this.zone.runOutsideAngular(() => {
|
|
65
|
+
this.subs.add(fromEvent(window, 'resize')
|
|
66
|
+
.pipe(tap(() => !this.previousSize && (this.previousSize = this.size)), filter(() => this.previousSize !== this.size))
|
|
67
|
+
.subscribe(() => {
|
|
68
|
+
this.previousSize = this.size;
|
|
69
|
+
this.zone.run(() => {
|
|
70
|
+
this.sizeChanges.next(this.size);
|
|
71
|
+
});
|
|
72
|
+
}));
|
|
73
|
+
});
|
|
74
|
+
}
|
|
55
75
|
}
|
|
56
76
|
/**
|
|
57
77
|
* @hidden
|
|
@@ -80,7 +100,7 @@ export class AdaptiveService {
|
|
|
80
100
|
ngOnDestroy() {
|
|
81
101
|
this.subs.unsubscribe();
|
|
82
102
|
}
|
|
83
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveService, deps: [{ token: ADAPTIVE_SETTINGS, optional: true }, { token: i1.AdaptiveSettingsService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
103
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveService, deps: [{ token: ADAPTIVE_SETTINGS, optional: true }, { token: i1.AdaptiveSettingsService, optional: true }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
84
104
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveService, providedIn: 'root' });
|
|
85
105
|
}
|
|
86
106
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveService, decorators: [{
|
|
@@ -95,4 +115,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
95
115
|
args: [ADAPTIVE_SETTINGS]
|
|
96
116
|
}] }, { type: i1.AdaptiveSettingsService, decorators: [{
|
|
97
117
|
type: Optional
|
|
98
|
-
}] }]; } });
|
|
118
|
+
}] }, { type: i0.NgZone }]; } });
|
|
@@ -116,6 +116,7 @@ export class DragTargetDirective {
|
|
|
116
116
|
hintComponent = null;
|
|
117
117
|
dragStarted = false;
|
|
118
118
|
pressed = false;
|
|
119
|
+
dragReady = false;
|
|
119
120
|
dragTimeout = null;
|
|
120
121
|
initialPosition = { x: 0, y: 0 };
|
|
121
122
|
position = { x: 0, y: 0 };
|
|
@@ -202,14 +203,15 @@ export class DragTargetDirective {
|
|
|
202
203
|
this.service.dragTargets.splice(currentDragTargetIndex, 1);
|
|
203
204
|
}
|
|
204
205
|
handlePress(event) {
|
|
206
|
+
this.pressed = true;
|
|
205
207
|
if (this.dragDelay > 0) {
|
|
206
208
|
this.dragTimeout = window.setTimeout(() => {
|
|
207
|
-
this.
|
|
209
|
+
this.dragReady = true;
|
|
208
210
|
this.emitZoneAwareEvent('onDragReady', event);
|
|
209
211
|
}, this.dragDelay);
|
|
210
212
|
}
|
|
211
213
|
else {
|
|
212
|
-
this.
|
|
214
|
+
this.dragReady = true;
|
|
213
215
|
}
|
|
214
216
|
this.scrollableParent = this.dragTarget.element ? getScrollableParent(this.dragTarget.element) : null;
|
|
215
217
|
this.prevUserSelect = this.dragTarget.element.style.userSelect;
|
|
@@ -224,6 +226,9 @@ export class DragTargetDirective {
|
|
|
224
226
|
}
|
|
225
227
|
return;
|
|
226
228
|
}
|
|
229
|
+
if (!this.dragReady) {
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
227
232
|
isDragStartPrevented = this.emitZoneAwareEvent('onDragStart', event).isDefaultPrevented();
|
|
228
233
|
if (isDragStartPrevented) {
|
|
229
234
|
return;
|
|
@@ -244,7 +249,7 @@ export class DragTargetDirective {
|
|
|
244
249
|
this.service.dragData = this.dragData({ dragTarget: this.dragTarget.element, dragTargetId: this.dragTargetIdResult, dragTargetIndex: null });
|
|
245
250
|
}
|
|
246
251
|
handleDrag(event) {
|
|
247
|
-
if (!this.pressed || isDragStartPrevented) {
|
|
252
|
+
if (!this.pressed || !this.dragReady || isDragStartPrevented) {
|
|
248
253
|
return;
|
|
249
254
|
}
|
|
250
255
|
const elem = this.hint ? this.hintElem : this.nativeElement;
|
|
@@ -273,6 +278,7 @@ export class DragTargetDirective {
|
|
|
273
278
|
this.dragTimeout = null;
|
|
274
279
|
}
|
|
275
280
|
this.pressed = false;
|
|
281
|
+
this.dragReady = false;
|
|
276
282
|
this.prevUserSelect ? this.renderer.setStyle(this.dragTarget.element, 'user-select', this.prevUserSelect) :
|
|
277
283
|
this.renderer.removeStyle(this.dragTarget.element, 'user-select');
|
|
278
284
|
this.prevUserSelect = null;
|
|
@@ -10,7 +10,7 @@ export const packageMetadata = {
|
|
|
10
10
|
productName: 'Kendo UI for Angular',
|
|
11
11
|
productCode: 'KENDOUIANGULAR',
|
|
12
12
|
productCodes: ['KENDOUIANGULAR'],
|
|
13
|
-
publishDate:
|
|
14
|
-
version: '19.0.0
|
|
13
|
+
publishDate: 1748362261,
|
|
14
|
+
version: '19.0.0',
|
|
15
15
|
licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
|
|
16
16
|
};
|
|
@@ -8,8 +8,8 @@ import { validatePackage } from '@progress/kendo-licensing';
|
|
|
8
8
|
import { dispatchDragAndDrop, getScrollableParent, autoScroll } from '@progress/kendo-draggable-common';
|
|
9
9
|
import { PreventableEvent, contains, isDocumentAvailable, parseCSSClassNames, isPresent as isPresent$1, areObjectsEqual } from '@progress/kendo-angular-common';
|
|
10
10
|
import { NgTemplateOutlet } from '@angular/common';
|
|
11
|
-
import { Subject, BehaviorSubject, Subscription } from 'rxjs';
|
|
12
|
-
import { map, tap } from 'rxjs/operators';
|
|
11
|
+
import { Subject, BehaviorSubject, Subscription, fromEvent } from 'rxjs';
|
|
12
|
+
import { map, tap, filter } from 'rxjs/operators';
|
|
13
13
|
|
|
14
14
|
/**
|
|
15
15
|
* Represents the Kendo UI DragHandle directive for Angular.
|
|
@@ -55,8 +55,8 @@ const packageMetadata = {
|
|
|
55
55
|
productName: 'Kendo UI for Angular',
|
|
56
56
|
productCode: 'KENDOUIANGULAR',
|
|
57
57
|
productCodes: ['KENDOUIANGULAR'],
|
|
58
|
-
publishDate:
|
|
59
|
-
version: '19.0.0
|
|
58
|
+
publishDate: 1748362261,
|
|
59
|
+
version: '19.0.0',
|
|
60
60
|
licensingDocsUrl: 'https://www.telerik.com/kendo-angular-ui/my-license/'
|
|
61
61
|
};
|
|
62
62
|
|
|
@@ -1367,6 +1367,7 @@ class DragTargetDirective {
|
|
|
1367
1367
|
hintComponent = null;
|
|
1368
1368
|
dragStarted = false;
|
|
1369
1369
|
pressed = false;
|
|
1370
|
+
dragReady = false;
|
|
1370
1371
|
dragTimeout = null;
|
|
1371
1372
|
initialPosition = { x: 0, y: 0 };
|
|
1372
1373
|
position = { x: 0, y: 0 };
|
|
@@ -1453,14 +1454,15 @@ class DragTargetDirective {
|
|
|
1453
1454
|
this.service.dragTargets.splice(currentDragTargetIndex, 1);
|
|
1454
1455
|
}
|
|
1455
1456
|
handlePress(event) {
|
|
1457
|
+
this.pressed = true;
|
|
1456
1458
|
if (this.dragDelay > 0) {
|
|
1457
1459
|
this.dragTimeout = window.setTimeout(() => {
|
|
1458
|
-
this.
|
|
1460
|
+
this.dragReady = true;
|
|
1459
1461
|
this.emitZoneAwareEvent('onDragReady', event);
|
|
1460
1462
|
}, this.dragDelay);
|
|
1461
1463
|
}
|
|
1462
1464
|
else {
|
|
1463
|
-
this.
|
|
1465
|
+
this.dragReady = true;
|
|
1464
1466
|
}
|
|
1465
1467
|
this.scrollableParent = this.dragTarget.element ? getScrollableParent(this.dragTarget.element) : null;
|
|
1466
1468
|
this.prevUserSelect = this.dragTarget.element.style.userSelect;
|
|
@@ -1475,6 +1477,9 @@ class DragTargetDirective {
|
|
|
1475
1477
|
}
|
|
1476
1478
|
return;
|
|
1477
1479
|
}
|
|
1480
|
+
if (!this.dragReady) {
|
|
1481
|
+
return;
|
|
1482
|
+
}
|
|
1478
1483
|
isDragStartPrevented = this.emitZoneAwareEvent('onDragStart', event).isDefaultPrevented();
|
|
1479
1484
|
if (isDragStartPrevented) {
|
|
1480
1485
|
return;
|
|
@@ -1495,7 +1500,7 @@ class DragTargetDirective {
|
|
|
1495
1500
|
this.service.dragData = this.dragData({ dragTarget: this.dragTarget.element, dragTargetId: this.dragTargetIdResult, dragTargetIndex: null });
|
|
1496
1501
|
}
|
|
1497
1502
|
handleDrag(event) {
|
|
1498
|
-
if (!this.pressed || isDragStartPrevented) {
|
|
1503
|
+
if (!this.pressed || !this.dragReady || isDragStartPrevented) {
|
|
1499
1504
|
return;
|
|
1500
1505
|
}
|
|
1501
1506
|
const elem = this.hint ? this.hintElem : this.nativeElement;
|
|
@@ -1524,6 +1529,7 @@ class DragTargetDirective {
|
|
|
1524
1529
|
this.dragTimeout = null;
|
|
1525
1530
|
}
|
|
1526
1531
|
this.pressed = false;
|
|
1532
|
+
this.dragReady = false;
|
|
1527
1533
|
this.prevUserSelect ? this.renderer.setStyle(this.dragTarget.element, 'user-select', this.prevUserSelect) :
|
|
1528
1534
|
this.renderer.removeStyle(this.dragTarget.element, 'user-select');
|
|
1529
1535
|
this.prevUserSelect = null;
|
|
@@ -2400,14 +2406,22 @@ const DEFAULT_ADAPTIVE_SETTINGS = {
|
|
|
2400
2406
|
*/
|
|
2401
2407
|
class AdaptiveService {
|
|
2402
2408
|
_adaptiveSettings;
|
|
2409
|
+
zone;
|
|
2403
2410
|
/**
|
|
2404
2411
|
* Notifies subscribers of the initial adaptive settings, and upon each call to `notify`.
|
|
2405
2412
|
* @hidden
|
|
2406
2413
|
*/
|
|
2407
2414
|
changes = new BehaviorSubject(this.adaptiveSettings || { small: 500, medium: 700 });
|
|
2415
|
+
/**
|
|
2416
|
+
* Notifies subscribers when the window size changes to any of small, medium, or large depending on the set adaptive size breakpoints.
|
|
2417
|
+
* @hidden
|
|
2418
|
+
*/
|
|
2419
|
+
sizeChanges = new BehaviorSubject(this.size);
|
|
2408
2420
|
subs = new Subscription();
|
|
2409
|
-
|
|
2421
|
+
previousSize;
|
|
2422
|
+
constructor(_adaptiveSettings, adaptiveSettingsService, zone) {
|
|
2410
2423
|
this._adaptiveSettings = _adaptiveSettings;
|
|
2424
|
+
this.zone = zone;
|
|
2411
2425
|
if (adaptiveSettingsService) {
|
|
2412
2426
|
this.subs.add(adaptiveSettingsService.changes
|
|
2413
2427
|
.pipe(map(adaptiveSettings => isPresent$1(adaptiveSettings) ? adaptiveSettings : this._adaptiveSettings), tap(adaptiveSettings => this._adaptiveSettings = adaptiveSettings))
|
|
@@ -2416,6 +2430,18 @@ class AdaptiveService {
|
|
|
2416
2430
|
if (isPresent$1(this.adaptiveSettings) && !areObjectsEqual(this.adaptiveSettings, DEFAULT_ADAPTIVE_SETTINGS)) {
|
|
2417
2431
|
this.changes.next(this.adaptiveSettings);
|
|
2418
2432
|
}
|
|
2433
|
+
if (isDocumentAvailable()) {
|
|
2434
|
+
this.zone.runOutsideAngular(() => {
|
|
2435
|
+
this.subs.add(fromEvent(window, 'resize')
|
|
2436
|
+
.pipe(tap(() => !this.previousSize && (this.previousSize = this.size)), filter(() => this.previousSize !== this.size))
|
|
2437
|
+
.subscribe(() => {
|
|
2438
|
+
this.previousSize = this.size;
|
|
2439
|
+
this.zone.run(() => {
|
|
2440
|
+
this.sizeChanges.next(this.size);
|
|
2441
|
+
});
|
|
2442
|
+
}));
|
|
2443
|
+
});
|
|
2444
|
+
}
|
|
2419
2445
|
}
|
|
2420
2446
|
/**
|
|
2421
2447
|
* @hidden
|
|
@@ -2444,7 +2470,7 @@ class AdaptiveService {
|
|
|
2444
2470
|
ngOnDestroy() {
|
|
2445
2471
|
this.subs.unsubscribe();
|
|
2446
2472
|
}
|
|
2447
|
-
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveService, deps: [{ token: ADAPTIVE_SETTINGS, optional: true }, { token: AdaptiveSettingsService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2473
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveService, deps: [{ token: ADAPTIVE_SETTINGS, optional: true }, { token: AdaptiveSettingsService, optional: true }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
2448
2474
|
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveService, providedIn: 'root' });
|
|
2449
2475
|
}
|
|
2450
2476
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AdaptiveService, decorators: [{
|
|
@@ -2459,7 +2485,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImpo
|
|
|
2459
2485
|
args: [ADAPTIVE_SETTINGS]
|
|
2460
2486
|
}] }, { type: AdaptiveSettingsService, decorators: [{
|
|
2461
2487
|
type: Optional
|
|
2462
|
-
}] }]; } });
|
|
2488
|
+
}] }, { type: i0.NgZone }]; } });
|
|
2463
2489
|
|
|
2464
2490
|
/**
|
|
2465
2491
|
* Generated bundle index. Do not edit.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@progress/kendo-angular-utils",
|
|
3
|
-
"version": "19.0.0
|
|
3
|
+
"version": "19.0.0",
|
|
4
4
|
"description": "Kendo UI Angular utils component",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"author": "Progress",
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"package": {
|
|
20
20
|
"productName": "Kendo UI for Angular",
|
|
21
21
|
"productCode": "KENDOUIANGULAR",
|
|
22
|
-
"publishDate":
|
|
22
|
+
"publishDate": 1748362261,
|
|
23
23
|
"licensingDocsUrl": "https://www.telerik.com/kendo-angular-ui/my-license/"
|
|
24
24
|
}
|
|
25
25
|
},
|
|
@@ -29,12 +29,12 @@
|
|
|
29
29
|
"@angular/core": "16 - 19",
|
|
30
30
|
"@angular/platform-browser": "16 - 19",
|
|
31
31
|
"@progress/kendo-licensing": "^1.5.0",
|
|
32
|
-
"@progress/kendo-angular-common": "19.0.0
|
|
32
|
+
"@progress/kendo-angular-common": "19.0.0",
|
|
33
33
|
"rxjs": "^6.5.3 || ^7.0.0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"tslib": "^2.3.1",
|
|
37
|
-
"@progress/kendo-angular-schematics": "19.0.0
|
|
37
|
+
"@progress/kendo-angular-schematics": "19.0.0",
|
|
38
38
|
"@progress/kendo-draggable-common": "^0.2.3"
|
|
39
39
|
},
|
|
40
40
|
"schematics": "./schematics/collection.json",
|