@sapphire-ion/framework 1.0.35 → 1.0.36
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/esm2022/lib/components/inputs/inputs.module.mjs +8 -4
- package/esm2022/lib/components/popover/sion-popover/sion-popover.component.mjs +11 -40
- package/esm2022/lib/components/popover/sion-popover.module.mjs +5 -4
- package/esm2022/lib/core.module.mjs +12 -7
- package/esm2022/lib/services/modal-focus-trap.service.mjs +58 -0
- package/fesm2022/sapphire-ion-framework.mjs +85 -51
- package/fesm2022/sapphire-ion-framework.mjs.map +1 -1
- package/lib/components/inputs/inputs.module.d.ts +2 -1
- package/lib/components/popover/sion-popover/sion-popover.component.d.ts +4 -9
- package/lib/components/popover/sion-popover.module.d.ts +2 -1
- package/lib/core.module.d.ts +3 -0
- package/lib/services/modal-focus-trap.service.d.ts +9 -0
- package/package.json +1 -1
- package/themes/components/popover/sion-popover/sion-popover.component.scss +5 -3
- package/themes/styles/core.styles.scss +2 -1
- package/themes/styles/ionic/ion-modal.scss +1 -1
|
@@ -3,7 +3,7 @@ import { NavController, IonicModule, IonDatetime, IonModal, IonBackButton, IonCh
|
|
|
3
3
|
import { FilePicker } from '@capawesome/capacitor-file-picker';
|
|
4
4
|
import { CameraSource } from '@capacitor/camera';
|
|
5
5
|
import * as i0 from '@angular/core';
|
|
6
|
-
import { Injectable, InjectionToken, NgModule, Inject, inject, signal, model, Component, Input, Pipe, input, computed, effect, contentChildren, output, forwardRef, ContentChildren, EventEmitter, Output, HostListener, ViewChild, Directive, TemplateRef, ContentChild,
|
|
6
|
+
import { Injectable, InjectionToken, NgModule, Inject, inject, signal, model, Component, Input, Pipe, input, computed, effect, contentChildren, output, forwardRef, ContentChildren, EventEmitter, Output, HostListener, ViewChild, Directive, ElementRef, TemplateRef, ContentChild, ViewChildren, HostBinding, ViewContainerRef } from '@angular/core';
|
|
7
7
|
import moment from 'moment';
|
|
8
8
|
import { BehaviorSubject, firstValueFrom, from, switchMap, Subject, takeUntil, distinctUntilChanged, debounceTime, lastValueFrom, Observable, tap, finalize, share, catchError } from 'rxjs';
|
|
9
9
|
import * as i1 from '@angular/common/http';
|
|
@@ -25,6 +25,7 @@ import { MaskitoDirective } from '@maskito/angular';
|
|
|
25
25
|
import { maskitoDateTimeOptionsGenerator, maskitoDateOptionsGenerator, maskitoTimeOptionsGenerator } from '@maskito/kit';
|
|
26
26
|
import { autoUpdate, computePosition, offset, flip, shift, limitShift, arrow } from '@floating-ui/dom';
|
|
27
27
|
import { Clipboard } from '@capacitor/clipboard';
|
|
28
|
+
import { OverlayModule } from '@angular/cdk/overlay';
|
|
28
29
|
import * as i7 from '@ngx-translate/core';
|
|
29
30
|
import { TranslateModule } from '@ngx-translate/core';
|
|
30
31
|
import { isPossiblePhoneNumber } from 'libphonenumber-js';
|
|
@@ -580,30 +581,89 @@ class InputCpfCnpjConfiguration {
|
|
|
580
581
|
}
|
|
581
582
|
}
|
|
582
583
|
|
|
584
|
+
class ModalFocusTrapService {
|
|
585
|
+
constructor() {
|
|
586
|
+
this.initGlobalFocusTrapDisable();
|
|
587
|
+
}
|
|
588
|
+
initGlobalFocusTrapDisable() {
|
|
589
|
+
// Wait for the platform to be ready
|
|
590
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
591
|
+
this.setupModalObserver();
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
setupModalObserver() {
|
|
595
|
+
// Create a mutation observer to watch for new modals
|
|
596
|
+
const observer = new MutationObserver((mutations) => {
|
|
597
|
+
mutations.forEach((mutation) => {
|
|
598
|
+
mutation.addedNodes.forEach((node) => {
|
|
599
|
+
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
600
|
+
const element = node;
|
|
601
|
+
// Check if the added node is an ion-modal
|
|
602
|
+
if (element.tagName?.toLowerCase() === 'ion-modal') {
|
|
603
|
+
this.disableFocusTrap(element);
|
|
604
|
+
}
|
|
605
|
+
// Check for ion-modal children
|
|
606
|
+
const modals = element.querySelectorAll?.('ion-modal');
|
|
607
|
+
modals?.forEach(modal => this.disableFocusTrap(modal));
|
|
608
|
+
}
|
|
609
|
+
});
|
|
610
|
+
});
|
|
611
|
+
});
|
|
612
|
+
// Start observing
|
|
613
|
+
observer.observe(document.body, {
|
|
614
|
+
childList: true,
|
|
615
|
+
subtree: true
|
|
616
|
+
});
|
|
617
|
+
// Also handle existing modals
|
|
618
|
+
const existingModals = document.querySelectorAll('ion-modal');
|
|
619
|
+
existingModals.forEach(modal => this.disableFocusTrap(modal));
|
|
620
|
+
}
|
|
621
|
+
disableFocusTrap(modal) {
|
|
622
|
+
// Add the CSS class
|
|
623
|
+
modal.classList.add('ion-disable-focus-trap');
|
|
624
|
+
// Set the property if it exists
|
|
625
|
+
const modalElement = modal;
|
|
626
|
+
if (modalElement.disableFocusTrap !== undefined) {
|
|
627
|
+
modalElement.disableFocusTrap = true;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ModalFocusTrapService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
631
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ModalFocusTrapService, providedIn: 'root' }); }
|
|
632
|
+
}
|
|
633
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: ModalFocusTrapService, decorators: [{
|
|
634
|
+
type: Injectable,
|
|
635
|
+
args: [{
|
|
636
|
+
providedIn: 'root'
|
|
637
|
+
}]
|
|
638
|
+
}], ctorParameters: () => [] });
|
|
639
|
+
|
|
583
640
|
const EnvironmentInjectionToken = new InjectionToken('Environment');
|
|
584
641
|
class SapphireIonFrameworkModule {
|
|
642
|
+
constructor(mis) {
|
|
643
|
+
this.mis = mis;
|
|
644
|
+
}
|
|
585
645
|
static forRoot(config) {
|
|
586
646
|
return {
|
|
587
647
|
ngModule: SapphireIonFrameworkModule,
|
|
588
648
|
providers: [
|
|
649
|
+
ModalFocusTrapService,
|
|
589
650
|
EnvironmentService, { provide: EnvironmentInjectionToken, useValue: config },
|
|
590
651
|
]
|
|
591
652
|
};
|
|
592
653
|
}
|
|
593
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SapphireIonFrameworkModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
654
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SapphireIonFrameworkModule, deps: [{ token: ModalFocusTrapService }], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
594
655
|
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: SapphireIonFrameworkModule, imports: [CommonModule] }); }
|
|
595
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SapphireIonFrameworkModule, imports: [CommonModule] }); }
|
|
656
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SapphireIonFrameworkModule, providers: [ModalFocusTrapService], imports: [CommonModule] }); }
|
|
596
657
|
}
|
|
597
658
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SapphireIonFrameworkModule, decorators: [{
|
|
598
659
|
type: NgModule,
|
|
599
660
|
args: [{
|
|
600
661
|
declarations: [],
|
|
601
662
|
exports: [],
|
|
602
|
-
imports: [
|
|
603
|
-
|
|
604
|
-
],
|
|
663
|
+
imports: [CommonModule,],
|
|
664
|
+
providers: [ModalFocusTrapService],
|
|
605
665
|
}]
|
|
606
|
-
}] });
|
|
666
|
+
}], ctorParameters: () => [{ type: ModalFocusTrapService }] });
|
|
607
667
|
|
|
608
668
|
class Environment {
|
|
609
669
|
get defaultPageLimit() {
|
|
@@ -2708,8 +2768,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
2708
2768
|
}] } });
|
|
2709
2769
|
|
|
2710
2770
|
class SIonPopoverComponent {
|
|
2711
|
-
constructor(
|
|
2712
|
-
this.viewContainerRef = viewContainerRef;
|
|
2771
|
+
constructor(ngZone) {
|
|
2713
2772
|
this.ngZone = ngZone;
|
|
2714
2773
|
this.fill = 'blur';
|
|
2715
2774
|
this.arrow = true;
|
|
@@ -2724,9 +2783,9 @@ class SIonPopoverComponent {
|
|
|
2724
2783
|
this.anchor = undefined;
|
|
2725
2784
|
this.state = POPOVER_STATE.IDLE;
|
|
2726
2785
|
}
|
|
2727
|
-
|
|
2728
|
-
this.
|
|
2729
|
-
this.
|
|
2786
|
+
ngAfterViewInit() {
|
|
2787
|
+
this._instance = this.contentContainer.nativeElement;
|
|
2788
|
+
document.body.appendChild(this._instance);
|
|
2730
2789
|
//TODO: Use Renderer2 to add event listeners for better Angular compatibility when updating to Angular 19
|
|
2731
2790
|
this.ngZone.runOutsideAngular(() => {
|
|
2732
2791
|
this.documentClickListener = (event) => {
|
|
@@ -2745,27 +2804,6 @@ class SIonPopoverComponent {
|
|
|
2745
2804
|
document.addEventListener('click', this.documentClickListener, true);
|
|
2746
2805
|
});
|
|
2747
2806
|
}
|
|
2748
|
-
CreateEmbeddedView() {
|
|
2749
|
-
if (this._embeddedView) {
|
|
2750
|
-
return;
|
|
2751
|
-
}
|
|
2752
|
-
this._embeddedView = this.popoverTemplate.createEmbeddedView({});
|
|
2753
|
-
this.viewRef = this.viewContainerRef.insert(this._embeddedView);
|
|
2754
|
-
}
|
|
2755
|
-
CreateInstance() {
|
|
2756
|
-
this._instance = this._embeddedView.rootNodes[0];
|
|
2757
|
-
document.body.appendChild(this._instance);
|
|
2758
|
-
// const style = {
|
|
2759
|
-
// "solid" : ['bg-light'],
|
|
2760
|
-
// "outline": ['bg-transparent'],
|
|
2761
|
-
// "blur" : ['backdrop-blur-md', 'bg-light/80'],
|
|
2762
|
-
// "clear" : ['!border-0 bg-transparent'],
|
|
2763
|
-
// }[this.fill];
|
|
2764
|
-
// style.forEach(s => {
|
|
2765
|
-
// this._instance.classList.add(s);
|
|
2766
|
-
// this.arrowEl?.classList.add(s);
|
|
2767
|
-
// });
|
|
2768
|
-
}
|
|
2769
2807
|
get arrowEl() {
|
|
2770
2808
|
return this._instance.querySelector('.popover-arrow');
|
|
2771
2809
|
}
|
|
@@ -2826,7 +2864,6 @@ class SIonPopoverComponent {
|
|
|
2826
2864
|
}
|
|
2827
2865
|
ngOnDestroy() {
|
|
2828
2866
|
if (this._instance) {
|
|
2829
|
-
document.body.removeChild(this._instance);
|
|
2830
2867
|
this._instance.remove();
|
|
2831
2868
|
this._instance = undefined;
|
|
2832
2869
|
}
|
|
@@ -2853,13 +2890,13 @@ class SIonPopoverComponent {
|
|
|
2853
2890
|
].filter(p => p),
|
|
2854
2891
|
});
|
|
2855
2892
|
}
|
|
2856
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SIonPopoverComponent, deps: [{ token: i0.
|
|
2857
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SIonPopoverComponent, selector: "sion-popover", inputs: { fill: "fill", arrow: "arrow", flip: "flip", placement: "placement", height: "height", width: "width", anchor: "anchor" }, outputs: { onWillPresent: "onWillPresent", onDidPresent: "onDidPresent", onWillDismiss: "onWillDismiss", onDidDismiss: "onDidDismiss" }, viewQueries: [{ propertyName: "
|
|
2893
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SIonPopoverComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2894
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: SIonPopoverComponent, selector: "sion-popover", inputs: { fill: "fill", arrow: "arrow", flip: "flip", placement: "placement", height: "height", width: "width", anchor: "anchor" }, outputs: { onWillPresent: "onWillPresent", onDidPresent: "onDidPresent", onWillDismiss: "onWillDismiss", onDidDismiss: "onDidDismiss" }, viewQueries: [{ propertyName: "contentContainer", first: true, predicate: ["popoverWrapper"], descendants: true, read: ElementRef }], ngImport: i0, template: "<div #popoverWrapper \r\n class=\"popover-wrapper translucid-border\"\r\n [style.height]=\"height\"\r\n [style.width]=\"width\"\r\n [ngClass]=\"{\r\n 'bg-light' : fill == 'solid',\r\n 'bg-transparent' : fill == 'outline',\r\n 'backdrop-blur-md bg-light/80': fill == 'blur',\r\n '!border-0' : fill == 'clear',\r\n }\"\r\n> \r\n <div #popoverArrow class=\"popover-arrow size-4 translucid-border\"\r\n [ngClass]=\"{\r\n 'bg-light' : fill == 'solid',\r\n 'bg-transparent' : fill == 'outline',\r\n 'backdrop-blur-md bg-light/80': fill == 'blur',\r\n '!border-0' : fill == 'clear',\r\n }\"\r\n ></div>\r\n <ng-content #content></ng-content>\r\n</div>", styles: [".popover-wrapper{border-radius:.75rem;width:max-content;position:fixed;will-change:left,top,bottom,right,auto,opacity,filter;opacity:0;transition:opacity .15s ease-in-out,transform .15s ease-in-out,filter .15s ease-in-out;min-width:2rem;min-height:2rem;filter:grayscale(.9);transform:scale(.95);pointer-events:auto!important;z-index:10001!important}.popover-arrow{border-radius:.125rem;position:absolute;transform:scale(1) rotate(var(--rotation))!important;clip-path:var(--clip-path-triangle, polygon(0% 0%, 0% 100%, 100% 100%))}.show{filter:grayscale(0);transform:scale(1);opacity:1}.popover-wrapper:not(.show){pointer-events:none!important}\n"], dependencies: [{ kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }] }); }
|
|
2858
2895
|
}
|
|
2859
2896
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SIonPopoverComponent, decorators: [{
|
|
2860
2897
|
type: Component,
|
|
2861
|
-
args: [{ selector: 'sion-popover', template: "<
|
|
2862
|
-
}], ctorParameters: () => [{ type: i0.
|
|
2898
|
+
args: [{ selector: 'sion-popover', template: "<div #popoverWrapper \r\n class=\"popover-wrapper translucid-border\"\r\n [style.height]=\"height\"\r\n [style.width]=\"width\"\r\n [ngClass]=\"{\r\n 'bg-light' : fill == 'solid',\r\n 'bg-transparent' : fill == 'outline',\r\n 'backdrop-blur-md bg-light/80': fill == 'blur',\r\n '!border-0' : fill == 'clear',\r\n }\"\r\n> \r\n <div #popoverArrow class=\"popover-arrow size-4 translucid-border\"\r\n [ngClass]=\"{\r\n 'bg-light' : fill == 'solid',\r\n 'bg-transparent' : fill == 'outline',\r\n 'backdrop-blur-md bg-light/80': fill == 'blur',\r\n '!border-0' : fill == 'clear',\r\n }\"\r\n ></div>\r\n <ng-content #content></ng-content>\r\n</div>", styles: [".popover-wrapper{border-radius:.75rem;width:max-content;position:fixed;will-change:left,top,bottom,right,auto,opacity,filter;opacity:0;transition:opacity .15s ease-in-out,transform .15s ease-in-out,filter .15s ease-in-out;min-width:2rem;min-height:2rem;filter:grayscale(.9);transform:scale(.95);pointer-events:auto!important;z-index:10001!important}.popover-arrow{border-radius:.125rem;position:absolute;transform:scale(1) rotate(var(--rotation))!important;clip-path:var(--clip-path-triangle, polygon(0% 0%, 0% 100%, 100% 100%))}.show{filter:grayscale(0);transform:scale(1);opacity:1}.popover-wrapper:not(.show){pointer-events:none!important}\n"] }]
|
|
2899
|
+
}], ctorParameters: () => [{ type: i0.NgZone }], propDecorators: { fill: [{
|
|
2863
2900
|
type: Input
|
|
2864
2901
|
}], arrow: [{
|
|
2865
2902
|
type: Input
|
|
@@ -2881,15 +2918,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
2881
2918
|
type: Output
|
|
2882
2919
|
}], anchor: [{
|
|
2883
2920
|
type: Input
|
|
2884
|
-
}], popoverTemplate: [{
|
|
2885
|
-
type: ViewChild,
|
|
2886
|
-
args: ['popoverTemplate', { static: true }]
|
|
2887
2921
|
}], contentContainer: [{
|
|
2888
2922
|
type: ViewChild,
|
|
2889
|
-
args: ['popoverWrapper']
|
|
2890
|
-
}], arrowElement: [{
|
|
2891
|
-
type: ViewChild,
|
|
2892
|
-
args: ['popoverArrow']
|
|
2923
|
+
args: ['popoverWrapper', { read: ElementRef }]
|
|
2893
2924
|
}] } });
|
|
2894
2925
|
var POPOVER_STATE;
|
|
2895
2926
|
(function (POPOVER_STATE) {
|
|
@@ -10188,8 +10219,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
10188
10219
|
|
|
10189
10220
|
class SIonPopoverModule {
|
|
10190
10221
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SIonPopoverModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
10191
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: SIonPopoverModule, declarations: [SIonPopoverComponent], imports: [CommonModule], exports: [SIonPopoverComponent] }); }
|
|
10192
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SIonPopoverModule, imports: [CommonModule] }); }
|
|
10222
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.13", ngImport: i0, type: SIonPopoverModule, declarations: [SIonPopoverComponent], imports: [CommonModule, OverlayModule], exports: [SIonPopoverComponent] }); }
|
|
10223
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SIonPopoverModule, imports: [CommonModule, OverlayModule] }); }
|
|
10193
10224
|
}
|
|
10194
10225
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: SIonPopoverModule, decorators: [{
|
|
10195
10226
|
type: NgModule,
|
|
@@ -10197,7 +10228,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
10197
10228
|
declarations: [SIonPopoverComponent],
|
|
10198
10229
|
exports: [SIonPopoverComponent],
|
|
10199
10230
|
imports: [
|
|
10200
|
-
CommonModule
|
|
10231
|
+
CommonModule, OverlayModule
|
|
10201
10232
|
]
|
|
10202
10233
|
}]
|
|
10203
10234
|
}] });
|
|
@@ -10245,7 +10276,8 @@ class InputsModule {
|
|
|
10245
10276
|
MaskitoDirective,
|
|
10246
10277
|
SIonPopoverModule,
|
|
10247
10278
|
LoadingComponent,
|
|
10248
|
-
NgVarDirective
|
|
10279
|
+
NgVarDirective,
|
|
10280
|
+
OverlayModule], exports: [InputBoolComponent,
|
|
10249
10281
|
InputCepComponent,
|
|
10250
10282
|
InputColorComponent,
|
|
10251
10283
|
InputCpfCnpjComponent,
|
|
@@ -10267,7 +10299,8 @@ class InputsModule {
|
|
|
10267
10299
|
FormsModule,
|
|
10268
10300
|
ImageComponent,
|
|
10269
10301
|
SIonPopoverModule,
|
|
10270
|
-
LoadingComponent
|
|
10302
|
+
LoadingComponent,
|
|
10303
|
+
OverlayModule] }); }
|
|
10271
10304
|
}
|
|
10272
10305
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: InputsModule, decorators: [{
|
|
10273
10306
|
type: NgModule,
|
|
@@ -10283,7 +10316,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
10283
10316
|
MaskitoDirective,
|
|
10284
10317
|
SIonPopoverModule,
|
|
10285
10318
|
LoadingComponent,
|
|
10286
|
-
NgVarDirective
|
|
10319
|
+
NgVarDirective,
|
|
10320
|
+
OverlayModule
|
|
10287
10321
|
]
|
|
10288
10322
|
}]
|
|
10289
10323
|
}] });
|