@decaf-ts/for-angular 0.0.24 → 0.0.26
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/fesm2022/decaf-ts-for-angular.mjs +1512 -1517
- package/fesm2022/decaf-ts-for-angular.mjs.map +1 -1
- package/index.d.ts +7470 -3
- package/package.json +14 -17
- package/components/component-renderer/component-renderer.component.d.ts +0 -278
- package/components/crud-field/crud-field.component.d.ts +0 -611
- package/components/crud-form/constants.d.ts +0 -5
- package/components/crud-form/crud-form.component.d.ts +0 -288
- package/components/crud-form/types.d.ts +0 -17
- package/components/empty-state/empty-state.component.d.ts +0 -300
- package/components/fieldset/fieldset.component.d.ts +0 -555
- package/components/filter/filter.component.d.ts +0 -514
- package/components/for-angular-components.module.d.ts +0 -20
- package/components/index.d.ts +0 -16
- package/components/layout/layout.component.d.ts +0 -110
- package/components/list/list.component.d.ts +0 -848
- package/components/list-item/list-item.component.d.ts +0 -390
- package/components/model-renderer/model-renderer.component.d.ts +0 -97
- package/components/pagination/constants.d.ts +0 -7
- package/components/pagination/pagination.component.d.ts +0 -264
- package/components/searchbar/searchbar.component.d.ts +0 -407
- package/components/steped-form/steped-form.component.d.ts +0 -243
- package/directives/collapsable.directive.d.ts +0 -9
- package/directives/index.d.ts +0 -1
- package/engine/DynamicModule.d.ts +0 -17
- package/engine/NgxBaseComponent.d.ts +0 -541
- package/engine/NgxCrudFormField.d.ts +0 -123
- package/engine/NgxFormService.d.ts +0 -601
- package/engine/NgxRenderingEngine.d.ts +0 -282
- package/engine/ValidatorFactory.d.ts +0 -15
- package/engine/constants.d.ts +0 -168
- package/engine/decorators.d.ts +0 -25
- package/engine/index.d.ts +0 -18
- package/engine/interfaces.d.ts +0 -271
- package/engine/types.d.ts +0 -200
- package/esm2022/components/component-renderer/component-renderer.component.mjs +0 -321
- package/esm2022/components/crud-field/crud-field.component.mjs +0 -518
- package/esm2022/components/crud-form/constants.mjs +0 -14
- package/esm2022/components/crud-form/crud-form.component.mjs +0 -259
- package/esm2022/components/crud-form/types.mjs +0 -2
- package/esm2022/components/empty-state/empty-state.component.mjs +0 -345
- package/esm2022/components/fieldset/fieldset.component.mjs +0 -677
- package/esm2022/components/filter/filter.component.mjs +0 -700
- package/esm2022/components/for-angular-components.module.mjs +0 -84
- package/esm2022/components/index.mjs +0 -20
- package/esm2022/components/layout/layout.component.mjs +0 -150
- package/esm2022/components/list/list.component.mjs +0 -1238
- package/esm2022/components/list-item/list-item.component.mjs +0 -405
- package/esm2022/components/model-renderer/model-renderer.component.mjs +0 -144
- package/esm2022/components/pagination/constants.mjs +0 -2
- package/esm2022/components/pagination/pagination.component.mjs +0 -321
- package/esm2022/components/searchbar/searchbar.component.mjs +0 -491
- package/esm2022/components/steped-form/steped-form.component.mjs +0 -291
- package/esm2022/decaf-ts-for-angular.mjs +0 -5
- package/esm2022/directives/collapsable.directive.mjs +0 -29
- package/esm2022/directives/index.mjs +0 -2
- package/esm2022/engine/DynamicModule.mjs +0 -18
- package/esm2022/engine/NgxBaseComponent.mjs +0 -541
- package/esm2022/engine/NgxCrudFormField.mjs +0 -137
- package/esm2022/engine/NgxFormService.mjs +0 -917
- package/esm2022/engine/NgxRenderingEngine.mjs +0 -376
- package/esm2022/engine/ValidatorFactory.mjs +0 -106
- package/esm2022/engine/constants.mjs +0 -170
- package/esm2022/engine/decorators.mjs +0 -38
- package/esm2022/engine/index.mjs +0 -19
- package/esm2022/engine/interfaces.mjs +0 -4
- package/esm2022/engine/types.mjs +0 -2
- package/esm2022/for-angular-common.module.mjs +0 -84
- package/esm2022/helpers/index.mjs +0 -13
- package/esm2022/helpers/utils.mjs +0 -436
- package/esm2022/i18n/Loader.mjs +0 -86
- package/esm2022/i18n/data/en.json +0 -80
- package/esm2022/public-apis.mjs +0 -15
- package/for-angular-common.module.d.ts +0 -50
- package/helpers/index.d.ts +0 -12
- package/helpers/utils.d.ts +0 -279
- package/i18n/Loader.d.ts +0 -43
- package/public-apis.d.ts +0 -14
|
@@ -11,11 +11,10 @@ import { TranslateModule, TranslatePipe, TranslateService } from '@ngx-translate
|
|
|
11
11
|
import { Logging } from '@decaf-ts/logging';
|
|
12
12
|
import { __decorate, __metadata } from 'tslib';
|
|
13
13
|
import { apply, metadata } from '@decaf-ts/reflection';
|
|
14
|
-
import { IonInput, IonItem, IonCheckbox, IonRadioGroup, IonRadio, IonSelect, IonSelectOption, IonLabel, IonText, IonTextarea,
|
|
14
|
+
import { IonInput, IonItem, IonCheckbox, IonRadioGroup, IonRadio, IonSelect, IonSelectOption, IonLabel, IonText, IonTextarea, IonButton, IonIcon, IonCard, IonCardContent, IonAccordionGroup, IonAccordion, IonList, IonReorder, IonReorderGroup, IonSearchbar, IonChip, IonRefresher, IonThumbnail, IonSkeletonText, IonRefresherContent, IonInfiniteScroll, IonInfiniteScrollContent, IonListHeader, IonItemSliding, IonItemOptions, IonItemOption, IonContent, IonPopover } from '@ionic/angular/standalone';
|
|
15
15
|
import { addIcons } from 'ionicons';
|
|
16
16
|
import * as allIcons from 'ionicons/icons';
|
|
17
17
|
import { chevronUpOutline, chevronDownOutline, createOutline, alertCircleOutline, chevronForwardOutline, chevronBackOutline, arrowBackOutline, arrowForwardOutline } from 'ionicons/icons';
|
|
18
|
-
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
|
|
19
18
|
import { forkJoin, fromEvent, debounceTime, Subject, timer } from 'rxjs';
|
|
20
19
|
import { map } from 'rxjs/operators';
|
|
21
20
|
import { Repository, OrderDirection, Condition } from '@decaf-ts/core';
|
|
@@ -292,8 +291,19 @@ class ValidatorFactory {
|
|
|
292
291
|
}
|
|
293
292
|
}
|
|
294
293
|
|
|
294
|
+
/** */
|
|
295
295
|
const DB_ADAPTER_PROVIDER_TOKEN = new InjectionToken('DB_ADAPTER_PROVIDER');
|
|
296
296
|
const I18N_CONFIG_TOKEN = new InjectionToken('I18N_CONFIG_TOKEN');
|
|
297
|
+
function provideDbAdapter(adapterClass, options = {}) {
|
|
298
|
+
const adapter = new adapterClass(options);
|
|
299
|
+
// Log and expose adapter flavour globally
|
|
300
|
+
getLogger(provideDbAdapter).info(`Using ${adapter.flavour} as Db Provider`);
|
|
301
|
+
// getWindow()['dbAdapterFlavour'] = adapter.flavour;
|
|
302
|
+
return {
|
|
303
|
+
provide: DB_ADAPTER_PROVIDER_TOKEN,
|
|
304
|
+
useValue: adapter,
|
|
305
|
+
};
|
|
306
|
+
}
|
|
297
307
|
const ComponentsAndModules = [
|
|
298
308
|
CommonModule,
|
|
299
309
|
FormsModule,
|
|
@@ -341,8 +351,8 @@ class ForAngularCommonModule {
|
|
|
341
351
|
ngModule: ForAngularCommonModule,
|
|
342
352
|
};
|
|
343
353
|
}
|
|
344
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
345
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
354
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ForAngularCommonModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
355
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.2", ngImport: i0, type: ForAngularCommonModule, imports: [CommonModule,
|
|
346
356
|
FormsModule,
|
|
347
357
|
ReactiveFormsModule,
|
|
348
358
|
TranslateModule,
|
|
@@ -351,7 +361,7 @@ class ForAngularCommonModule {
|
|
|
351
361
|
ReactiveFormsModule,
|
|
352
362
|
TranslateModule,
|
|
353
363
|
TranslatePipe] }); }
|
|
354
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
364
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ForAngularCommonModule, imports: [CommonModule,
|
|
355
365
|
FormsModule,
|
|
356
366
|
ReactiveFormsModule,
|
|
357
367
|
TranslateModule,
|
|
@@ -360,7 +370,7 @@ class ForAngularCommonModule {
|
|
|
360
370
|
ReactiveFormsModule,
|
|
361
371
|
TranslateModule] }); }
|
|
362
372
|
}
|
|
363
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
373
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ForAngularCommonModule, decorators: [{
|
|
364
374
|
type: NgModule,
|
|
365
375
|
args: [{
|
|
366
376
|
imports: ComponentsAndModules,
|
|
@@ -2382,10 +2392,10 @@ class ComponentRendererComponent {
|
|
|
2382
2392
|
}
|
|
2383
2393
|
}
|
|
2384
2394
|
}
|
|
2385
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2386
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2395
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ComponentRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2396
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: ComponentRendererComponent, isStandalone: true, selector: "ngx-decaf-component-renderer", inputs: { tag: "tag", globals: "globals", children: "children", model: "model", parent: "parent" }, outputs: { listenEvent: "listenEvent" }, host: { properties: { "attr.id": "uid" } }, viewQueries: [{ propertyName: "vcr", first: true, predicate: ["componentViewContainer"], descendants: true, read: ViewContainerRef, static: true }, { propertyName: "inner", first: true, predicate: ["inner"], descendants: true, read: TemplateRef, static: true }], ngImport: i0, template: "<!-- Keep to avoid id conflicts -->\n<div [id]=\"uid\"></div>\n\n<ng-template #componentViewContainer></ng-template>\n<ng-template #inner>\n @if(parent?.children?.length) {\n @for(child of parent.children; track child) {\n @if(!child.children?.length) {\n <ng-container\n *ngComponentOutlet=\"\n child.component;\n injector: child.injector;\n inputs: child.inputs;\n content:child.content;\n \"\n />\n } @else {\n <ngx-decaf-component-renderer [parent]=\"child\"> </ngx-decaf-component-renderer>\n }\n }\n }\n @if(children?.length) {\n @for(child of children; track child) {\n @if(child.children?.length) {\n <ngx-decaf-component-renderer [parent]=\"child\"> </ngx-decaf-component-renderer>\n } @else {\n <ngx-decaf-component-renderer\n [tag]=\"child?.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{props: child.props}\" />\n }\n }\n }\n</ng-template>\n\n\n", styles: [""], dependencies: [{ kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "globals", "children", "model", "parent"], outputs: ["listenEvent"] }, { kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }] }); }
|
|
2387
2397
|
}
|
|
2388
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2398
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ComponentRendererComponent, decorators: [{
|
|
2389
2399
|
type: Component,
|
|
2390
2400
|
args: [{ selector: 'ngx-decaf-component-renderer', imports: [NgComponentOutlet], standalone: true, host: { '[attr.id]': 'uid' }, template: "<!-- Keep to avoid id conflicts -->\n<div [id]=\"uid\"></div>\n\n<ng-template #componentViewContainer></ng-template>\n<ng-template #inner>\n @if(parent?.children?.length) {\n @for(child of parent.children; track child) {\n @if(!child.children?.length) {\n <ng-container\n *ngComponentOutlet=\"\n child.component;\n injector: child.injector;\n inputs: child.inputs;\n content:child.content;\n \"\n />\n } @else {\n <ngx-decaf-component-renderer [parent]=\"child\"> </ngx-decaf-component-renderer>\n }\n }\n }\n @if(children?.length) {\n @for(child of children; track child) {\n @if(child.children?.length) {\n <ngx-decaf-component-renderer [parent]=\"child\"> </ngx-decaf-component-renderer>\n } @else {\n <ngx-decaf-component-renderer\n [tag]=\"child?.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{props: child.props}\" />\n }\n }\n }\n</ng-template>\n\n\n" }]
|
|
2391
2401
|
}], ctorParameters: () => [], propDecorators: { vcr: [{
|
|
@@ -2648,6 +2658,11 @@ var component = {
|
|
|
2648
2658
|
step3: "Type a value",
|
|
2649
2659
|
no_suggestions: "No suggestions",
|
|
2650
2660
|
sort: "Sort by"
|
|
2661
|
+
},
|
|
2662
|
+
stepped_form: {
|
|
2663
|
+
next: "Next",
|
|
2664
|
+
previous: "Previous",
|
|
2665
|
+
submit: "Submit"
|
|
2651
2666
|
}
|
|
2652
2667
|
};
|
|
2653
2668
|
var en = {
|
|
@@ -2655,20 +2670,6 @@ var en = {
|
|
|
2655
2670
|
component: component
|
|
2656
2671
|
};
|
|
2657
2672
|
|
|
2658
|
-
class I18nLoader {
|
|
2659
|
-
static loadFromHttp(http) {
|
|
2660
|
-
function getSuffix() {
|
|
2661
|
-
const today = new Date();
|
|
2662
|
-
return `.json?version=${today.getFullYear()}${today.getMonth()}${today.getDay()}`;
|
|
2663
|
-
}
|
|
2664
|
-
return new (class extends TranslateHttpLoader {
|
|
2665
|
-
getTranslation(lang) {
|
|
2666
|
-
const res = super.getTranslation(lang);
|
|
2667
|
-
return res;
|
|
2668
|
-
}
|
|
2669
|
-
})(http, './assets/i18n/', getSuffix());
|
|
2670
|
-
}
|
|
2671
|
-
}
|
|
2672
2673
|
function getLocaleContext(clazz, suffix) {
|
|
2673
2674
|
return getLocaleFromClassName(clazz, suffix);
|
|
2674
2675
|
}
|
|
@@ -2695,22 +2696,21 @@ function getLocaleContextByKey(locale, phrase) {
|
|
|
2695
2696
|
return `${locale}.${cleanSpaces(parts.join('.'), true)}`;
|
|
2696
2697
|
}
|
|
2697
2698
|
function I18nLoaderFactory(http) {
|
|
2698
|
-
const { resources, versionedSuffix } = inject(I18N_CONFIG_TOKEN, { optional: true }) ??
|
|
2699
|
-
return new
|
|
2699
|
+
const { resources, versionedSuffix } = inject(I18N_CONFIG_TOKEN, { optional: true }) ?? provideI18nLoader().useValue;
|
|
2700
|
+
return new I18nLoader(http, resources?.length ? resources : [{ prefix: './app/assets/i18n/', suffix: '.json' }], versionedSuffix);
|
|
2700
2701
|
}
|
|
2701
|
-
function
|
|
2702
|
+
function provideI18nLoader(resources = [], versionedSuffix = false) {
|
|
2702
2703
|
if (!Array.isArray(resources))
|
|
2703
2704
|
resources = [resources];
|
|
2704
2705
|
return {
|
|
2705
2706
|
provide: I18N_CONFIG_TOKEN,
|
|
2706
2707
|
useValue: { resources: [
|
|
2707
|
-
// { prefix: './assets/i18n/', suffix: '.json' },
|
|
2708
2708
|
...resources
|
|
2709
2709
|
], versionedSuffix }
|
|
2710
2710
|
};
|
|
2711
2711
|
}
|
|
2712
2712
|
const libLanguage = { en };
|
|
2713
|
-
class
|
|
2713
|
+
class I18nLoader {
|
|
2714
2714
|
constructor(http, resources = [], versionedSuffix = false) {
|
|
2715
2715
|
this.http = http;
|
|
2716
2716
|
this.resources = resources;
|
|
@@ -3096,13 +3096,13 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxCrudFormField {
|
|
|
3096
3096
|
});
|
|
3097
3097
|
component.dispatchEvent(event);
|
|
3098
3098
|
}
|
|
3099
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3100
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: CrudFieldComponent, isStandalone: true, selector: "ngx-decaf-crud-field", inputs: { operation: "operation", name: "name", path: "path", childOf: "childOf", type: "type", value: "value", disabled: "disabled", label: "label", placeholder: "placeholder", format: "format", hidden: "hidden", max: "max", maxlength: "maxlength", min: "min", minlength: "minlength", pattern: "pattern", readonly: "readonly", required: "required", step: "step", equals: "equals", different: "different", lessThan: "lessThan", lessThanOrEqual: "lessThanOrEqual", greaterThan: "greaterThan", greaterThanOrEqual: "greaterThanOrEqual", cols: "cols", rows: "rows", alignment: "alignment", checked: "checked", justify: "justify", cancelText: "cancelText", interface: "interface", options: "options", mode: "mode", spellcheck: "spellcheck", inputmode: "inputmode", autocomplete: "autocomplete", fill: "fill", labelPlacement: "labelPlacement", updateOn: "updateOn", formGroup: "formGroup", formControl: "formControl", multiple: "multiple", uid: "uid", page: "page", translatable: "translatable", activeFormGroup: "activeFormGroup", pk: "pk" }, host: { listeners: { "window:fieldsetAddGroupEvent": "handleFieldsetCreateGroupEvent($event)", "window:fieldsetUpdateGroupEvent": "handleFieldsetUpdateGroupEvent($event)", "window:fieldsetRemoveGroupEvent": "handleFieldsetRemoveGroupEvent($event)" }, properties: { "attr.id": "uid" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "@if(operation === 'read' || operation === 'delete') {\n <ng-container #component>\n <div [class]=\"'dcf-input-item ' + operation\">\n <ion-item>\n <ion-label>\n {{ label | translate }}<br />\n @if(value) {\n <ion-text [innerHTML]=\"type === 'password' ? '********' : value\"></ion-text>\n } @else {\n <br />\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n} @else {\n <ng-container [formGroup]=\"getActiveFormGroup\">\n <div #container [class]=\"'dcf-input-item ' + (operation || 'create')\" (createGroupEvent)=\"multiple ? handleFieldsetCreateGroupEvent($event) : ''\">\n @if(type === 'textarea') {\n <ion-textarea\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [required]=\"required !== undefined ? required : null\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component>\n </ion-textarea>\n }\n @else if(type === 'checkbox') {\n <ion-item>\n <ion-checkbox\n #checkboxElement\n [mode]=\"mode\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"value\"\n [checked]=\"checked\"\n [readonly]=\"readonly\"\n (ionChange)=\"checked = !checked\"\n [formControlName]=\"name\"\n #component>\n <span [innerHTML]=\"label | translate\"></span>\n </ion-checkbox>\n </ion-item>\n }\n @else if(type === 'radio') {\n <ion-radio-group [formControlName]=\"name\" [value]=\"value\" #component>\n <label class=\"dcf-radio-group-label\" [for]=\"path\">{{label | translate}}</label>\n @for(option of options; track option) {\n <ion-item>\n <ion-radio\n [errorText]=\"getErrors(container)\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [readonly]=\"readonly\"\n [value]=\"option.value\"\n >{{ translatable ? (option?.text | translate) : option?.text }}</ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n }\n @else if(type === 'select') {\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"translatable ? (label | translate) : label\"\n [value]=\"value\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [interface]=\"interface\" #component>\n @for(option of options; track option.value) {\n <ion-select-option [value]=\"option.value\">\n {{ option.text | translate }}\n </ion-select-option>\n }\n </ion-select>\n }\n @else {\n <ion-input\n [type]=\"type\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [required]=\"required !== undefined ? required : false\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [pattern]=\"pattern !== undefined ? pattern : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\" #component />\n }\n </div>\n </ng-container>\n}\n\n", styles: [".dcf-input-item.create,.dcf-input-item.update{margin-bottom:1.8rem;margin-top:0!important}.dcf-input-item.create.checkbox+.checkbox,.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}.dcf-input-item.create ion-item,.dcf-input-item.update ion-item{--border-color: transparent}.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{font-weight:600}@media (prefers-color-scheme: light){.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{color:var(--dcf-color-gray-7)}}.dcf-input-item.read ion-text,.dcf-input-item.delete ion-text{display:block;margin-top:.5rem!important}.dcf-input-item ion-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15}@media (prefers-color-scheme: dark){.dcf-input-item ion-item{--border-color: var(--dcf-color-gray-6)}}@media (prefers-color-scheme: light){.dcf-input-item ion-item{--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}}.dcf-input-item ion-item span,.dcf-input-item ion-item ion-text{font-weight:400!important;font-size:.925rem;min-height:.5rem!important}.dcf-input-item ion-item span:not(.dcf-display-block),.dcf-input-item ion-item ion-text:not(.dcf-display-block){display:inline-block}.dcf-input-item ion-item span.dcf-display-block,.dcf-input-item ion-item ion-text.dcf-display-block{display:block!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-item{--inner-padding-start: .75rem}ion-checkbox::part(container){border-radius:50%;padding:3px}@media (prefers-color-scheme: light){ion-checkbox::part(container){border:2px solid var(--dcf-color-primary)}}ion-item .dcf-radio-group-label,ion-radio-group .dcf-radio-group-label{font-weight:600}ion-item .dcf-radio-group-label~ion-item,ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-item+.dcf-helper,ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:600!important;line-height:1.1rem;box-sizing:border-box;z-index:9999;margin-top:0;animation-duration:.1s;animation-timing-function:ease-out;animation-fill-mode:both;animation-name:fadeTopSmallAnimation;display:flex;align-items:flex-start;gap:.25rem}.dcf-error .ti,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;color:var(--dcf-color-gray-7)!important;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}@keyframes fadeTopSmallAnimation{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeBottomSmallAnimation{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeTopMediumAnimation{0%{opacity:0;transform:translateY(-50px)}to{opacity:1;transform:translateY(0)}}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }] }); }
|
|
3099
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CrudFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
3100
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: CrudFieldComponent, isStandalone: true, selector: "ngx-decaf-crud-field", inputs: { operation: "operation", name: "name", path: "path", childOf: "childOf", type: "type", value: "value", disabled: "disabled", label: "label", placeholder: "placeholder", format: "format", hidden: "hidden", max: "max", maxlength: "maxlength", min: "min", minlength: "minlength", pattern: "pattern", readonly: "readonly", required: "required", step: "step", equals: "equals", different: "different", lessThan: "lessThan", lessThanOrEqual: "lessThanOrEqual", greaterThan: "greaterThan", greaterThanOrEqual: "greaterThanOrEqual", cols: "cols", rows: "rows", alignment: "alignment", checked: "checked", justify: "justify", cancelText: "cancelText", interface: "interface", options: "options", mode: "mode", spellcheck: "spellcheck", inputmode: "inputmode", autocomplete: "autocomplete", fill: "fill", labelPlacement: "labelPlacement", updateOn: "updateOn", formGroup: "formGroup", formControl: "formControl", multiple: "multiple", uid: "uid", page: "page", translatable: "translatable", activeFormGroup: "activeFormGroup", pk: "pk" }, host: { listeners: { "window:fieldsetAddGroupEvent": "handleFieldsetCreateGroupEvent($event)", "window:fieldsetUpdateGroupEvent": "handleFieldsetUpdateGroupEvent($event)", "window:fieldsetRemoveGroupEvent": "handleFieldsetRemoveGroupEvent($event)" }, properties: { "attr.id": "uid" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "@if(operation === 'read' || operation === 'delete') {\n <ng-container #component>\n <div [class]=\"'dcf-input-item ' + operation\">\n <ion-item>\n <ion-label>\n {{ label | translate }}<br />\n @if(value) {\n <ion-text [innerHTML]=\"type === 'password' ? '********' : value\"></ion-text>\n } @else {\n <br />\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n} @else {\n <ng-container [formGroup]=\"getActiveFormGroup\">\n <div #container [class]=\"'dcf-input-item ' + (operation || 'create')\" (createGroupEvent)=\"multiple ? handleFieldsetCreateGroupEvent($event) : ''\">\n @if(type === 'textarea') {\n <ion-textarea\n [id]=\"name\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [required]=\"required !== undefined ? required : null\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component>\n </ion-textarea>\n }\n @else if(type === 'checkbox') {\n <ion-item>\n <ion-checkbox\n [id]=\"name\"\n [mode]=\"mode\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"value\"\n [checked]=\"checked\"\n [readonly]=\"readonly\"\n (ionChange)=\"checked = !checked\"\n [formControlName]=\"name\"\n #component>\n <span [innerHTML]=\"label | translate\"></span>\n </ion-checkbox>\n </ion-item>\n }\n @else if(type === 'radio') {\n <ion-radio-group [formControlName]=\"name\" [value]=\"value\" #component>\n <label class=\"dcf-radio-group-label\" [for]=\"path\">{{label | translate}}</label>\n @for(option of options; track option) {\n <ion-item>\n <ion-radio\n [id]=\"name\"\n [errorText]=\"getErrors(container)\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [readonly]=\"readonly\"\n [value]=\"option.value\"\n >{{ translatable ? (option?.text | translate) : option?.text }}</ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n }\n @else if(type === 'select') {\n <ion-select\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"translatable ? (label | translate) : label\"\n [value]=\"value\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [interface]=\"interface\" #component>\n @for(option of options; track option.value) {\n <ion-select-option [value]=\"option.value\">\n {{ option.text | translate }}\n </ion-select-option>\n }\n </ion-select>\n }\n @else {\n <ion-input\n [id]=\"name\"\n [type]=\"type\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [required]=\"required !== undefined ? required : false\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [pattern]=\"pattern !== undefined ? pattern : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\" #component />\n }\n </div>\n </ng-container>\n}\n\n", styles: ["@media (prefers-color-scheme: light){.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{color:var(--dcf-color-gray-7)}.dcf-input-item ion-item{--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}ion-checkbox::part(container){border:2px solid var(--dcf-color-primary)}}@media (prefers-color-scheme: dark){.dcf-input-item ion-item{--border-color: var(--dcf-color-gray-6)}}.dcf-input-item.create,.dcf-input-item.update{margin-bottom:1.8rem;margin-top:0!important}.dcf-input-item.create.checkbox+.checkbox,.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}.dcf-input-item.create ion-item,.dcf-input-item.update ion-item{--border-color: transparent}.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{font-weight:600}.dcf-input-item.read ion-text,.dcf-input-item.delete ion-text{display:block;margin-top:.5rem!important}.dcf-input-item ion-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15}.dcf-input-item ion-item span,.dcf-input-item ion-item ion-text{font-weight:400!important;font-size:.925rem;min-height:.5rem!important}.dcf-input-item ion-item span:not(.dcf-display-block),.dcf-input-item ion-item ion-text:not(.dcf-display-block){display:inline-block}.dcf-input-item ion-item span.dcf-display-block,.dcf-input-item ion-item ion-text.dcf-display-block{display:block!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-item{--inner-padding-start: .75rem}ion-checkbox::part(container){border-radius:50%;padding:3px}ion-item .dcf-radio-group-label,ion-radio-group .dcf-radio-group-label{font-weight:600}ion-item .dcf-radio-group-label~ion-item,ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-item+.dcf-helper,ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:600!important;line-height:1.1rem;box-sizing:border-box;z-index:9999;margin-top:0;animation-duration:.1s;animation-timing-function:ease-out;animation-fill-mode:both;animation-name:fadeTopSmallAnimation;display:flex;align-items:flex-start;gap:.25rem}.dcf-error .ti,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;color:var(--dcf-color-gray-7)!important;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}@keyframes fadeTopSmallAnimation{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeBottomSmallAnimation{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeTopMediumAnimation{0%{opacity:0;transform:translateY(-50px)}to{opacity:1;transform:translateY(0)}}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.PatternValidator, selector: "[pattern][formControlName],[pattern][formControl],[pattern][ngModel]", inputs: ["pattern"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
3101
3101
|
};
|
|
3102
3102
|
CrudFieldComponent = __decorate([
|
|
3103
3103
|
Dynamic()
|
|
3104
3104
|
], CrudFieldComponent);
|
|
3105
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3105
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CrudFieldComponent, decorators: [{
|
|
3106
3106
|
type: Component,
|
|
3107
3107
|
args: [{ standalone: true, imports: [
|
|
3108
3108
|
ReactiveFormsModule,
|
|
@@ -3116,9 +3116,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
3116
3116
|
IonSelectOption,
|
|
3117
3117
|
IonLabel,
|
|
3118
3118
|
IonText,
|
|
3119
|
-
IonTextarea
|
|
3120
|
-
|
|
3121
|
-
], selector: 'ngx-decaf-crud-field', schemas: [CUSTOM_ELEMENTS_SCHEMA], host: { '[attr.id]': 'uid' }, template: "@if(operation === 'read' || operation === 'delete') {\n <ng-container #component>\n <div [class]=\"'dcf-input-item ' + operation\">\n <ion-item>\n <ion-label>\n {{ label | translate }}<br />\n @if(value) {\n <ion-text [innerHTML]=\"type === 'password' ? '********' : value\"></ion-text>\n } @else {\n <br />\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n} @else {\n <ng-container [formGroup]=\"getActiveFormGroup\">\n <div #container [class]=\"'dcf-input-item ' + (operation || 'create')\" (createGroupEvent)=\"multiple ? handleFieldsetCreateGroupEvent($event) : ''\">\n @if(type === 'textarea') {\n <ion-textarea\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [required]=\"required !== undefined ? required : null\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component>\n </ion-textarea>\n }\n @else if(type === 'checkbox') {\n <ion-item>\n <ion-checkbox\n #checkboxElement\n [mode]=\"mode\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"value\"\n [checked]=\"checked\"\n [readonly]=\"readonly\"\n (ionChange)=\"checked = !checked\"\n [formControlName]=\"name\"\n #component>\n <span [innerHTML]=\"label | translate\"></span>\n </ion-checkbox>\n </ion-item>\n }\n @else if(type === 'radio') {\n <ion-radio-group [formControlName]=\"name\" [value]=\"value\" #component>\n <label class=\"dcf-radio-group-label\" [for]=\"path\">{{label | translate}}</label>\n @for(option of options; track option) {\n <ion-item>\n <ion-radio\n [errorText]=\"getErrors(container)\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [readonly]=\"readonly\"\n [value]=\"option.value\"\n >{{ translatable ? (option?.text | translate) : option?.text }}</ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n }\n @else if(type === 'select') {\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"translatable ? (label | translate) : label\"\n [value]=\"value\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [interface]=\"interface\" #component>\n @for(option of options; track option.value) {\n <ion-select-option [value]=\"option.value\">\n {{ option.text | translate }}\n </ion-select-option>\n }\n </ion-select>\n }\n @else {\n <ion-input\n [type]=\"type\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [required]=\"required !== undefined ? required : false\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [pattern]=\"pattern !== undefined ? pattern : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\" #component />\n }\n </div>\n </ng-container>\n}\n\n", styles: [".dcf-input-item.create,.dcf-input-item.update{margin-bottom:1.8rem;margin-top:0!important}.dcf-input-item.create.checkbox+.checkbox,.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}.dcf-input-item.create ion-item,.dcf-input-item.update ion-item{--border-color: transparent}.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{font-weight:600}@media (prefers-color-scheme: light){.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{color:var(--dcf-color-gray-7)}}.dcf-input-item.read ion-text,.dcf-input-item.delete ion-text{display:block;margin-top:.5rem!important}.dcf-input-item ion-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15}@media (prefers-color-scheme: dark){.dcf-input-item ion-item{--border-color: var(--dcf-color-gray-6)}}@media (prefers-color-scheme: light){.dcf-input-item ion-item{--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}}.dcf-input-item ion-item span,.dcf-input-item ion-item ion-text{font-weight:400!important;font-size:.925rem;min-height:.5rem!important}.dcf-input-item ion-item span:not(.dcf-display-block),.dcf-input-item ion-item ion-text:not(.dcf-display-block){display:inline-block}.dcf-input-item ion-item span.dcf-display-block,.dcf-input-item ion-item ion-text.dcf-display-block{display:block!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-item{--inner-padding-start: .75rem}ion-checkbox::part(container){border-radius:50%;padding:3px}@media (prefers-color-scheme: light){ion-checkbox::part(container){border:2px solid var(--dcf-color-primary)}}ion-item .dcf-radio-group-label,ion-radio-group .dcf-radio-group-label{font-weight:600}ion-item .dcf-radio-group-label~ion-item,ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-item+.dcf-helper,ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:600!important;line-height:1.1rem;box-sizing:border-box;z-index:9999;margin-top:0;animation-duration:.1s;animation-timing-function:ease-out;animation-fill-mode:both;animation-name:fadeTopSmallAnimation;display:flex;align-items:flex-start;gap:.25rem}.dcf-error .ti,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;color:var(--dcf-color-gray-7)!important;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}@keyframes fadeTopSmallAnimation{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeBottomSmallAnimation{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeTopMediumAnimation{0%{opacity:0;transform:translateY(-50px)}to{opacity:1;transform:translateY(0)}}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin}\n"] }]
|
|
3119
|
+
IonTextarea
|
|
3120
|
+
], selector: 'ngx-decaf-crud-field', schemas: [CUSTOM_ELEMENTS_SCHEMA], host: { '[attr.id]': 'uid' }, template: "@if(operation === 'read' || operation === 'delete') {\n <ng-container #component>\n <div [class]=\"'dcf-input-item ' + operation\">\n <ion-item>\n <ion-label>\n {{ label | translate }}<br />\n @if(value) {\n <ion-text [innerHTML]=\"type === 'password' ? '********' : value\"></ion-text>\n } @else {\n <br />\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n} @else {\n <ng-container [formGroup]=\"getActiveFormGroup\">\n <div #container [class]=\"'dcf-input-item ' + (operation || 'create')\" (createGroupEvent)=\"multiple ? handleFieldsetCreateGroupEvent($event) : ''\">\n @if(type === 'textarea') {\n <ion-textarea\n [id]=\"name\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [required]=\"required !== undefined ? required : null\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component>\n </ion-textarea>\n }\n @else if(type === 'checkbox') {\n <ion-item>\n <ion-checkbox\n [id]=\"name\"\n [mode]=\"mode\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"value\"\n [checked]=\"checked\"\n [readonly]=\"readonly\"\n (ionChange)=\"checked = !checked\"\n [formControlName]=\"name\"\n #component>\n <span [innerHTML]=\"label | translate\"></span>\n </ion-checkbox>\n </ion-item>\n }\n @else if(type === 'radio') {\n <ion-radio-group [formControlName]=\"name\" [value]=\"value\" #component>\n <label class=\"dcf-radio-group-label\" [for]=\"path\">{{label | translate}}</label>\n @for(option of options; track option) {\n <ion-item>\n <ion-radio\n [id]=\"name\"\n [errorText]=\"getErrors(container)\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [readonly]=\"readonly\"\n [value]=\"option.value\"\n >{{ translatable ? (option?.text | translate) : option?.text }}</ion-radio>\n </ion-item>\n }\n </ion-radio-group>\n }\n @else if(type === 'select') {\n <ion-select\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"translatable ? (label | translate) : label\"\n [value]=\"value\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [interface]=\"interface\" #component>\n @for(option of options; track option.value) {\n <ion-select-option [value]=\"option.value\">\n {{ option.text | translate }}\n </ion-select-option>\n }\n </ion-select>\n }\n @else {\n <ion-input\n [id]=\"name\"\n [type]=\"type\"\n [mode]=\"mode\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [required]=\"required !== undefined ? required : false\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [pattern]=\"pattern !== undefined ? pattern : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\" #component />\n }\n </div>\n </ng-container>\n}\n\n", styles: ["@media (prefers-color-scheme: light){.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{color:var(--dcf-color-gray-7)}.dcf-input-item ion-item{--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}ion-checkbox::part(container){border:2px solid var(--dcf-color-primary)}}@media (prefers-color-scheme: dark){.dcf-input-item ion-item{--border-color: var(--dcf-color-gray-6)}}.dcf-input-item.create,.dcf-input-item.update{margin-bottom:1.8rem;margin-top:0!important}.dcf-input-item.create.checkbox+.checkbox,.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}.dcf-input-item.create ion-item,.dcf-input-item.update ion-item{--border-color: transparent}.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}.dcf-input-item.read ion-label,.dcf-input-item.delete ion-label{font-weight:600}.dcf-input-item.read ion-text,.dcf-input-item.delete ion-text{display:block;margin-top:.5rem!important}.dcf-input-item ion-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15}.dcf-input-item ion-item span,.dcf-input-item ion-item ion-text{font-weight:400!important;font-size:.925rem;min-height:.5rem!important}.dcf-input-item ion-item span:not(.dcf-display-block),.dcf-input-item ion-item ion-text:not(.dcf-display-block){display:inline-block}.dcf-input-item ion-item span.dcf-display-block,.dcf-input-item ion-item ion-text.dcf-display-block{display:block!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-item{--inner-padding-start: .75rem}ion-checkbox::part(container){border-radius:50%;padding:3px}ion-item .dcf-radio-group-label,ion-radio-group .dcf-radio-group-label{font-weight:600}ion-item .dcf-radio-group-label~ion-item,ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-item+.dcf-helper,ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:600!important;line-height:1.1rem;box-sizing:border-box;z-index:9999;margin-top:0;animation-duration:.1s;animation-timing-function:ease-out;animation-fill-mode:both;animation-name:fadeTopSmallAnimation;display:flex;align-items:flex-start;gap:.25rem}.dcf-error .ti,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;color:var(--dcf-color-gray-7)!important;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}@keyframes fadeTopSmallAnimation{0%{opacity:0;transform:translateY(-10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeBottomSmallAnimation{0%{opacity:0;transform:translateY(10px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeTopMediumAnimation{0%{opacity:0;transform:translateY(-50px)}to{opacity:1;transform:translateY(0)}}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin}\n"] }]
|
|
3122
3121
|
}], propDecorators: { operation: [{
|
|
3123
3122
|
type: Input,
|
|
3124
3123
|
args: [{ required: true }]
|
|
@@ -3738,10 +3737,10 @@ class NgxBaseComponent {
|
|
|
3738
3737
|
if (!this.initialized)
|
|
3739
3738
|
this.initialized = true;
|
|
3740
3739
|
}
|
|
3741
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3742
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
3740
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxBaseComponent, deps: [{ token: 'instanceToken' }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3741
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: NgxBaseComponent, isStandalone: true, selector: "ng-component", inputs: { rendererId: "rendererId", model: "model", props: "props", item: "item", pk: "pk", route: "route", operations: "operations", uid: "uid", mapper: "mapper", locale: "locale", translatable: "translatable", className: "className", mode: "mode", renderChild: "renderChild" }, outputs: { listenEvent: "listenEvent" }, host: { properties: { "attr.id": "uid" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef, static: true }], usesOnChanges: true, ngImport: i0, template: '<div></div>', isInline: true }); }
|
|
3743
3742
|
}
|
|
3744
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3743
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxBaseComponent, decorators: [{
|
|
3745
3744
|
type: Component,
|
|
3746
3745
|
args: [{
|
|
3747
3746
|
standalone: true,
|
|
@@ -4010,13 +4009,13 @@ let CrudFormComponent = class CrudFormComponent {
|
|
|
4010
4009
|
name: EventConstants.SUBMIT,
|
|
4011
4010
|
});
|
|
4012
4011
|
}
|
|
4013
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
4014
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
4012
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CrudFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4013
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: CrudFormComponent, isStandalone: true, selector: "ngx-decaf-crud-form", inputs: { model: "model", modelId: "modelId", updateOn: "updateOn", target: "target", method: "method", options: "options", action: "action", operation: "operation", handlers: "handlers", formGroup: "formGroup", childOf: "childOf", rendererId: "rendererId", uid: "uid", allowClear: "allowClear" }, outputs: { submitEvent: "submitEvent" }, host: { properties: { "attr.id": "uid" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["reactiveForm"], descendants: true, read: ElementRef }], ngImport: i0, template: "@if(operation !== 'read' && operation !== 'delete') {\n <form #reactiveForm [id]=\"rendererId\" [formGroup]=\"formGroup\" (submit)=\"submit($event)\" novalidate [target]=\"target\">\n <ng-content #formContent></ng-content>\n <div class=\"dcf-buttons-container dcf-grid dcf-grid-collapse dcf-flex dcf-flex-left\">\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if(options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : options.buttons.submit.text}}\n </ion-button>\n </div>\n @if(!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if(options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n Back\n </ion-button>\n </div>\n }\n </div>\n </form>\n} @else {\n <div [class]=\"'dcf-buttons-container dcf-grid dcf-grid-collapse dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if(operation === OperationKeys.READ && modelId) {\n <div>\n <ion-button\n (click)=\"handleDelete()\"\n color=\"danger\"\n type=\"button\">\n @if(options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n Delete\n </ion-button>\n </div>\n\n }\n @if(operation === OperationKeys.CREATE || operation === OperationKeys.UPDATE) {\n\n <div>\n <ion-button\n type=\"submit\">\n @if(options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{options.buttons.submit.text}}\n </ion-button>\n </div>\n }\n\n @if(options.buttons.clear) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if(options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ [OperationKeys.DELETE, OperationKeys.READ, OperationKeys.UPDATE].includes(operation) ? 'Back' : options.buttons.clear?.text}}\n </ion-button>\n </div>\n\n }\n </div>\n}\n\n", styles: [".dcf-buttons-container{margin-top:1.8rem;margin-bottom:0}@media (min-width: 768px){.dcf-buttons-container.dcf-flex{flex-direction:row-reverse}}@media (max-width: 767px){.dcf-buttons-container.dcf-flex div{width:100%}.dcf-buttons-container.dcf-flex ion-button{width:100%;margin-bottom:1rem}}form{padding:2rem 1rem}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
|
|
4015
4014
|
};
|
|
4016
4015
|
CrudFormComponent = __decorate([
|
|
4017
4016
|
Dynamic()
|
|
4018
4017
|
], CrudFormComponent);
|
|
4019
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4018
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CrudFormComponent, decorators: [{
|
|
4020
4019
|
type: Component,
|
|
4021
4020
|
args: [{ standalone: true, selector: 'ngx-decaf-crud-form', imports: [ReactiveFormsModule, IonButton, IonIcon], host: { '[attr.id]': 'uid' }, template: "@if(operation !== 'read' && operation !== 'delete') {\n <form #reactiveForm [id]=\"rendererId\" [formGroup]=\"formGroup\" (submit)=\"submit($event)\" novalidate [target]=\"target\">\n <ng-content #formContent></ng-content>\n <div class=\"dcf-buttons-container dcf-grid dcf-grid-collapse dcf-flex dcf-flex-left\">\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if(options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : options.buttons.submit.text}}\n </ion-button>\n </div>\n @if(!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if(options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n Back\n </ion-button>\n </div>\n }\n </div>\n </form>\n} @else {\n <div [class]=\"'dcf-buttons-container dcf-grid dcf-grid-collapse dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if(operation === OperationKeys.READ && modelId) {\n <div>\n <ion-button\n (click)=\"handleDelete()\"\n color=\"danger\"\n type=\"button\">\n @if(options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n Delete\n </ion-button>\n </div>\n\n }\n @if(operation === OperationKeys.CREATE || operation === OperationKeys.UPDATE) {\n\n <div>\n <ion-button\n type=\"submit\">\n @if(options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{options.buttons.submit.text}}\n </ion-button>\n </div>\n }\n\n @if(options.buttons.clear) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if(options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ [OperationKeys.DELETE, OperationKeys.READ, OperationKeys.UPDATE].includes(operation) ? 'Back' : options.buttons.clear?.text}}\n </ion-button>\n </div>\n\n }\n </div>\n}\n\n", styles: [".dcf-buttons-container{margin-top:1.8rem;margin-bottom:0}@media (min-width: 768px){.dcf-buttons-container.dcf-flex{flex-direction:row-reverse}}@media (max-width: 767px){.dcf-buttons-container.dcf-flex div{width:100%}.dcf-buttons-container.dcf-flex ion-button{width:100%;margin-bottom:1rem}}form{padding:2rem 1rem}\n"] }]
|
|
4022
4021
|
}], propDecorators: { model: [{
|
|
@@ -4342,17 +4341,16 @@ let EmptyStateComponent = class EmptyStateComponent extends NgxBaseComponent {
|
|
|
4342
4341
|
const result = await this.translate.instant(content, { 'value0': this.searchValue });
|
|
4343
4342
|
return this.sanitizer.bypassSecurityTrustHtml(result);
|
|
4344
4343
|
}
|
|
4345
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
4346
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
4344
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: EmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4345
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: EmptyStateComponent, isStandalone: true, selector: "ngx-decaf-empty-state", inputs: { title: "title", titleColor: "titleColor", subtitle: "subtitle", subtitleColor: "subtitleColor", showIcon: "showIcon", icon: "icon", iconSize: "iconSize", iconColor: "iconColor", buttonLink: "buttonLink", buttonText: "buttonText", buttonFill: "buttonFill", buttonColor: "buttonColor", buttonSize: "buttonSize", searchValue: "searchValue" }, usesInheritance: true, ngImport: i0, template: "\n<ion-card [id]=\"uid\" [class]=\"className\">\n <ion-card-content>\n @if(icon && showIcon) {\n <div class=\"dcf-icon-container\">\n <ion-icon\n name=\"alert-circle-outline\"\n size=\"large\"\n color=\"danger\"\n />\n </div>\n }\n @if(title) {\n <h5 [class]=\"titleColor\" [innerHTML]=\"title\"></h5>\n }\n @if(subtitle) {\n @if(!searchValue) {\n <p [class]=\"subtitleColor\" [innerHTML]=\"subtitle\"></p>\n } @else {\n <p [class]=\"subtitleColor\" [innerHTML]=\"searchSubtitle\"></p>\n }\n }\n @if(buttonLink && buttonText) {\n <div>\n <ion-button\n [size]=\"buttonSize\"\n [fill]=\"buttonFill\"\n [color]=\"buttonColor\"\n (click)=\"handleClick()\">\n {{ buttonText }}\n </ion-button>\n </div>\n }\n </ion-card-content>\n</ion-card>\n", styles: ["ion-card{text-align:center}ion-card ion-button{margin-top:.75rem}ion-card ion-icon{font-size:2.5rem}ion-card .dcf-icon-container{transform:scale(1.25);opacity:.75;margin-top:1.25rem!important;margin-bottom:.5rem!important}ion-card .dcf-ititle{font-weight:600!important;color:var(--dcf-color-gray-6)!important}ion-card .dcf-isubtitle{font-weight:500!important}\n"], dependencies: [{ kind: "component", type: IonCard, selector: "ion-card", inputs: ["button", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCardContent, selector: "ion-card-content", inputs: ["mode"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
|
|
4347
4346
|
};
|
|
4348
4347
|
EmptyStateComponent = __decorate([
|
|
4349
4348
|
Dynamic(),
|
|
4350
4349
|
__metadata("design:paramtypes", [])
|
|
4351
4350
|
], EmptyStateComponent);
|
|
4352
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4351
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: EmptyStateComponent, decorators: [{
|
|
4353
4352
|
type: Component,
|
|
4354
4353
|
args: [{ selector: 'ngx-decaf-empty-state', standalone: true, imports: [
|
|
4355
|
-
TranslatePipe,
|
|
4356
4354
|
IonCard,
|
|
4357
4355
|
IonCardContent,
|
|
4358
4356
|
IonIcon
|
|
@@ -4996,14 +4994,14 @@ let FieldsetComponent = class FieldsetComponent extends NgxBaseComponent {
|
|
|
4996
4994
|
}
|
|
4997
4995
|
return this.mapper;
|
|
4998
4996
|
}
|
|
4999
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
5000
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: FieldsetComponent, isStandalone: true, selector: "ngx-decaf-fieldset", inputs: { name: "name", childOf: "childOf", page: "page", uid: "uid", customTypes: "customTypes", operation: "operation", formGroup: "formGroup", title: "title", description: "description", target: "target", multiple: "multiple", value: "value", handlers: "handlers" }, host: { properties: { "attr.id": "overriode " } }, viewQueries: [{ propertyName: "accordionComponent", first: true, predicate: ["accordionComponent"], descendants: true }], usesInheritance: true, ngImport: i0, template: "\n\n<fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n (fieldsetRemoveGroupEvent)=\"handleRemoveItem(undefined, $event)\"\n [class]=\"'dcf-fieldset ' + operation\"\n #component>\n <ion-accordion-group [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" (validationErrorEvent)=\"handleValidationError($event)\" #accordionComponent>\n <ion-accordion value=\"open\">\n <ion-item slot=\"header\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ name | translate }}</legend>\n </div>\n @if(!isRequired && ['create', 'update'].includes(operation)) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleRemoveComponent($event)\">\n <ion-icon name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if(multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if(item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n @if(!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem(item.title, $index)\">\n <ion-icon name=\"create-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n }\n\n @if(!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleRemoveItem(item.title)\">\n <ion-icon name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n <ng-content select=\"[slot=content]\"></ng-content>\n\n @if(multiple && ['create', 'update'].includes(operation)) {\n @if(isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n <div class=\"dcf-margin-bottom dcf-grid dcf-grid-collapse dcf-flex\">\n @if(updatingItem) {\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ buttonCancelLabel }}\n </ion-button>\n }\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" (click)=\"handleCreateItem()\">\n <ion-icon name=\"add-outline\" slot=\"start\"></ion-icon>\n {{buttonLabel}}\n </ion-button>\n\n </div>\n }\n\n </div>\n </ion-accordion>\n </ion-accordion-group>\n</fieldset>\n\n", styles: ["ion-accordion-group ion-item[slot=header] .dcf-delete{width:30px}ion-accordion-group ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion-group ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}::ng-deep ion-accordion ngx-decaf-crud-field:last-child ion-item{--inner-border-width: 0px !important;--border-width: 0px !important}.dcf-fieldset{margin-bottom:1.8rem;margin-top:1rem;padding-bottom:0;padding-top:1rem;background:var(--dcf-card-background);border-radius:6px;height:100%}@media (prefers-color-scheme: light){.dcf-fieldset{border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset .dcf-button-add{color:var(--ion-color-dark)!important}}@media (prefers-color-scheme: dark){.dcf-fieldset{border:1px solid var(--dcf-color-step-400)}.dcf-fieldset .dcf-button-add{color:var(--ion-color-gray-2)}}.dcf-fieldset.read,.dcf-fieldset.delete{margin-top:1.25rem;padding-bottom:1rem}.dcf-fieldset.read [slot=content],.dcf-fieldset.delete [slot=content]{padding-top:0!important}.dcf-fieldset.read ion-accordion,.dcf-fieldset.delete ion-accordion{margin-bottom:0rem!important}@media (prefers-color-scheme: dark){.dcf-fieldset.read,.dcf-fieldset.delete{border:1px solid var(--dcf-color-gray-6)}}.dcf-fieldset ion-accordion{background:var(--dcf-card-background);margin-bottom:1rem}.dcf-fieldset ion-accordion.accordion-collapsing,.dcf-fieldset ion-accordion.accordion-collapsed{margin-bottom:1rem}.dcf-fieldset ion-accordion ion-item[slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: 12px}.dcf-fieldset ion-accordion ion-item[slot=header] legend{font-weight:600;font-size:1rem;margin:0}@media (prefers-color-scheme: light){.dcf-fieldset ion-accordion ion-item[slot=header] legend{color:var(--dcf-color-gray-7)}}.dcf-fieldset ion-accordion [slot=content]{padding-top:2rem!important;padding-inline:.75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:1rem;flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{margin-top:-1rem;margin-bottom:1rem;padding:0!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important;border:1px solid transparent;box-sizing:border-box}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:1rem;transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.8rem;color:var(--dcf-color-gray-7)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: IonAccordionGroup, selector: "ion-accordion-group", inputs: ["animated", "disabled", "expand", "mode", "multiple", "readonly", "value"] }, { kind: "component", type: IonAccordion, selector: "ion-accordion", inputs: ["disabled", "mode", "readonly", "toggleIcon", "toggleIconSlot", "value"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonReorder, selector: "ion-reorder" }, { kind: "component", type: IonReorderGroup, selector: "ion-reorder-group", inputs: ["disabled"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
|
|
4997
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FieldsetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4998
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: FieldsetComponent, isStandalone: true, selector: "ngx-decaf-fieldset", inputs: { name: "name", childOf: "childOf", page: "page", uid: "uid", customTypes: "customTypes", operation: "operation", formGroup: "formGroup", title: "title", description: "description", target: "target", multiple: "multiple", value: "value", handlers: "handlers" }, host: { properties: { "attr.id": "overriode " } }, viewQueries: [{ propertyName: "accordionComponent", first: true, predicate: ["accordionComponent"], descendants: true }], usesInheritance: true, ngImport: i0, template: "\n\n<fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n (fieldsetRemoveGroupEvent)=\"handleRemoveItem(undefined, $event)\"\n [class]=\"'dcf-fieldset ' + operation\"\n #component>\n <ion-accordion-group [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" (validationErrorEvent)=\"handleValidationError($event)\" #accordionComponent>\n <ion-accordion value=\"open\">\n <ion-item slot=\"header\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ name | translate }}</legend>\n </div>\n @if(!isRequired && ['create', 'update'].includes(operation)) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleRemoveComponent($event)\">\n <ion-icon name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if(multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if(item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n @if(!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem(item.title, $index)\">\n <ion-icon name=\"create-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n }\n\n @if(!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleRemoveItem(item.title)\">\n <ion-icon name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n <ng-content select=\"[slot=content]\"></ng-content>\n\n @if(multiple && ['create', 'update'].includes(operation)) {\n @if(isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n <div class=\"dcf-margin-bottom dcf-grid dcf-grid-collapse dcf-flex\">\n @if(updatingItem) {\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ buttonCancelLabel }}\n </ion-button>\n }\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" (click)=\"handleCreateItem()\">\n <ion-icon name=\"add-outline\" slot=\"start\"></ion-icon>\n {{buttonLabel}}\n </ion-button>\n\n </div>\n }\n\n </div>\n </ion-accordion>\n </ion-accordion-group>\n</fieldset>\n\n", styles: ["ion-accordion-group ion-item[slot=header] .dcf-delete{width:30px}ion-accordion-group ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion-group ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}::ng-deep ion-accordion ngx-decaf-crud-field:last-child ion-item{--inner-border-width: 0px !important;--border-width: 0px !important}@media (prefers-color-scheme: light){.dcf-fieldset{border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset .dcf-button-add{color:var(--ion-color-dark)!important}ion-accordion ion-item[slot=header] legend{color:var(--dcf-color-gray-7)}}@media (prefers-color-scheme: dark){.dcf-fieldset{border:1px solid var(--dcf-color-step-400)}.dcf-fieldset .dcf-button-add{color:var(--ion-color-gray-2)}.dcf-fieldset.read,.dcf-fieldset.delete{border:1px solid var(--dcf-color-gray-6)}}.dcf-fieldset{margin-bottom:1.8rem;margin-top:1rem;padding-bottom:0;padding-top:1rem;background:var(--dcf-card-background);border-radius:6px;height:100%}.dcf-fieldset.read,.dcf-fieldset.delete{margin-top:1.25rem;padding-bottom:1rem}.dcf-fieldset.read [slot=content],.dcf-fieldset.delete [slot=content]{padding-top:0!important}.dcf-fieldset.read ion-accordion,.dcf-fieldset.delete ion-accordion{margin-bottom:0rem!important}.dcf-fieldset ion-accordion{background:var(--dcf-card-background);margin-bottom:1rem}.dcf-fieldset ion-accordion.accordion-collapsing,.dcf-fieldset ion-accordion.accordion-collapsed{margin-bottom:1rem}.dcf-fieldset ion-accordion ion-item[slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: 12px}.dcf-fieldset ion-accordion ion-item[slot=header] legend{font-weight:600;font-size:1rem;margin:0}.dcf-fieldset ion-accordion [slot=content]{padding-top:2rem!important;padding-inline:.75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:1rem;flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{margin-top:-1rem;margin-bottom:1rem;padding:0!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important;border:1px solid transparent;box-sizing:border-box}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:1rem;transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.8rem;color:var(--dcf-color-gray-7)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: IonAccordionGroup, selector: "ion-accordion-group", inputs: ["animated", "disabled", "expand", "mode", "multiple", "readonly", "value"] }, { kind: "component", type: IonAccordion, selector: "ion-accordion", inputs: ["disabled", "mode", "readonly", "toggleIcon", "toggleIconSlot", "value"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonReorder, selector: "ion-reorder" }, { kind: "component", type: IonReorderGroup, selector: "ion-reorder-group", inputs: ["disabled"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
5001
4999
|
};
|
|
5002
5000
|
FieldsetComponent = __decorate([
|
|
5003
5001
|
Dynamic(),
|
|
5004
5002
|
__metadata("design:paramtypes", [])
|
|
5005
5003
|
], FieldsetComponent);
|
|
5006
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
5004
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FieldsetComponent, decorators: [{
|
|
5007
5005
|
type: Component,
|
|
5008
5006
|
args: [{ standalone: true, selector: 'ngx-decaf-fieldset', schemas: [], imports: [
|
|
5009
5007
|
TranslatePipe,
|
|
@@ -5018,7 +5016,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
5018
5016
|
IonReorderGroup,
|
|
5019
5017
|
IonButton,
|
|
5020
5018
|
IonIcon,
|
|
5021
|
-
], host: { '[attr.id]': 'overriode ' }, template: "\n\n<fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n (fieldsetRemoveGroupEvent)=\"handleRemoveItem(undefined, $event)\"\n [class]=\"'dcf-fieldset ' + operation\"\n #component>\n <ion-accordion-group [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" (validationErrorEvent)=\"handleValidationError($event)\" #accordionComponent>\n <ion-accordion value=\"open\">\n <ion-item slot=\"header\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ name | translate }}</legend>\n </div>\n @if(!isRequired && ['create', 'update'].includes(operation)) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleRemoveComponent($event)\">\n <ion-icon name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if(multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if(item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n @if(!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem(item.title, $index)\">\n <ion-icon name=\"create-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n }\n\n @if(!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleRemoveItem(item.title)\">\n <ion-icon name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n <ng-content select=\"[slot=content]\"></ng-content>\n\n @if(multiple && ['create', 'update'].includes(operation)) {\n @if(isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n <div class=\"dcf-margin-bottom dcf-grid dcf-grid-collapse dcf-flex\">\n @if(updatingItem) {\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ buttonCancelLabel }}\n </ion-button>\n }\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" (click)=\"handleCreateItem()\">\n <ion-icon name=\"add-outline\" slot=\"start\"></ion-icon>\n {{buttonLabel}}\n </ion-button>\n\n </div>\n }\n\n </div>\n </ion-accordion>\n </ion-accordion-group>\n</fieldset>\n\n", styles: ["ion-accordion-group ion-item[slot=header] .dcf-delete{width:30px}ion-accordion-group ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion-group ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}::ng-deep ion-accordion ngx-decaf-crud-field:last-child ion-item{--inner-border-width: 0px !important;--border-width: 0px !important}
|
|
5019
|
+
], host: { '[attr.id]': 'overriode ' }, template: "\n\n<fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n (fieldsetRemoveGroupEvent)=\"handleRemoveItem(undefined, $event)\"\n [class]=\"'dcf-fieldset ' + operation\"\n #component>\n <ion-accordion-group [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" (validationErrorEvent)=\"handleValidationError($event)\" #accordionComponent>\n <ion-accordion value=\"open\">\n <ion-item slot=\"header\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ name | translate }}</legend>\n </div>\n @if(!isRequired && ['create', 'update'].includes(operation)) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleRemoveComponent($event)\">\n <ion-icon name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if(multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if(item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n @if(!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem(item.title, $index)\">\n <ion-icon name=\"create-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n }\n\n @if(!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleRemoveItem(item.title)\">\n <ion-icon name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n <ng-content select=\"[slot=content]\"></ng-content>\n\n @if(multiple && ['create', 'update'].includes(operation)) {\n @if(isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n <div class=\"dcf-margin-bottom dcf-grid dcf-grid-collapse dcf-flex\">\n @if(updatingItem) {\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ buttonCancelLabel }}\n </ion-button>\n }\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" (click)=\"handleCreateItem()\">\n <ion-icon name=\"add-outline\" slot=\"start\"></ion-icon>\n {{buttonLabel}}\n </ion-button>\n\n </div>\n }\n\n </div>\n </ion-accordion>\n </ion-accordion-group>\n</fieldset>\n\n", styles: ["ion-accordion-group ion-item[slot=header] .dcf-delete{width:30px}ion-accordion-group ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion-group ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}::ng-deep ion-accordion ngx-decaf-crud-field:last-child ion-item{--inner-border-width: 0px !important;--border-width: 0px !important}@media (prefers-color-scheme: light){.dcf-fieldset{border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset .dcf-button-add{color:var(--ion-color-dark)!important}ion-accordion ion-item[slot=header] legend{color:var(--dcf-color-gray-7)}}@media (prefers-color-scheme: dark){.dcf-fieldset{border:1px solid var(--dcf-color-step-400)}.dcf-fieldset .dcf-button-add{color:var(--ion-color-gray-2)}.dcf-fieldset.read,.dcf-fieldset.delete{border:1px solid var(--dcf-color-gray-6)}}.dcf-fieldset{margin-bottom:1.8rem;margin-top:1rem;padding-bottom:0;padding-top:1rem;background:var(--dcf-card-background);border-radius:6px;height:100%}.dcf-fieldset.read,.dcf-fieldset.delete{margin-top:1.25rem;padding-bottom:1rem}.dcf-fieldset.read [slot=content],.dcf-fieldset.delete [slot=content]{padding-top:0!important}.dcf-fieldset.read ion-accordion,.dcf-fieldset.delete ion-accordion{margin-bottom:0rem!important}.dcf-fieldset ion-accordion{background:var(--dcf-card-background);margin-bottom:1rem}.dcf-fieldset ion-accordion.accordion-collapsing,.dcf-fieldset ion-accordion.accordion-collapsed{margin-bottom:1rem}.dcf-fieldset ion-accordion ion-item[slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: 12px}.dcf-fieldset ion-accordion ion-item[slot=header] legend{font-weight:600;font-size:1rem;margin:0}.dcf-fieldset ion-accordion [slot=content]{padding-top:2rem!important;padding-inline:.75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:1rem;flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{margin-top:-1rem;margin-bottom:1rem;padding:0!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important;border:1px solid transparent;box-sizing:border-box}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:1rem;transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.8rem;color:var(--dcf-color-gray-7)}\n"] }]
|
|
5022
5020
|
}], ctorParameters: () => [], propDecorators: { accordionComponent: [{
|
|
5023
5021
|
type: ViewChild,
|
|
5024
5022
|
args: ['accordionComponent', { static: false }]
|
|
@@ -5476,10 +5474,10 @@ class SearchbarComponent extends NgxBaseComponent {
|
|
|
5476
5474
|
preventChange(event) {
|
|
5477
5475
|
event.preventDefault();
|
|
5478
5476
|
}
|
|
5479
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
5480
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
5477
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SearchbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5478
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "20.3.2", type: SearchbarComponent, isStandalone: true, selector: "ngx-decaf-searchbar", inputs: { autocomplete: "autocomplete", autocorrect: "autocorrect", animated: "animated", buttonCancelText: "buttonCancelText", clearIcon: "clearIcon", color: "color", debounce: "debounce", disabled: "disabled", enterkeyhint: "enterkeyhint", inputmode: "inputmode", placeholder: "placeholder", searchIcon: "searchIcon", showCancelButton: "showCancelButton", showClearButton: "showClearButton", spellcheck: "spellcheck", type: "type", value: "value", queryKeys: "queryKeys", isVisible: "isVisible", wrapper: "wrapper", wrapperColor: "wrapperColor", emitEventToWindow: "emitEventToWindow" }, outputs: { searchEvent: "searchEvent" }, host: { listeners: { "window:toggleSearchbarVisibility": "handleToggleVisibility($event)" } }, usesInheritance: true, ngImport: i0, template: "<ion-searchbar\n [id]=\"uid\"\n ngClass=\"dcf-searchbar\"\n name=\"search\"\n mode=\"ios\"\n (keyup.enter)=\"preventChange($event)\"\n (ionChange)=\"handleChange($event)\"\n (ionInput)=\"handleInput($event)\"\n (ionClear)=\"handleClear()\"\n [autocomplete]=\"autocomplete\"\n [showCancelButton]=\"showCancelButton\"\n [cancelButtonText]=\"buttonCancelText\"\n [clearIcon]=\"clearIcon\"\n [color]=\"color\"\n [debounce]=\"debounce\"\n [disabled]=\"disabled\"\n [enterkeyhint]=\"enterkeyhint\"\n [inputmode]=\"inputmode\"\n [placeholder]=\"placeholder\"\n [searchIcon]=\"searchIcon\"\n [showClearButton]=\"showClearButton\"\n [spellcheck]=\"spellcheck\"\n [type]=\"type\"\n #component\n />\n", styles: [""], dependencies: [{ kind: "component", type: IonSearchbar, selector: "ion-searchbar", inputs: ["animated", "autocomplete", "autocorrect", "cancelButtonIcon", "cancelButtonText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "mode", "name", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value"] }] }); }
|
|
5481
5479
|
}
|
|
5482
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
5480
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SearchbarComponent, decorators: [{
|
|
5483
5481
|
type: Component,
|
|
5484
5482
|
args: [{ selector: 'ngx-decaf-searchbar', standalone: true, imports: [IonSearchbar], template: "<ion-searchbar\n [id]=\"uid\"\n ngClass=\"dcf-searchbar\"\n name=\"search\"\n mode=\"ios\"\n (keyup.enter)=\"preventChange($event)\"\n (ionChange)=\"handleChange($event)\"\n (ionInput)=\"handleInput($event)\"\n (ionClear)=\"handleClear()\"\n [autocomplete]=\"autocomplete\"\n [showCancelButton]=\"showCancelButton\"\n [cancelButtonText]=\"buttonCancelText\"\n [clearIcon]=\"clearIcon\"\n [color]=\"color\"\n [debounce]=\"debounce\"\n [disabled]=\"disabled\"\n [enterkeyhint]=\"enterkeyhint\"\n [inputmode]=\"inputmode\"\n [placeholder]=\"placeholder\"\n [searchIcon]=\"searchIcon\"\n [showClearButton]=\"showClearButton\"\n [spellcheck]=\"spellcheck\"\n [type]=\"type\"\n #component\n />\n" }]
|
|
5485
5483
|
}], ctorParameters: () => [], propDecorators: { autocomplete: [{
|
|
@@ -6178,20 +6176,18 @@ let FilterComponent = class FilterComponent extends NgxBaseComponent {
|
|
|
6178
6176
|
handleSearch(value) {
|
|
6179
6177
|
this.searchEvent.emit(value);
|
|
6180
6178
|
}
|
|
6181
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6182
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: FilterComponent, isStandalone: true, selector: "ngx-decaf-filter", inputs: { indexes: "indexes", conditions: "conditions", sortBy: "sortBy", disableSort: "disableSort" }, outputs: { filterEvent: "filterEvent", searchEvent: "searchEvent" }, viewQueries: [{ propertyName: "optionsFilterElement", first: true, predicate: ["optionsFilterElement"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "\n@if(!indexes.length) {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n}\n\n<div [id]=\"uid\" class=\"dcf-grid dcf-grid-small dcf-grid-match dcf-filter-grid\" [class.dcf-hidden]=\"!indexes.length\">\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-filter\">\n <div class=\"dcf-input\">\n @for(filter of filterValue; track trackItemFn($index, filter?.['index'])) {\n @if(filter?.['index']) {\n <ion-chip [outline]=\"true\">{{ filter?.['index'] }}</ion-chip>\n }\n @if(filter?.['condition']) {\n <ion-chip [outline]=\"true\">{{ filter?.['condition'] }}</ion-chip>\n }\n @if(filter?.['value']) {\n <ion-chip [outline]=\"true\" class=\"dcf-filter-value\">\n {{ filter?.['value'] }}\n <ion-icon name=\"close\" (click)=\"removeFilter(filter?.['value'])\" size=\"small\"></ion-icon>\n </ion-chip>\n }\n }\n <div class=\"dcf-width-1-1\">\n <!-- [readonly]=\"step !== 3\" -->\n <input\n fill=\"none\"\n [(ngModel)]=\"value\"\n (keydown.enter)=\"addFilter(value, $event)\"\n (keydown.backspace)=\"clear(value)\"\n (input)=\"handleInput($event)\"\n (click)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n type=\"text\"\n\n placeholder=\"{{ locale + (step === 3 ? '.type' : '.select') | translate }}\"\n #component\n />\n @if(windowWidth >= 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if(filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if(filterValue.length > 0) {\n <div class=\"dcf-icon-clear\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"clear()\">\n <ion-icon name=\"trash-outline\" [color]=\"!isDarkMode ? 'dark' : 'medium'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n <div class=\"dcf-icon-search\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"submit()\">\n <ion-icon name=\"search-outline\" [color]=\"!isDarkMode ? 'dark' : 'medium'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n </div>\n @if(windowWidth < 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if(filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n @if(!disableSort) {\n <div class=\"dcf-width-1-5@m dcf-width-1-1 dcf-sort-container\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-grid-match\">\n <div class=\"dcf-width-expand\">\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n class=\"dcf-sort-select\"\n (ionChange)=\"handleSortChange($event)\"\n interface=\"popover\"\n [value]=\"sortValue\"\n label-placement=\"floating\"\n fill=\"outline\"\n [label]=\"locale + '.sort' | translate\"\n >\n @for(sort of sortBy; track sort) {\n\n <ion-select-option [value]=\"sort\">{{ sort | translate }}</ion-select-option>\n }\n </ion-select>\n </div>\n <div class=\"dcf-width-auto\">\n <ion-button (click)=\"handleSortDirectionChange()\" fill=\"clear\">\n <ion-icon slot=\"icon-only\" [color]=\"!isDarkMode ? 'primary' : 'medium'\" [name]=\"sortDirection === 'desc' ? 'arrow-down-outline' : 'arrow-up-outline'\"></ion-icon>\n </ion-button>\n </div>\n </div>\n </div>\n }\n</div>\n\n\n", styles: [".dcf-filter-grid{padding:0 .5rem;margin-top:.75rem;margin-bottom:.75rem}ion-select{min-height:44px!important}.dcf-hidden{display:none!important}.dcf-filter{display:flex;width:100%;min-height:40px;box-shadow:0 1px 2px #0a0d120d;border-radius:var(--dcf-border-radius);box-sizing:border-box}@media (prefers-color-scheme: light){.dcf-filter{border:1px solid var(--dcf-color-gray-3);background-color:#fff}.dcf-filter:focus-within{border-color:var(--dcf-color-primary);background-color:#fff}}@media (prefers-color-scheme: dark){.dcf-filter{border:1px solid var(--dcf-color-step-500)}.dcf-filter ::-webkit-input-placeholder,.dcf-filter ::placeholder{color:var(--dcf-color-gray-4)!important}.dcf-filter:hover{border-color:var(--dcf-color-gray-2)}.dcf-filter:focus-within{border-color:var(--dcf-color-gray-2)}}.dcf-filter ion-chip{border-radius:6px;padding:0 8px!important;height:24px;min-height:24px;font-size:.75rem;font-style:normal;font-weight:500;flex-shrink:0;margin-right:2px;white-space:nowrap}@media (prefers-color-scheme: light){.dcf-filter ion-chip{border:1px solid var(--dcf-color-gray-3);color:var(--dcf-color-gray-7)}.dcf-filter ion-chip.dcf-filter-value{background:var(--dcf-color-gray-2);border-color:var(--dcf-color-gray-4)!important;color:var(--dcf-color-gray-8)!important}}@media (prefers-color-scheme: dark){.dcf-filter ion-chip{border-color:var(--dcf-color-step-300);background:rgba(var(--dcf-color-medium-rgb),.1)}.dcf-filter ion-chip.dcf-filter-value{background:rgba(var(--dcf-color-medium-rgb),.3)!important;border-color:var(--dcf-color-step-500)}}.dcf-filter ion-chip.sc-ion-chip-md-h,.dcf-filter ion-chip.sc-ion-chip-ios-h{height:24px;min-height:24px}.dcf-filter ion-chip.sc-ion-chip-md-h .chip-native,.dcf-filter ion-chip.sc-ion-chip-ios-h .chip-native{padding:0 8px!important;height:24px;min-height:24px}.dcf-filter ion-chip ion-label{padding:0 4px;margin:0;font-size:.75rem;white-space:nowrap}.dcf-filter ion-chip ion-icon{margin:0 2px;font-size:.75rem}.dcf-filter .dcf-input{width:100%;display:flex;align-items:center;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding-left:.5rem}.dcf-filter .dcf-input input{min-height:40px;min-width:100px;width:100%;font-size:1rem;border:none;outline:none;background:transparent;border:0px!important;outline:none!important}@media (prefers-color-scheme: light){.dcf-filter .dcf-input input{color:var(--dcf-color-gray-7)}}@media (prefers-color-scheme: dark){.dcf-filter .dcf-input input{color:var(--dcf-color-gray-1)}}.dcf-filter .dcf-input input:focus{border:0px!important;outline:none!important}.dcf-filter .dcf-icon-clear,.dcf-filter .dcf-icon-search{display:flex;justify-content:center;text-align:center;align-items:center;min-width:40px}.dcf-filter .dcf-icon-search ion-icon{font-size:1.25rem}.dcf-sort-container{min-width:200px!important;width:auto}@media (min-width: 990px){.dcf-sort-container{max-width:20%!important}}@media (max-width: 680px){.dcf-sort-container{min-width:100%!important;margin:.75rem 0rem}}.dcf-dropdown{position:absolute;max-height:200px;overflow-y:auto;border-radius:4px;z-index:1000!important;min-width:200px;max-width:300px;display:none}@media (prefers-color-scheme: light){.dcf-dropdown{background-color:#fff}.dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-gray-2)}}@media (prefers-color-scheme: dark){.dcf-dropdown{background-color:var(--dcf-item-background)}.dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-step-600)}}.dcf-dropdown.dcf-active{display:block;margin-top:-3px;box-shadow:0 12px 16px -4px #0a0d1214,0 4px 6px -2px #0a0d1208,0 2px 2px -1px #0a0d120a!important;border-radius:var(--dcf-border-radius);padding:.5rem .25rem}@media (max-width: 768px){.dcf-dropdown.dcf-active{margin-top:55px}}.dcf-dropdown.dcf-active>div>div{cursor:pointer;height:35px;padding:.5rem 1rem;border:1px solid transparent;font-size:1rem;display:flex;align-items:center;border-radius:6px}@media (prefers-color-scheme: light){.dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-8)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-3)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{pointer-events:none;touch-action:none;cursor:text!important;border-color:transparent!important}.dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-1)}}@media (prefers-color-scheme: dark){.dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-1)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-5)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{cursor:text!important;pointer-events:none;touch-action:none;border-color:transparent!important}.dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-8)}}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "component", type: IonChip, selector: "ion-chip", inputs: ["color", "disabled", "mode", "outline"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: SearchbarComponent, selector: "ngx-decaf-searchbar", inputs: ["autocomplete", "autocorrect", "animated", "buttonCancelText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value", "queryKeys", "isVisible", "wrapper", "wrapperColor", "emitEventToWindow"], outputs: ["searchEvent"] }] }); }
|
|
6179
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6180
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: FilterComponent, isStandalone: true, selector: "ngx-decaf-filter", inputs: { indexes: "indexes", conditions: "conditions", sortBy: "sortBy", disableSort: "disableSort" }, outputs: { filterEvent: "filterEvent", searchEvent: "searchEvent" }, viewQueries: [{ propertyName: "optionsFilterElement", first: true, predicate: ["optionsFilterElement"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "\n@if(!indexes.length) {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n}\n\n<div [id]=\"uid\" class=\"dcf-grid dcf-grid-small dcf-grid-match dcf-filter-grid\" [class.dcf-hidden]=\"!indexes.length\">\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-filter\">\n <div class=\"dcf-input\">\n @for(filter of filterValue; track trackItemFn($index, filter?.['index'])) {\n @if(filter?.['index']) {\n <ion-chip [outline]=\"true\">{{ filter?.['index'] }}</ion-chip>\n }\n @if(filter?.['condition']) {\n <ion-chip [outline]=\"true\">{{ filter?.['condition'] }}</ion-chip>\n }\n @if(filter?.['value']) {\n <ion-chip [outline]=\"true\" class=\"dcf-filter-value\">\n {{ filter?.['value'] }}\n <ion-icon name=\"close\" (click)=\"removeFilter(filter?.['value'])\" size=\"small\"></ion-icon>\n </ion-chip>\n }\n }\n <div class=\"dcf-width-1-1\">\n <!-- [readonly]=\"step !== 3\" -->\n <input\n fill=\"none\"\n [(ngModel)]=\"value\"\n (keydown.enter)=\"addFilter(value, $event)\"\n (keydown.backspace)=\"clear(value)\"\n (input)=\"handleInput($event)\"\n (click)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n type=\"text\"\n\n placeholder=\"{{ locale + (step === 3 ? '.type' : '.select') | translate }}\"\n #component\n />\n @if(windowWidth >= 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if(filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if(filterValue.length > 0) {\n <div class=\"dcf-icon-clear\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"clear()\">\n <ion-icon name=\"trash-outline\" [color]=\"!isDarkMode ? 'dark' : 'medium'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n <div class=\"dcf-icon-search\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"submit()\">\n <ion-icon name=\"search-outline\" [color]=\"!isDarkMode ? 'dark' : 'medium'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n </div>\n @if(windowWidth < 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if(filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n @if(!disableSort) {\n <div class=\"dcf-width-1-5@m dcf-width-1-1 dcf-sort-container\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-grid-match\">\n <div class=\"dcf-width-expand\">\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n class=\"dcf-sort-select\"\n (ionChange)=\"handleSortChange($event)\"\n interface=\"popover\"\n [value]=\"sortValue\"\n label-placement=\"floating\"\n fill=\"outline\"\n [label]=\"locale + '.sort' | translate\"\n >\n @for(sort of sortBy; track sort) {\n\n <ion-select-option [value]=\"sort\">{{ sort | translate }}</ion-select-option>\n }\n </ion-select>\n </div>\n <div class=\"dcf-width-auto\">\n <ion-button (click)=\"handleSortDirectionChange()\" fill=\"clear\">\n <ion-icon slot=\"icon-only\" [color]=\"!isDarkMode ? 'primary' : 'medium'\" [name]=\"sortDirection === 'desc' ? 'arrow-down-outline' : 'arrow-up-outline'\"></ion-icon>\n </ion-button>\n </div>\n </div>\n </div>\n }\n</div>\n\n\n", styles: ["@media (prefers-color-scheme: light){.dcf-filter{border:1px solid var(--dcf-color-gray-3);background-color:#fff}.dcf-filter:focus-within{border-color:var(--dcf-color-primary);background-color:#fff}ion-chip{border:1px solid var(--dcf-color-gray-3);color:var(--dcf-color-gray-7)}ion-chip.dcf-filter-value{background:var(--dcf-color-gray-2);border-color:var(--dcf-color-gray-4)!important;color:var(--dcf-color-gray-8)!important}.dcf-input input{color:var(--dcf-color-gray-7)}.dcf-dropdown{background-color:#fff}.dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-gray-2)}.dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-8)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-3)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{pointer-events:none;touch-action:none;cursor:text!important;border-color:transparent!important}.dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-1)}}@media (prefers-color-scheme: dark){.dcf-filter{border:1px solid var(--dcf-color-step-500)}.dcf-filter ::-webkit-input-placeholder,.dcf-filter ::placeholder{color:var(--dcf-color-gray-4)!important}.dcf-filter:hover{border-color:var(--dcf-color-gray-2)}.dcf-filter:focus-within{border-color:var(--dcf-color-gray-2)}ion-chip{border-color:var(--dcf-color-step-300);background:rgba(var(--dcf-color-medium-rgb),.1)}ion-chip.dcf-filter-value{background:rgba(var(--dcf-color-medium-rgb),.3)!important;border-color:var(--dcf-color-step-500)}.dcf-input input{color:var(--dcf-color-gray-1)}.dcf-dropdown{background-color:var(--dcf-item-background)}.dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-step-600)}.dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-1)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-5)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{cursor:text!important;pointer-events:none;touch-action:none;border-color:transparent!important}.dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-8)}}.dcf-filter-grid{padding:0 .5rem;margin-top:.75rem;margin-bottom:.75rem}ion-select{min-height:44px!important}.dcf-hidden{display:none!important}.dcf-filter{display:flex;width:100%;min-height:40px;box-shadow:0 1px 2px #0a0d120d;border-radius:var(--dcf-border-radius);box-sizing:border-box}.dcf-filter ion-chip{border-radius:6px;padding:0 8px!important;height:24px;min-height:24px;font-size:.75rem;font-style:normal;font-weight:500;flex-shrink:0;margin-right:2px;white-space:nowrap}.dcf-filter ion-chip.sc-ion-chip-md-h,.dcf-filter ion-chip.sc-ion-chip-ios-h{height:24px;min-height:24px}.dcf-filter ion-chip.sc-ion-chip-md-h .chip-native,.dcf-filter ion-chip.sc-ion-chip-ios-h .chip-native{padding:0 8px!important;height:24px;min-height:24px}.dcf-filter ion-chip ion-label{padding:0 4px;margin:0;font-size:.75rem;white-space:nowrap}.dcf-filter ion-chip ion-icon{margin:0 2px;font-size:.75rem}.dcf-filter .dcf-input{width:100%;display:flex;align-items:center;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding-left:.5rem}.dcf-filter .dcf-input input{min-height:40px;min-width:100px;width:100%;font-size:1rem;border:none;outline:none;background:transparent;border:0px!important;outline:none!important}.dcf-filter .dcf-input input:focus{border:0px!important;outline:none!important}.dcf-filter .dcf-icon-clear,.dcf-filter .dcf-icon-search{display:flex;justify-content:center;text-align:center;align-items:center;min-width:40px}.dcf-filter .dcf-icon-search ion-icon{font-size:1.25rem}.dcf-sort-container{min-width:200px!important;width:auto}@media (min-width: 990px){.dcf-sort-container{max-width:20%!important}}@media (max-width: 680px){.dcf-sort-container{min-width:100%!important;margin:.75rem 0rem}}.dcf-dropdown{position:absolute;max-height:200px;overflow-y:auto;border-radius:4px;z-index:1000!important;min-width:200px;max-width:300px;display:none}.dcf-dropdown.dcf-active{display:block;margin-top:-3px;box-shadow:0 12px 16px -4px #0a0d1214,0 4px 6px -2px #0a0d1208,0 2px 2px -1px #0a0d120a!important;border-radius:var(--dcf-border-radius);padding:.5rem .25rem}@media (max-width: 768px){.dcf-dropdown.dcf-active{margin-top:55px}}.dcf-dropdown.dcf-active>div>div{cursor:pointer;height:35px;padding:.5rem 1rem;border:1px solid transparent;font-size:1rem;display:flex;align-items:center;border-radius:6px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: IonChip, selector: "ion-chip", inputs: ["color", "disabled", "mode", "outline"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: SearchbarComponent, selector: "ngx-decaf-searchbar", inputs: ["autocomplete", "autocorrect", "animated", "buttonCancelText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value", "queryKeys", "isVisible", "wrapper", "wrapperColor", "emitEventToWindow"], outputs: ["searchEvent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
6183
6181
|
};
|
|
6184
6182
|
FilterComponent = __decorate([
|
|
6185
6183
|
Dynamic(),
|
|
6186
6184
|
__metadata("design:paramtypes", [])
|
|
6187
6185
|
], FilterComponent);
|
|
6188
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6186
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FilterComponent, decorators: [{
|
|
6189
6187
|
type: Component,
|
|
6190
6188
|
args: [{ selector: 'ngx-decaf-filter', imports: [
|
|
6191
6189
|
FormsModule,
|
|
6192
6190
|
TranslatePipe,
|
|
6193
|
-
IonLabel,
|
|
6194
|
-
IonItem,
|
|
6195
6191
|
IonChip,
|
|
6196
6192
|
IonIcon,
|
|
6197
6193
|
IonButton,
|
|
@@ -6199,7 +6195,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
6199
6195
|
IonSelectOption,
|
|
6200
6196
|
IonIcon,
|
|
6201
6197
|
SearchbarComponent
|
|
6202
|
-
], standalone: true, template: "\n@if(!indexes.length) {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n}\n\n<div [id]=\"uid\" class=\"dcf-grid dcf-grid-small dcf-grid-match dcf-filter-grid\" [class.dcf-hidden]=\"!indexes.length\">\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-filter\">\n <div class=\"dcf-input\">\n @for(filter of filterValue; track trackItemFn($index, filter?.['index'])) {\n @if(filter?.['index']) {\n <ion-chip [outline]=\"true\">{{ filter?.['index'] }}</ion-chip>\n }\n @if(filter?.['condition']) {\n <ion-chip [outline]=\"true\">{{ filter?.['condition'] }}</ion-chip>\n }\n @if(filter?.['value']) {\n <ion-chip [outline]=\"true\" class=\"dcf-filter-value\">\n {{ filter?.['value'] }}\n <ion-icon name=\"close\" (click)=\"removeFilter(filter?.['value'])\" size=\"small\"></ion-icon>\n </ion-chip>\n }\n }\n <div class=\"dcf-width-1-1\">\n <!-- [readonly]=\"step !== 3\" -->\n <input\n fill=\"none\"\n [(ngModel)]=\"value\"\n (keydown.enter)=\"addFilter(value, $event)\"\n (keydown.backspace)=\"clear(value)\"\n (input)=\"handleInput($event)\"\n (click)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n type=\"text\"\n\n placeholder=\"{{ locale + (step === 3 ? '.type' : '.select') | translate }}\"\n #component\n />\n @if(windowWidth >= 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if(filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if(filterValue.length > 0) {\n <div class=\"dcf-icon-clear\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"clear()\">\n <ion-icon name=\"trash-outline\" [color]=\"!isDarkMode ? 'dark' : 'medium'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n <div class=\"dcf-icon-search\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"submit()\">\n <ion-icon name=\"search-outline\" [color]=\"!isDarkMode ? 'dark' : 'medium'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n </div>\n @if(windowWidth < 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if(filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n @if(!disableSort) {\n <div class=\"dcf-width-1-5@m dcf-width-1-1 dcf-sort-container\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-grid-match\">\n <div class=\"dcf-width-expand\">\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n class=\"dcf-sort-select\"\n (ionChange)=\"handleSortChange($event)\"\n interface=\"popover\"\n [value]=\"sortValue\"\n label-placement=\"floating\"\n fill=\"outline\"\n [label]=\"locale + '.sort' | translate\"\n >\n @for(sort of sortBy; track sort) {\n\n <ion-select-option [value]=\"sort\">{{ sort | translate }}</ion-select-option>\n }\n </ion-select>\n </div>\n <div class=\"dcf-width-auto\">\n <ion-button (click)=\"handleSortDirectionChange()\" fill=\"clear\">\n <ion-icon slot=\"icon-only\" [color]=\"!isDarkMode ? 'primary' : 'medium'\" [name]=\"sortDirection === 'desc' ? 'arrow-down-outline' : 'arrow-up-outline'\"></ion-icon>\n </ion-button>\n </div>\n </div>\n </div>\n }\n</div>\n\n\n", styles: [".dcf-filter-grid{padding:0 .5rem;margin-top:.75rem;margin-bottom:.75rem}ion-select{min-height:44px!important}.dcf-hidden{display:none!important}.dcf-filter{display:flex;width:100%;min-height:40px;box-shadow:0 1px 2px #0a0d120d;border-radius:var(--dcf-border-radius);box-sizing:border-box}@media (prefers-color-scheme: light){.dcf-filter{border:1px solid var(--dcf-color-gray-3);background-color:#fff}.dcf-filter:focus-within{border-color:var(--dcf-color-primary);background-color:#fff}}@media (prefers-color-scheme: dark){.dcf-filter{border:1px solid var(--dcf-color-step-500)}.dcf-filter ::-webkit-input-placeholder,.dcf-filter ::placeholder{color:var(--dcf-color-gray-4)!important}.dcf-filter:hover{border-color:var(--dcf-color-gray-2)}.dcf-filter:focus-within{border-color:var(--dcf-color-gray-2)}}.dcf-filter ion-chip{border-radius:6px;padding:0 8px!important;height:24px;min-height:24px;font-size:.75rem;font-style:normal;font-weight:500;flex-shrink:0;margin-right:2px;white-space:nowrap}@media (prefers-color-scheme: light){.dcf-filter ion-chip{border:1px solid var(--dcf-color-gray-3);color:var(--dcf-color-gray-7)}.dcf-filter ion-chip.dcf-filter-value{background:var(--dcf-color-gray-2);border-color:var(--dcf-color-gray-4)!important;color:var(--dcf-color-gray-8)!important}}@media (prefers-color-scheme: dark){.dcf-filter ion-chip{border-color:var(--dcf-color-step-300);background:rgba(var(--dcf-color-medium-rgb),.1)}.dcf-filter ion-chip.dcf-filter-value{background:rgba(var(--dcf-color-medium-rgb),.3)!important;border-color:var(--dcf-color-step-500)}}.dcf-filter ion-chip.sc-ion-chip-md-h,.dcf-filter ion-chip.sc-ion-chip-ios-h{height:24px;min-height:24px}.dcf-filter ion-chip.sc-ion-chip-md-h .chip-native,.dcf-filter ion-chip.sc-ion-chip-ios-h .chip-native{padding:0 8px!important;height:24px;min-height:24px}.dcf-filter ion-chip ion-label{padding:0 4px;margin:0;font-size:.75rem;white-space:nowrap}.dcf-filter ion-chip ion-icon{margin:0 2px;font-size:.75rem}.dcf-filter .dcf-input{width:100%;display:flex;align-items:center;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding-left:.5rem}.dcf-filter .dcf-input input{min-height:40px;min-width:100px;width:100%;font-size:1rem;border:none;outline:none;background:transparent;border:0px!important;outline:none!important}@media (prefers-color-scheme: light){.dcf-filter .dcf-input input{color:var(--dcf-color-gray-7)}}@media (prefers-color-scheme: dark){.dcf-filter .dcf-input input{color:var(--dcf-color-gray-1)}}.dcf-filter .dcf-input input:focus{border:0px!important;outline:none!important}.dcf-filter .dcf-icon-clear,.dcf-filter .dcf-icon-search{display:flex;justify-content:center;text-align:center;align-items:center;min-width:40px}.dcf-filter .dcf-icon-search ion-icon{font-size:1.25rem}.dcf-sort-container{min-width:200px!important;width:auto}@media (min-width: 990px){.dcf-sort-container{max-width:20%!important}}@media (max-width: 680px){.dcf-sort-container{min-width:100%!important;margin:.75rem 0rem}}.dcf-dropdown{position:absolute;max-height:200px;overflow-y:auto;border-radius:4px;z-index:1000!important;min-width:200px;max-width:300px;display:none}@media (prefers-color-scheme: light){.dcf-dropdown{background-color:#fff}.dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-gray-2)}}@media (prefers-color-scheme: dark){.dcf-dropdown{background-color:var(--dcf-item-background)}.dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-step-600)}}.dcf-dropdown.dcf-active{display:block;margin-top:-3px;box-shadow:0 12px 16px -4px #0a0d1214,0 4px 6px -2px #0a0d1208,0 2px 2px -1px #0a0d120a!important;border-radius:var(--dcf-border-radius);padding:.5rem .25rem}@media (max-width: 768px){.dcf-dropdown.dcf-active{margin-top:55px}}.dcf-dropdown.dcf-active>div>div{cursor:pointer;height:35px;padding:.5rem 1rem;border:1px solid transparent;font-size:1rem;display:flex;align-items:center;border-radius:6px}@media (prefers-color-scheme: light){.dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-8)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-3)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{pointer-events:none;touch-action:none;cursor:text!important;border-color:transparent!important}.dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-1)}}@media (prefers-color-scheme: dark){.dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-1)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-5)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{cursor:text!important;pointer-events:none;touch-action:none;border-color:transparent!important}.dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-8)}}\n"] }]
|
|
6198
|
+
], standalone: true, template: "\n@if(!indexes.length) {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n}\n\n<div [id]=\"uid\" class=\"dcf-grid dcf-grid-small dcf-grid-match dcf-filter-grid\" [class.dcf-hidden]=\"!indexes.length\">\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-filter\">\n <div class=\"dcf-input\">\n @for(filter of filterValue; track trackItemFn($index, filter?.['index'])) {\n @if(filter?.['index']) {\n <ion-chip [outline]=\"true\">{{ filter?.['index'] }}</ion-chip>\n }\n @if(filter?.['condition']) {\n <ion-chip [outline]=\"true\">{{ filter?.['condition'] }}</ion-chip>\n }\n @if(filter?.['value']) {\n <ion-chip [outline]=\"true\" class=\"dcf-filter-value\">\n {{ filter?.['value'] }}\n <ion-icon name=\"close\" (click)=\"removeFilter(filter?.['value'])\" size=\"small\"></ion-icon>\n </ion-chip>\n }\n }\n <div class=\"dcf-width-1-1\">\n <!-- [readonly]=\"step !== 3\" -->\n <input\n fill=\"none\"\n [(ngModel)]=\"value\"\n (keydown.enter)=\"addFilter(value, $event)\"\n (keydown.backspace)=\"clear(value)\"\n (input)=\"handleInput($event)\"\n (click)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n type=\"text\"\n\n placeholder=\"{{ locale + (step === 3 ? '.type' : '.select') | translate }}\"\n #component\n />\n @if(windowWidth >= 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if(filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if(filterValue.length > 0) {\n <div class=\"dcf-icon-clear\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"clear()\">\n <ion-icon name=\"trash-outline\" [color]=\"!isDarkMode ? 'dark' : 'medium'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n <div class=\"dcf-icon-search\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"submit()\">\n <ion-icon name=\"search-outline\" [color]=\"!isDarkMode ? 'dark' : 'medium'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n </div>\n @if(windowWidth < 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if(filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n @if(!disableSort) {\n <div class=\"dcf-width-1-5@m dcf-width-1-1 dcf-sort-container\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-grid-match\">\n <div class=\"dcf-width-expand\">\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n class=\"dcf-sort-select\"\n (ionChange)=\"handleSortChange($event)\"\n interface=\"popover\"\n [value]=\"sortValue\"\n label-placement=\"floating\"\n fill=\"outline\"\n [label]=\"locale + '.sort' | translate\"\n >\n @for(sort of sortBy; track sort) {\n\n <ion-select-option [value]=\"sort\">{{ sort | translate }}</ion-select-option>\n }\n </ion-select>\n </div>\n <div class=\"dcf-width-auto\">\n <ion-button (click)=\"handleSortDirectionChange()\" fill=\"clear\">\n <ion-icon slot=\"icon-only\" [color]=\"!isDarkMode ? 'primary' : 'medium'\" [name]=\"sortDirection === 'desc' ? 'arrow-down-outline' : 'arrow-up-outline'\"></ion-icon>\n </ion-button>\n </div>\n </div>\n </div>\n }\n</div>\n\n\n", styles: ["@media (prefers-color-scheme: light){.dcf-filter{border:1px solid var(--dcf-color-gray-3);background-color:#fff}.dcf-filter:focus-within{border-color:var(--dcf-color-primary);background-color:#fff}ion-chip{border:1px solid var(--dcf-color-gray-3);color:var(--dcf-color-gray-7)}ion-chip.dcf-filter-value{background:var(--dcf-color-gray-2);border-color:var(--dcf-color-gray-4)!important;color:var(--dcf-color-gray-8)!important}.dcf-input input{color:var(--dcf-color-gray-7)}.dcf-dropdown{background-color:#fff}.dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-gray-2)}.dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-8)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-3)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{pointer-events:none;touch-action:none;cursor:text!important;border-color:transparent!important}.dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-1)}}@media (prefers-color-scheme: dark){.dcf-filter{border:1px solid var(--dcf-color-step-500)}.dcf-filter ::-webkit-input-placeholder,.dcf-filter ::placeholder{color:var(--dcf-color-gray-4)!important}.dcf-filter:hover{border-color:var(--dcf-color-gray-2)}.dcf-filter:focus-within{border-color:var(--dcf-color-gray-2)}ion-chip{border-color:var(--dcf-color-step-300);background:rgba(var(--dcf-color-medium-rgb),.1)}ion-chip.dcf-filter-value{background:rgba(var(--dcf-color-medium-rgb),.3)!important;border-color:var(--dcf-color-step-500)}.dcf-input input{color:var(--dcf-color-gray-1)}.dcf-dropdown{background-color:var(--dcf-item-background)}.dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-step-600)}.dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-1)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-5)}.dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{cursor:text!important;pointer-events:none;touch-action:none;border-color:transparent!important}.dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-8)}}.dcf-filter-grid{padding:0 .5rem;margin-top:.75rem;margin-bottom:.75rem}ion-select{min-height:44px!important}.dcf-hidden{display:none!important}.dcf-filter{display:flex;width:100%;min-height:40px;box-shadow:0 1px 2px #0a0d120d;border-radius:var(--dcf-border-radius);box-sizing:border-box}.dcf-filter ion-chip{border-radius:6px;padding:0 8px!important;height:24px;min-height:24px;font-size:.75rem;font-style:normal;font-weight:500;flex-shrink:0;margin-right:2px;white-space:nowrap}.dcf-filter ion-chip.sc-ion-chip-md-h,.dcf-filter ion-chip.sc-ion-chip-ios-h{height:24px;min-height:24px}.dcf-filter ion-chip.sc-ion-chip-md-h .chip-native,.dcf-filter ion-chip.sc-ion-chip-ios-h .chip-native{padding:0 8px!important;height:24px;min-height:24px}.dcf-filter ion-chip ion-label{padding:0 4px;margin:0;font-size:.75rem;white-space:nowrap}.dcf-filter ion-chip ion-icon{margin:0 2px;font-size:.75rem}.dcf-filter .dcf-input{width:100%;display:flex;align-items:center;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding-left:.5rem}.dcf-filter .dcf-input input{min-height:40px;min-width:100px;width:100%;font-size:1rem;border:none;outline:none;background:transparent;border:0px!important;outline:none!important}.dcf-filter .dcf-input input:focus{border:0px!important;outline:none!important}.dcf-filter .dcf-icon-clear,.dcf-filter .dcf-icon-search{display:flex;justify-content:center;text-align:center;align-items:center;min-width:40px}.dcf-filter .dcf-icon-search ion-icon{font-size:1.25rem}.dcf-sort-container{min-width:200px!important;width:auto}@media (min-width: 990px){.dcf-sort-container{max-width:20%!important}}@media (max-width: 680px){.dcf-sort-container{min-width:100%!important;margin:.75rem 0rem}}.dcf-dropdown{position:absolute;max-height:200px;overflow-y:auto;border-radius:4px;z-index:1000!important;min-width:200px;max-width:300px;display:none}.dcf-dropdown.dcf-active{display:block;margin-top:-3px;box-shadow:0 12px 16px -4px #0a0d1214,0 4px 6px -2px #0a0d1208,0 2px 2px -1px #0a0d120a!important;border-radius:var(--dcf-border-radius);padding:.5rem .25rem}@media (max-width: 768px){.dcf-dropdown.dcf-active{margin-top:55px}}.dcf-dropdown.dcf-active>div>div{cursor:pointer;height:35px;padding:.5rem 1rem;border:1px solid transparent;font-size:1rem;display:flex;align-items:center;border-radius:6px}\n"] }]
|
|
6203
6199
|
}], ctorParameters: () => [], propDecorators: { optionsFilterElement: [{
|
|
6204
6200
|
type: ViewChild,
|
|
6205
6201
|
args: ['optionsFilterElement', { read: ElementRef, static: false }]
|
|
@@ -6330,10 +6326,10 @@ class ModelRendererComponent {
|
|
|
6330
6326
|
}
|
|
6331
6327
|
}
|
|
6332
6328
|
}
|
|
6333
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6334
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
6329
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ModelRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6330
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: ModelRendererComponent, isStandalone: true, selector: "ngx-decaf-model-renderer", inputs: { model: "model", globals: "globals", projectable: "projectable", rendererId: "rendererId" }, outputs: { listenEvent: "listenEvent" }, host: { properties: { "attr.id": "rendererId" } }, viewQueries: [{ propertyName: "inner", first: true, predicate: ["inner"], descendants: true, read: TemplateRef, static: true }, { propertyName: "vcr", first: true, predicate: ["componentOuter"], descendants: true, read: ViewContainerRef, static: true }], usesOnChanges: true, ngImport: i0, template: " <!-- Keep to avoid id conflicts -->\n <div [id]=\"rendererId\"></div>\n\n <ng-template #componentOuter></ng-template>\n <ng-template #inner>\n <div [id]=\"rendererId || null\">\n @for (child of output?.children; track child) {\n @if(child?.children?.length) {\n <ngx-decaf-component-renderer [parent]=\"child\" />\n } @else {\n <ng-container\n #childComponents\n *ngComponentOutlet=\"\n child.component;\n injector: child.injector;\n inputs: child.inputs;\n content:child.content;\n \"\n />\n }\n }\n </div>\n </ng-template>\n", styles: [""], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletEnvironmentInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "globals", "children", "model", "parent"], outputs: ["listenEvent"] }] }); }
|
|
6335
6331
|
}
|
|
6336
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6332
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ModelRendererComponent, decorators: [{
|
|
6337
6333
|
type: Component,
|
|
6338
6334
|
args: [{ standalone: true, imports: [NgComponentOutlet, ComponentRendererComponent], selector: 'ngx-decaf-model-renderer', host: { '[attr.id]': 'rendererId' }, template: " <!-- Keep to avoid id conflicts -->\n <div [id]=\"rendererId\"></div>\n\n <ng-template #componentOuter></ng-template>\n <ng-template #inner>\n <div [id]=\"rendererId || null\">\n @for (child of output?.children; track child) {\n @if(child?.children?.length) {\n <ngx-decaf-component-renderer [parent]=\"child\" />\n } @else {\n <ng-container\n #childComponents\n *ngComponentOutlet=\"\n child.component;\n injector: child.injector;\n inputs: child.inputs;\n content:child.content;\n \"\n />\n }\n }\n </div>\n </ng-template>\n" }]
|
|
6339
6335
|
}], propDecorators: { model: [{
|
|
@@ -6483,10 +6479,10 @@ class LayoutComponent extends NgxBaseComponent {
|
|
|
6483
6479
|
this.rows = this._rows;
|
|
6484
6480
|
this.initialized = true;
|
|
6485
6481
|
}
|
|
6486
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6487
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
6482
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6483
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: LayoutComponent, isStandalone: true, selector: "ngx-decaf-layout", inputs: { cols: "cols", rows: "rows", breakpoint: "breakpoint", children: "children" }, usesInheritance: true, ngImport: i0, template: "\n@if(initialized) {\n @for (row of rows; track trackItemFn($index, row); let rowIndex = $index) {\n <div [id]=\"uid\" class=\"dcf-grid dcf-grid-collapse dcf-grid-match\">\n @if(row) {\n <div class=\"dcf-width-1-1 dcf-grid-title\">\n <ion-card class=\"dcf-grid-title\">\n {{row.title | translate}}\n </ion-card>\n </div>\n }\n @for (child of row.cols; track trackItemFn($index, child.col); let colIndex = $index) {\n <div [class]=\"(child.col === cols.length ? 'dcf-width-1-1' : 'dcf-width-'+child.col+'-'+cols.length+'@'+breakpoint)\">\n <div [class]=\"'dcf-grid-child '+child.col \">\n @if(child.tag === 'ngx-decaf-crud-form') {\n <ion-card [class]=\"'dcf-height-1-1 ' + className\">\n <ion-card-content>\n <ngx-decaf-model-renderer\n [model]=\"child.props.name\"\n (listenEvent)=\"handleEvent($event)\"\n />\n </ion-card-content>\n </ion-card>\n } @else {\n <ngx-decaf-component-renderer\n [tag]=\"child.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{props: child.props}\"\n />\n }\n </div>\n </div>\n }\n </div>\n }\n}\n", styles: [".dcf-grid>div:not(.dcf-grid-title) ::ng-deep ngx-decaf-component-renderer>*>*{height:100%;display:flex;justify-content:center!important;align-items:center!important}.dcf-grid ion-card.dcf-height-1-1>ion-card-content{margin-top:2rem}.dcf-grid.dcf-grid-small .dcf-grid-child{margin-bottom:2rem}.dcf-grid.dcf-grid-collapse .dcf-grid-child{margin-bottom:1.25rem}.dcf-grid.dcf-grid-collapse .dcf-grid-child ion-card{margin-bottom:1.25rem}.dcf-grid-title{font-size:1.05rem!important;background:none;box-shadow:none;margin-bottom:0;padding-bottom:0;font-weight:600;color:var(--dcf-color-dark);display:flex;align-items:center;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}\n"], dependencies: [{ kind: "component", type: ModelRendererComponent, selector: "ngx-decaf-model-renderer", inputs: ["model", "globals", "projectable", "rendererId"], outputs: ["listenEvent"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "globals", "children", "model", "parent"], outputs: ["listenEvent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
6488
6484
|
}
|
|
6489
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6485
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LayoutComponent, decorators: [{
|
|
6490
6486
|
type: Component,
|
|
6491
6487
|
args: [{ selector: 'ngx-decaf-layout', imports: [TranslatePipe, ModelRendererComponent, ComponentRendererComponent], standalone: true, template: "\n@if(initialized) {\n @for (row of rows; track trackItemFn($index, row); let rowIndex = $index) {\n <div [id]=\"uid\" class=\"dcf-grid dcf-grid-collapse dcf-grid-match\">\n @if(row) {\n <div class=\"dcf-width-1-1 dcf-grid-title\">\n <ion-card class=\"dcf-grid-title\">\n {{row.title | translate}}\n </ion-card>\n </div>\n }\n @for (child of row.cols; track trackItemFn($index, child.col); let colIndex = $index) {\n <div [class]=\"(child.col === cols.length ? 'dcf-width-1-1' : 'dcf-width-'+child.col+'-'+cols.length+'@'+breakpoint)\">\n <div [class]=\"'dcf-grid-child '+child.col \">\n @if(child.tag === 'ngx-decaf-crud-form') {\n <ion-card [class]=\"'dcf-height-1-1 ' + className\">\n <ion-card-content>\n <ngx-decaf-model-renderer\n [model]=\"child.props.name\"\n (listenEvent)=\"handleEvent($event)\"\n />\n </ion-card-content>\n </ion-card>\n } @else {\n <ngx-decaf-component-renderer\n [tag]=\"child.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{props: child.props}\"\n />\n }\n </div>\n </div>\n }\n </div>\n }\n}\n", styles: [".dcf-grid>div:not(.dcf-grid-title) ::ng-deep ngx-decaf-component-renderer>*>*{height:100%;display:flex;justify-content:center!important;align-items:center!important}.dcf-grid ion-card.dcf-height-1-1>ion-card-content{margin-top:2rem}.dcf-grid.dcf-grid-small .dcf-grid-child{margin-bottom:2rem}.dcf-grid.dcf-grid-collapse .dcf-grid-child{margin-bottom:1.25rem}.dcf-grid.dcf-grid-collapse .dcf-grid-child ion-card{margin-bottom:1.25rem}.dcf-grid-title{font-size:1.05rem!important;background:none;box-shadow:none;margin-bottom:0;padding-bottom:0;font-weight:600;color:var(--dcf-color-dark);display:flex;align-items:center;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}\n"] }]
|
|
6492
6488
|
}], ctorParameters: () => [], propDecorators: { cols: [{
|
|
@@ -6500,857 +6496,466 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
6500
6496
|
}] } });
|
|
6501
6497
|
|
|
6502
6498
|
/**
|
|
6503
|
-
* @description A component for
|
|
6504
|
-
* @summary
|
|
6505
|
-
*
|
|
6506
|
-
*
|
|
6507
|
-
* @extends NgxBaseComponent
|
|
6508
|
-
*
|
|
6509
|
-
* @param {string} [lines='none'] - Determines the line style of the item. Can be 'inset', 'inseet', or 'none'.
|
|
6510
|
-
* @param {Record<string, any>} item - The data item to be displayed in the list item.
|
|
6511
|
-
* @param {string} icon - The name of the icon to be displayed.
|
|
6512
|
-
* @param {'start' | 'end'} [iconSlot='start'] - The position of the icon within the item.
|
|
6513
|
-
* @param {StringOrBoolean} [button=true] - Determines if the item should behave as a button.
|
|
6514
|
-
* @param {string} [title] - The main title of the list item.
|
|
6515
|
-
* @param {string} [description] - A description for the list item.
|
|
6516
|
-
* @param {string} [info] - Additional information for the list item.
|
|
6517
|
-
* @param {string} [subinfo] - Sub-information for the list item.
|
|
6499
|
+
* @description A pagination component for navigating through multiple pages of content.
|
|
6500
|
+
* @summary This component provides a user interface for paginated content navigation,
|
|
6501
|
+
* displaying page numbers and navigation controls. It supports customizable page counts,
|
|
6502
|
+
* current page tracking, and emits events when users navigate between pages.
|
|
6518
6503
|
*
|
|
6519
|
-
*
|
|
6520
|
-
*
|
|
6521
|
-
*
|
|
6522
|
-
* icon="star"
|
|
6523
|
-
* title="Item Title"
|
|
6524
|
-
* description="Item Description"
|
|
6525
|
-
* (clickEvent)="handleItemClick($event)">
|
|
6526
|
-
* </ngx-decaf-list-item>
|
|
6504
|
+
* The component intelligently handles large numbers of pages by showing a subset of page
|
|
6505
|
+
* numbers with ellipses to indicate skipped pages, ensuring the UI remains clean and usable
|
|
6506
|
+
* even with many pages.
|
|
6527
6507
|
*
|
|
6528
6508
|
* @mermaid
|
|
6529
6509
|
* sequenceDiagram
|
|
6530
|
-
* participant C as Component
|
|
6531
|
-
* participant V as View
|
|
6532
6510
|
* participant U as User
|
|
6533
|
-
*
|
|
6534
|
-
*
|
|
6535
|
-
*
|
|
6536
|
-
*
|
|
6537
|
-
*
|
|
6538
|
-
*
|
|
6511
|
+
* participant P as PaginationComponent
|
|
6512
|
+
* participant E as External Component
|
|
6513
|
+
*
|
|
6514
|
+
* U->>P: Click page number
|
|
6515
|
+
* P->>P: navigate(page)
|
|
6516
|
+
* P->>P: handleClick(direction, page)
|
|
6517
|
+
* P->>E: Emit clickEvent with PaginationCustomEvent
|
|
6518
|
+
*
|
|
6519
|
+
* U->>P: Click next button
|
|
6520
|
+
* P->>P: next()
|
|
6521
|
+
* P->>P: handleClick('next')
|
|
6522
|
+
* P->>E: Emit clickEvent with PaginationCustomEvent
|
|
6523
|
+
*
|
|
6524
|
+
* U->>P: Click previous button
|
|
6525
|
+
* P->>P: previous()
|
|
6526
|
+
* P->>P: handleClick('previous')
|
|
6527
|
+
* P->>E: Emit clickEvent with PaginationCustomEvent
|
|
6528
|
+
*
|
|
6529
|
+
* @example
|
|
6530
|
+
* <ngx-decaf-pagination
|
|
6531
|
+
* [pages]="10"
|
|
6532
|
+
* [current]="3"
|
|
6533
|
+
* (clickEvent)="handlePageChange($event)">
|
|
6534
|
+
* </ngx-decaf-pagination>
|
|
6535
|
+
*
|
|
6536
|
+
* @extends {NgxBaseComponent}
|
|
6537
|
+
* @implements {OnInit}
|
|
6539
6538
|
*/
|
|
6540
|
-
|
|
6539
|
+
class PaginationComponent extends NgxBaseComponent {
|
|
6541
6540
|
/**
|
|
6542
|
-
* @
|
|
6543
|
-
* @
|
|
6544
|
-
* with the component name for
|
|
6545
|
-
* all available Ionic icons to ensure they can be displayed in the component.
|
|
6546
|
-
*
|
|
6547
|
-
* @memberOf ListItemComponent
|
|
6541
|
+
* @constructor
|
|
6542
|
+
* @description Initializes a new instance of the PaginationComponent.
|
|
6543
|
+
* Calls the parent constructor with the component name for generate base locale string.
|
|
6548
6544
|
*/
|
|
6549
6545
|
constructor() {
|
|
6550
|
-
super("
|
|
6551
|
-
/**
|
|
6552
|
-
* @description Controls the display of lines around the list item.
|
|
6553
|
-
* @summary Determines how lines are displayed around the list item borders.
|
|
6554
|
-
* 'inset' shows lines with padding, 'full' shows full-width lines, and 'none'
|
|
6555
|
-
* removes all lines. This affects the visual separation between list items.
|
|
6556
|
-
*
|
|
6557
|
-
* @type {'inset' | 'full' | 'none'}
|
|
6558
|
-
* @default 'inset'
|
|
6559
|
-
* @memberOf ListItemComponent
|
|
6560
|
-
*/
|
|
6561
|
-
this.lines = 'full';
|
|
6562
|
-
/**
|
|
6563
|
-
* @description Position of the icon within the list item.
|
|
6564
|
-
* @summary Determines whether the icon appears at the start (left in LTR languages)
|
|
6565
|
-
* or end (right in LTR languages) of the list item. This affects the overall
|
|
6566
|
-
* layout and visual hierarchy of the item content.
|
|
6567
|
-
*
|
|
6568
|
-
* @type {'start' | 'end'}
|
|
6569
|
-
* @default 'start'
|
|
6570
|
-
* @memberOf ListItemComponent
|
|
6571
|
-
*/
|
|
6572
|
-
this.iconSlot = 'start';
|
|
6546
|
+
super("PaginationComponent");
|
|
6573
6547
|
/**
|
|
6574
|
-
* @description Controls whether the
|
|
6575
|
-
* @summary When set to true, the
|
|
6576
|
-
*
|
|
6577
|
-
* When false, the item is displayed as static content without interactive behavior.
|
|
6548
|
+
* @description Controls whether the component uses translation services.
|
|
6549
|
+
* @summary When set to true, the component will attempt to use translation services
|
|
6550
|
+
* for any text content. This allows for internationalization of the pagination component.
|
|
6578
6551
|
*
|
|
6579
6552
|
* @type {StringOrBoolean}
|
|
6580
6553
|
* @default true
|
|
6581
|
-
* @memberOf
|
|
6582
|
-
*/
|
|
6583
|
-
this.button = true;
|
|
6584
|
-
/**
|
|
6585
|
-
* @description Event emitter for list item click interactions.
|
|
6586
|
-
* @summary Emits custom events when the list item is clicked or when actions
|
|
6587
|
-
* are performed on it. The emitted event contains information about the action,
|
|
6588
|
-
* the item data, and other relevant context for parent components to handle.
|
|
6589
|
-
*
|
|
6590
|
-
* @type {EventEmitter<ListItemCustomEvent>}
|
|
6591
|
-
* @memberOf ListItemComponent
|
|
6592
|
-
*/
|
|
6593
|
-
this.clickEvent = new EventEmitter();
|
|
6594
|
-
/**
|
|
6595
|
-
* @description Flag indicating whether slide items are currently enabled.
|
|
6596
|
-
* @summary Controls the visibility of slide actions based on screen size and
|
|
6597
|
-
* available operations. When true, users can swipe on the item to reveal
|
|
6598
|
-
* action buttons for operations like edit and delete.
|
|
6599
|
-
*
|
|
6600
|
-
* @type {boolean}
|
|
6601
|
-
* @default false
|
|
6602
|
-
* @memberOf ListItemComponent
|
|
6554
|
+
* @memberOf PaginationComponent
|
|
6603
6555
|
*/
|
|
6604
|
-
this.
|
|
6556
|
+
this.translatable = true;
|
|
6605
6557
|
/**
|
|
6606
|
-
* @description
|
|
6607
|
-
* @summary
|
|
6608
|
-
*
|
|
6609
|
-
* are performed. Used for managing the popover lifecycle.
|
|
6558
|
+
* @description The currently active page number.
|
|
6559
|
+
* @summary Specifies which page is currently active or selected. This value is used
|
|
6560
|
+
* to highlight the current page in the UI and as a reference point for navigation.
|
|
6610
6561
|
*
|
|
6611
|
-
* @type {
|
|
6612
|
-
* @default
|
|
6613
|
-
* @memberOf
|
|
6562
|
+
* @type {number}
|
|
6563
|
+
* @default 1
|
|
6564
|
+
* @memberOf PaginationComponent
|
|
6614
6565
|
*/
|
|
6615
|
-
this.
|
|
6566
|
+
this.current = 1;
|
|
6616
6567
|
/**
|
|
6617
|
-
* @description
|
|
6618
|
-
* @summary
|
|
6619
|
-
*
|
|
6620
|
-
*
|
|
6568
|
+
* @description Event emitter for pagination navigation events.
|
|
6569
|
+
* @summary Emits a custom event when users navigate between pages, either by clicking
|
|
6570
|
+
* on page numbers or using the next/previous buttons. The event contains information
|
|
6571
|
+
* about the navigation direction and the target page number.
|
|
6621
6572
|
*
|
|
6622
|
-
* @
|
|
6623
|
-
* @
|
|
6624
|
-
* @memberOf ListItemComponent
|
|
6573
|
+
* @type {EventEmitter<PaginationCustomEvent>}
|
|
6574
|
+
* @memberOf PaginationComponent
|
|
6625
6575
|
*/
|
|
6626
|
-
this.
|
|
6627
|
-
addIcons(
|
|
6576
|
+
this.clickEvent = new EventEmitter();
|
|
6577
|
+
addIcons({ chevronBackOutline, chevronForwardOutline });
|
|
6628
6578
|
}
|
|
6629
6579
|
/**
|
|
6630
|
-
* @description Initializes the component after Angular
|
|
6631
|
-
* @summary Sets up the component by
|
|
6632
|
-
*
|
|
6633
|
-
*
|
|
6634
|
-
* properly initialized and responsive behavior is configured.
|
|
6580
|
+
* @description Initializes the component after Angular sets the input properties.
|
|
6581
|
+
* @summary Sets up the component by initializing the locale settings based on the
|
|
6582
|
+
* translatable property, generating the page numbers based on the total pages and
|
|
6583
|
+
* current page, and storing the last page number for boundary checking.
|
|
6635
6584
|
*
|
|
6636
6585
|
* @mermaid
|
|
6637
6586
|
* sequenceDiagram
|
|
6638
6587
|
* participant A as Angular Lifecycle
|
|
6639
|
-
* participant
|
|
6640
|
-
* participant W as Window
|
|
6588
|
+
* participant P as PaginationComponent
|
|
6641
6589
|
*
|
|
6642
|
-
* A->>
|
|
6643
|
-
*
|
|
6644
|
-
*
|
|
6645
|
-
*
|
|
6646
|
-
*
|
|
6647
|
-
*
|
|
6648
|
-
* end
|
|
6649
|
-
* L->>W: getWindowWidth()
|
|
6650
|
-
* W-->>L: Return current width
|
|
6651
|
-
* L->>L: Store windowWidth
|
|
6590
|
+
* A->>P: ngOnInit()
|
|
6591
|
+
* P->>P: getLocale(translatable)
|
|
6592
|
+
* P->>P: Set locale
|
|
6593
|
+
* P->>P: getPages(data, current)
|
|
6594
|
+
* P->>P: Set pages array
|
|
6595
|
+
* P->>P: Set last page number
|
|
6652
6596
|
*
|
|
6653
|
-
* @
|
|
6654
|
-
* @memberOf
|
|
6597
|
+
* @returns {void}
|
|
6598
|
+
* @memberOf PaginationComponent
|
|
6655
6599
|
*/
|
|
6656
|
-
|
|
6657
|
-
this.
|
|
6658
|
-
this.
|
|
6659
|
-
this.
|
|
6660
|
-
if (this.operations?.length)
|
|
6661
|
-
this.className += ` action`;
|
|
6662
|
-
this.windowWidth = getWindowWidth();
|
|
6600
|
+
ngOnInit() {
|
|
6601
|
+
this.locale = this.getLocale(this.translatable);
|
|
6602
|
+
this.pages = this.getPages(this.totalPages, this.current);
|
|
6603
|
+
this.last = this.totalPages;
|
|
6663
6604
|
}
|
|
6664
6605
|
/**
|
|
6665
|
-
* @description Handles
|
|
6666
|
-
* @summary
|
|
6667
|
-
*
|
|
6668
|
-
*
|
|
6669
|
-
* route configuration. This method supports both event-driven and navigation-driven architectures.
|
|
6606
|
+
* @description Handles click events on pagination controls.
|
|
6607
|
+
* @summary Processes user interactions with the pagination component, updating the
|
|
6608
|
+
* current page if specified and emitting an event with navigation details. This method
|
|
6609
|
+
* is called when users click on page numbers or navigation buttons.
|
|
6670
6610
|
*
|
|
6671
|
-
* @param {
|
|
6672
|
-
* @param {
|
|
6673
|
-
* @
|
|
6674
|
-
* @return {Promise<boolean|void>} A promise that resolves to navigation success or void for events
|
|
6611
|
+
* @param {('next' | 'previous')} direction - The direction of navigation
|
|
6612
|
+
* @param {number} [page] - Optional page number to navigate to directly
|
|
6613
|
+
* @returns {void}
|
|
6675
6614
|
*
|
|
6676
6615
|
* @mermaid
|
|
6677
6616
|
* sequenceDiagram
|
|
6678
6617
|
* participant U as User
|
|
6679
|
-
* participant
|
|
6680
|
-
* participant
|
|
6681
|
-
* participant N as NavController
|
|
6682
|
-
* participant E as Event System
|
|
6618
|
+
* participant P as PaginationComponent
|
|
6619
|
+
* participant E as External Component
|
|
6683
6620
|
*
|
|
6684
|
-
* U->>
|
|
6685
|
-
*
|
|
6686
|
-
* alt
|
|
6687
|
-
*
|
|
6688
|
-
* end
|
|
6689
|
-
* L->>L: removeFocusTrap()
|
|
6690
|
-
* alt No route configured
|
|
6691
|
-
* L->>E: windowEventEmitter()
|
|
6692
|
-
* L->>P: clickEvent.emit()
|
|
6693
|
-
* else Route configured
|
|
6694
|
-
* L->>N: redirect(action, uid)
|
|
6695
|
-
* N-->>L: Return navigation result
|
|
6621
|
+
* U->>P: Click pagination control
|
|
6622
|
+
* P->>P: handleClick(direction, page?)
|
|
6623
|
+
* alt page is provided
|
|
6624
|
+
* P->>P: Update current page
|
|
6696
6625
|
* end
|
|
6626
|
+
* P->>E: Emit clickEvent with direction and page
|
|
6697
6627
|
*
|
|
6698
|
-
* @memberOf
|
|
6628
|
+
* @memberOf PaginationComponent
|
|
6699
6629
|
*/
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
}
|
|
6711
|
-
return await this.redirect(action, (typeof this.uid === 'number' ? `${this.uid}` : this.uid));
|
|
6630
|
+
handleClick(direction, page) {
|
|
6631
|
+
if (page)
|
|
6632
|
+
this.current = page;
|
|
6633
|
+
this.clickEvent.emit({
|
|
6634
|
+
name: EventConstants.CLICK,
|
|
6635
|
+
data: {
|
|
6636
|
+
direction,
|
|
6637
|
+
page: this.current
|
|
6638
|
+
},
|
|
6639
|
+
component: this.componentName
|
|
6640
|
+
});
|
|
6712
6641
|
}
|
|
6713
6642
|
/**
|
|
6714
|
-
* @description
|
|
6715
|
-
* @summary
|
|
6716
|
-
*
|
|
6717
|
-
*
|
|
6718
|
-
*
|
|
6643
|
+
* @description Generates the array of page objects for display.
|
|
6644
|
+
* @summary Creates an array of page objects based on the total number of pages and
|
|
6645
|
+
* the current page. For small page counts (≤5), all pages are shown. For larger page
|
|
6646
|
+
* counts, a subset is shown with ellipses to indicate skipped pages. This ensures
|
|
6647
|
+
* the pagination UI remains clean and usable even with many pages.
|
|
6719
6648
|
*
|
|
6720
|
-
* @
|
|
6649
|
+
* @param {number} total - The total number of pages
|
|
6650
|
+
* @param {number} [current] - The current active page (defaults to this.current)
|
|
6651
|
+
* @returns {KeyValue[]} Array of page objects with index and text properties
|
|
6721
6652
|
*
|
|
6722
6653
|
* @mermaid
|
|
6723
|
-
*
|
|
6724
|
-
*
|
|
6725
|
-
*
|
|
6726
|
-
*
|
|
6654
|
+
* flowchart TD
|
|
6655
|
+
* A[Start] --> B{total <= 5?}
|
|
6656
|
+
* B -->|Yes| C[Show all pages]
|
|
6657
|
+
* B -->|No| D[Show first page]
|
|
6658
|
+
* D --> E[Show last pages]
|
|
6659
|
+
* E --> F[Add ellipses for skipped pages]
|
|
6660
|
+
* C --> G[Return pages array]
|
|
6661
|
+
* F --> G
|
|
6727
6662
|
*
|
|
6728
|
-
*
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6663
|
+
* @memberOf PaginationComponent
|
|
6664
|
+
*/
|
|
6665
|
+
getPages(total, current) {
|
|
6666
|
+
if (!current)
|
|
6667
|
+
current = this.current;
|
|
6668
|
+
const pages = [];
|
|
6669
|
+
function getPage(index, text = '', clazz = 'button') {
|
|
6670
|
+
if (pages.some(item => item['index'] === index))
|
|
6671
|
+
return;
|
|
6672
|
+
pages.push({ index, text: index != null ? index.toString().padStart(2, '0') : text, class: clazz });
|
|
6673
|
+
}
|
|
6674
|
+
if (total <= 5) {
|
|
6675
|
+
for (let i = 1; i <= total; i++)
|
|
6676
|
+
getPage(i);
|
|
6677
|
+
}
|
|
6678
|
+
else {
|
|
6679
|
+
// Adiciona os dois primeiros
|
|
6680
|
+
getPage(1);
|
|
6681
|
+
getPage(2);
|
|
6682
|
+
// Adiciona "..." entre os blocos
|
|
6683
|
+
if (current && current > 3)
|
|
6684
|
+
getPage(null, '...');
|
|
6685
|
+
// Adiciona a página atual (se estiver no meio)
|
|
6686
|
+
if (current && current > 2 && current < total - 1)
|
|
6687
|
+
getPage(current);
|
|
6688
|
+
// Adiciona "..." entre os blocos
|
|
6689
|
+
if (current && current < total - 2)
|
|
6690
|
+
getPage(null, '...', 'separator');
|
|
6691
|
+
// Adiciona os dois últimos
|
|
6692
|
+
getPage(total - 1);
|
|
6693
|
+
getPage(total);
|
|
6694
|
+
}
|
|
6695
|
+
return pages;
|
|
6696
|
+
}
|
|
6697
|
+
/**
|
|
6698
|
+
* @description Gets the current active page number.
|
|
6699
|
+
* @summary Returns the current page number that is active in the pagination component.
|
|
6700
|
+
* This method provides a way to access the current page state from outside the component.
|
|
6738
6701
|
*
|
|
6739
|
-
* @
|
|
6702
|
+
* @returns {number} The current page number
|
|
6703
|
+
* @memberOf PaginationComponent
|
|
6740
6704
|
*/
|
|
6741
|
-
|
|
6742
|
-
this.
|
|
6743
|
-
if (!this.operations?.length || this.windowWidth > 639)
|
|
6744
|
-
return this.showSlideItems = false;
|
|
6745
|
-
this.showSlideItems = this.operations.includes(OperationKeys.UPDATE) || this.operations.includes(OperationKeys.DELETE);
|
|
6746
|
-
return this.showSlideItems;
|
|
6705
|
+
getCurrent() {
|
|
6706
|
+
return this.current;
|
|
6747
6707
|
}
|
|
6748
6708
|
/**
|
|
6749
|
-
* @description
|
|
6750
|
-
* @summary
|
|
6751
|
-
*
|
|
6752
|
-
*
|
|
6753
|
-
* is coordinated with the CSS animation duration to ensure the element is removed
|
|
6754
|
-
* after the animation completes.
|
|
6709
|
+
* @description Navigates to the next page.
|
|
6710
|
+
* @summary Increments the current page number if not at the last page and triggers
|
|
6711
|
+
* the click event handler with 'next' direction. This method is typically called
|
|
6712
|
+
* when the user clicks on the "next" button in the pagination UI.
|
|
6755
6713
|
*
|
|
6756
|
-
* @
|
|
6757
|
-
* @return {void}
|
|
6714
|
+
* @returns {void}
|
|
6758
6715
|
*
|
|
6759
6716
|
* @mermaid
|
|
6760
6717
|
* sequenceDiagram
|
|
6761
|
-
* participant
|
|
6762
|
-
* participant
|
|
6763
|
-
* participant D as DOM
|
|
6718
|
+
* participant U as User
|
|
6719
|
+
* participant P as PaginationComponent
|
|
6764
6720
|
*
|
|
6765
|
-
*
|
|
6766
|
-
*
|
|
6767
|
-
*
|
|
6768
|
-
*
|
|
6769
|
-
*
|
|
6770
|
-
*
|
|
6771
|
-
* D->>D: Remove element from DOM
|
|
6721
|
+
* U->>P: Click next button
|
|
6722
|
+
* P->>P: next()
|
|
6723
|
+
* alt page <= max pages
|
|
6724
|
+
* P->>P: Increment current page
|
|
6725
|
+
* P->>P: handleClick('next')
|
|
6726
|
+
* end
|
|
6772
6727
|
*
|
|
6773
|
-
* @memberOf
|
|
6728
|
+
* @memberOf PaginationComponent
|
|
6774
6729
|
*/
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6730
|
+
next() {
|
|
6731
|
+
const page = this.current + 1;
|
|
6732
|
+
if (page <= Object.keys(this.pages)?.length || 0) {
|
|
6733
|
+
this.current = page;
|
|
6734
|
+
this.handleClick('next');
|
|
6735
|
+
}
|
|
6778
6736
|
}
|
|
6779
6737
|
/**
|
|
6780
|
-
* @description Navigates to
|
|
6781
|
-
* @summary
|
|
6782
|
-
* the
|
|
6783
|
-
*
|
|
6784
|
-
* CRUD operations where each action (create, read, update, delete) has its own route.
|
|
6738
|
+
* @description Navigates to the previous page.
|
|
6739
|
+
* @summary Decrements the current page number if not at the first page and triggers
|
|
6740
|
+
* the click event handler with 'previous' direction. This method is typically called
|
|
6741
|
+
* when the user clicks on the "previous" button in the pagination UI.
|
|
6785
6742
|
*
|
|
6786
|
-
* @
|
|
6787
|
-
* @param {string} [id] - The unique identifier of the item to be acted upon
|
|
6788
|
-
* @return {Promise<boolean>} A promise that resolves to true if navigation was successful
|
|
6743
|
+
* @returns {void}
|
|
6789
6744
|
*
|
|
6790
6745
|
* @mermaid
|
|
6791
6746
|
* sequenceDiagram
|
|
6792
|
-
* participant
|
|
6793
|
-
* participant
|
|
6794
|
-
* participant R as Router
|
|
6747
|
+
* participant U as User
|
|
6748
|
+
* participant P as PaginationComponent
|
|
6795
6749
|
*
|
|
6796
|
-
*
|
|
6797
|
-
*
|
|
6798
|
-
*
|
|
6799
|
-
*
|
|
6800
|
-
*
|
|
6801
|
-
*
|
|
6750
|
+
* U->>P: Click previous button
|
|
6751
|
+
* P->>P: previous()
|
|
6752
|
+
* alt page > 0
|
|
6753
|
+
* P->>P: Decrement current page
|
|
6754
|
+
* P->>P: handleClick('previous')
|
|
6755
|
+
* end
|
|
6802
6756
|
*
|
|
6803
|
-
* @memberOf
|
|
6757
|
+
* @memberOf PaginationComponent
|
|
6804
6758
|
*/
|
|
6805
|
-
|
|
6806
|
-
|
|
6759
|
+
previous() {
|
|
6760
|
+
const page = this.current - 1;
|
|
6761
|
+
if (page > 0) {
|
|
6762
|
+
this.current = page;
|
|
6763
|
+
this.handleClick('previous');
|
|
6764
|
+
}
|
|
6807
6765
|
}
|
|
6808
6766
|
/**
|
|
6809
|
-
* @description
|
|
6810
|
-
* @summary
|
|
6811
|
-
*
|
|
6812
|
-
*
|
|
6813
|
-
* popover with the triggering event, and opens the action menu. The menu typically contains
|
|
6814
|
-
* available CRUD operations for the item.
|
|
6767
|
+
* @description Navigates to a specific page number.
|
|
6768
|
+
* @summary Updates the current page to the specified page number and triggers
|
|
6769
|
+
* the click event handler with the appropriate direction. This method is typically
|
|
6770
|
+
* called when the user clicks directly on a page number in the pagination UI.
|
|
6815
6771
|
*
|
|
6816
|
-
* @param {
|
|
6817
|
-
* @
|
|
6772
|
+
* @param {number | null} page - The page number to navigate to
|
|
6773
|
+
* @returns {void}
|
|
6818
6774
|
*
|
|
6819
6775
|
* @mermaid
|
|
6820
6776
|
* sequenceDiagram
|
|
6821
6777
|
* participant U as User
|
|
6822
|
-
* participant
|
|
6823
|
-
* participant P as Popover
|
|
6824
|
-
* participant A as Accessibility
|
|
6778
|
+
* participant P as PaginationComponent
|
|
6825
6779
|
*
|
|
6826
|
-
* U->>
|
|
6827
|
-
*
|
|
6828
|
-
*
|
|
6829
|
-
*
|
|
6830
|
-
*
|
|
6831
|
-
*
|
|
6780
|
+
* U->>P: Click page number
|
|
6781
|
+
* P->>P: navigate(page)
|
|
6782
|
+
* alt page is not null and different from current
|
|
6783
|
+
* P->>P: Determine direction (next/previous)
|
|
6784
|
+
* P->>P: handleClick(direction, page)
|
|
6785
|
+
* end
|
|
6832
6786
|
*
|
|
6833
|
-
* @memberOf
|
|
6787
|
+
* @memberOf PaginationComponent
|
|
6834
6788
|
*/
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
removeFocusTrap();
|
|
6839
|
-
this.actionMenuComponent.event = event;
|
|
6840
|
-
this.actionMenuOpen = true;
|
|
6789
|
+
navigate(page) {
|
|
6790
|
+
if (page !== null && this.current !== page)
|
|
6791
|
+
this.handleClick(page > this.current ? 'next' : 'previous', page);
|
|
6841
6792
|
}
|
|
6842
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6843
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ListItemComponent, isStandalone: true, selector: "ngx-decaf-list-item", inputs: { lines: "lines", item: "item", icon: "icon", iconSlot: "iconSlot", button: "button", title: "title", description: "description", info: "info", subinfo: "subinfo" }, outputs: { clickEvent: "clickEvent" }, host: { listeners: { "window:resize": "enableSlideItems($event)" } }, viewQueries: [{ propertyName: "actionMenuComponent", first: true, predicate: ["actionMenuComponent"], descendants: true }], usesInheritance: true, ngImport: i0, template: "\n@if(title || description) {\n <ion-item-sliding #component>\n <ion-item\n [id]=\"uid\"\n [lines]=\"lines\"\n [button]=\"button\"\n [class]=\"className\"\n (click)=\"operations?.includes('read') ? handleAction('read', $event, component) : ''\n \">\n @if(icon && lines !== 'inset') {\n <div class=\"dcf-icon\" [slot]=\"iconSlot\">\n <ion-avatar>\n <ion-icon aria-hidden=\"true\" name=\"reader-outline\" size=\"default\"></ion-icon>\n </ion-avatar>\n </div>\n }\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-flex dcf-flex-middle dcf-grid-collapse\" dcf-grid>\n @if(icon && lines === 'inset') {\n <div class=\"dcf-icon dcf-grid-icon\">\n <ion-avatar>\n <ion-icon aria-hidden=\"true\" name=\"reader-outline\" size=\"default\"></ion-icon>\n </ion-avatar>\n </div>\n }\n <div class=\"dcf-width-expand@s dcf-width-1-1 dcf-label\">\n <ion-label class=\"dcf-item-title\" [innerHTML]=\"uid + ' - ' + title\" ></ion-label>\n @if(description) {\n <div class=\"dcf-description\" [innerHTML]=\"description\"></div>\n }\n </div>\n @if(info || subinfo) {\n <div class=\"dcf-width-auto@s dcf-width-expand dcf-info dcf-flex dcf-flex-right@s\">\n <div>\n @if(info) {\n <span [innerHTML]=\"info\"></span>\n }\n @if(subinfo) {\n <div class=\"dcf-subinfo dcf-text-truncate\" [innerHTML]=\"subinfo\" ></div>\n }\n </div>\n </div>\n }\n\n <div class=\"dcf-width-auto dcf-flex dcf-flex-middle dcf-flex-right\">\n @if((operations.includes('delete') || operations.includes('update')) && uid) {\n <div class=\"dcf-visible@m\" id=\"dcf-actions\">\n <ion-button class=\"dcf-hidden@m\" shape=\"round\" fill=\"clear\" color=\"primary\" (click)=\"presentActionsMenu($event)\">\n <ion-icon slot=\"icon-only\" aria-hidden=\"true\" name=\"ellipsis-vertical-outline\"></ion-icon>\n </ion-button>\n <ion-popover\n #actionMenuComponent\n side=\"bottom\"\n alignment=\"left\"\n\n [isOpen]=\"actionMenuOpen\"\n (didDismiss)=\"actionMenuOpen = false\">\n <ng-template>\n <ion-content class=\"ion-padding\">\n <ion-list lines=\"none\">\n <ion-list-header>\n <h4 class=\"dcf-text-capitalize\" [innerHTML]=\"'actions' | translate\"></h4>\n </ion-list-header>\n @for (operation of ['update', 'delete']; track operation) {\n @if(operations.includes(operation)) {\n <ion-item [button]=\"true\" (click)=\"handleAction(operation, $event, component)\">\n <ion-avatar class=\"dcf-flex dcf-flex-middle\" aria-hidden=\"true\" slot=\"start\">\n @if(operation === 'update') {\n <ion-icon color=\"primary\" aria-hidden=\"true\" name=\"create-outline\"></ion-icon>\n } @else {\n <ion-icon color=\"danger\" aria-hidden=\"true\" name=\"trash\"></ion-icon>\n }\n </ion-avatar>\n <ion-label class=\"dcf-text-capitalize\">{{ operation | translate }}</ion-label>\n </ion-item>\n }\n }\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n </div>\n }\n <!-- @if(operations?.length && uid) {\n <div class=\"dcf-visible@m\" id=\"dcf-actions\">\n @if(operations?.includes('update')) {\n <ion-button fill=\"clear\" size=\"small\" color=\"primary\" (click)=\"handleAction('update', component)\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"create-outline\"></ion-icon>\n </ion-button>\n }\n @if(operations?.includes('delete')) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleAction('delete', component)\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n }\n </div>\n } -->\n @if(windowWidth > 639) {\n <div id=\"end\">\n <ng-content select=\"[slot='end']\"></ng-content>\n </div>\n }\n </div>\n </div>\n </div>\n </ion-item>\n @if(showSlideItems && uid) {\n <ion-item-options side=\"end\" (ionSwipe)=\"operations.length === 1 ? handleAction(operations[0], $event, component) : ''\">\n @if(operations?.includes('update')) {\n <ion-item-option class=\"dcf-update\" (click)=\"handleAction('update', $event, component)\" [expandable]=\"operations.length === 1\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"create-outline\"></ion-icon>\n </ion-item-option>\n }\n @if(operations?.includes('delete')) {\n <ion-item-option class=\"dcf- delete\" (click)=\"handleAction('delete', $event, component)\" [expandable]=\"operations.length === 1\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-item-option>\n }\n </ion-item-options>\n }\n </ion-item-sliding>\n}\n", styles: ["ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--background-hover: var(--dcf-color-gray-8);--background-focused: var(--dcf-color-gray-8)}@media (prefers-color-scheme: dark){ion-item{--background-hover-opacity: .25;--background-focused-opacity: .25}}@media (prefers-color-scheme: light){ion-item{--background-hover-opacity: .1;--background-focused-opacity: .1}}ion-item.item-lines-full{--padding-top: .5rem;--padding-bottom: .5rem;--padding-start: .25rem;-padding-end:.25rem;padding:0 .65rem}ion-item.item-lines-inset{--padding-top: 0rem !important;--padding-bottom: 0rem !important;--inner-padding-top: .5rem !important;--inner-padding-bottom: .65rem !important}@media (prefers-color-scheme: light){ion-item{--border-color: var(--dcf-color-gray-2)}ion-item .dcf-info{color:var(--dcf-color-gray-6)}ion-item .dcf-item-title{color:var(--dcf-color-gray-8)}ion-item .dcf-description{color:var(--dcf-color-gray-6)}}@media (prefers-color-scheme: dark){ion-item{--border-color: var(--dcf-color-gray-6)}ion-item .dcf-description{color:var(--dcf-color-gray-4)}}ion-item .dcf-info{min-width:10vw;background:transparent!important}ion-item .dcf-grid{padding:0!important;margin:0!important;min-width:100%!important}ion-item .dcf-item-title{font-style:normal;font-weight:700}ion-item .dcf-description{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-style:normal;font-weight:400;font-size:.925rem}ion-item::part(native){min-width:100%}ion-item [slot=start]{margin-right:.5rem!important}ion-item [slot=end]{margin-left:.5rem!important}ion-item .dcf-info{font-size:.9rem}ion-item .dcf-info .dcf-subinfo.dcf-line{margin-left:.5rem}@media (min-width: var(--dcf-width-sm)){ion-item .dcf-info .dcf-subinfo.dcf-line{display:block;margin-left:0}}ion-item #dcf-actions{padding:5px}@media (max-width: var(--dcf-width-m)){ion-item #dcf-actions{display:none;pointer-events:none!important;cursor:text!important}ion-item #dcf-actions *{display:none;pointer-events:none!important;cursor:text!important}}ion-item #dcf-actions ion-button{--padding-start: 1rem;--padding-end: .75rem;--padding-top: .85rem !important;--padding-bottom: .85rem !important;color:#ccc;margin-right:.5rem!important;--background: var(--dcf-color-gray-2) !important}ion-item #dcf-actions ion-button ion-icon{position:relative;left:-1px}@media (max-width: var(--dcf-width-m)){ion-item #dcf-end,ion-item [slot=end]{display:none!important}}ion-item #dcf-end{padding-top:5px;display:flex;align-items:flex-end}ion-item .dcf-icon{display:flex;justify-content:center;align-items:center;text-align:center;margin-right:.5rem!important}ion-item .dcf-icon.dcf-grid-icon{min-width:50px;text-align:left;display:flex;justify-content:flex-start}@media (max-width: var(--dcf-width-s)){ion-item .dcf-icon{align-items:flex-start!important}}@media (prefers-color-scheme: light){ion-item .dcf-icon ion-button{color:var(--dcf-color-gray-7);--background: var(--dcf-color-gray-1) !important}}@media (prefers-color-scheme: dark){ion-item .dcf-icon ion-button{color:var(--dcf-color-gray-1)!important;--background: var(--dcf-color-gray-7) !important}}ion-item .dcf-icon ion-button ion-icon{font-size:20px}ion-item .dcf-icon ion-avatar{width:48px;height:48px;display:flex;justify-content:center;align-items:center;text-align:center}@media (prefers-color-scheme: light){ion-item .dcf-icon ion-avatar{color:var(--dcf-color-gray-7);background:var(--dcf-color-gray-1)!important}}@media (prefers-color-scheme: dark){ion-item .dcf-icon ion-avatar{color:var(--dcf-color-gray-1)!important;background:var(--dcf-background-color)!important}}ion-item .dcf-icon ion-avatar ion-icon{font-size:20px}ion-item .dcf-icon ion-avatar .dcf-icon-large{transform:translateY(5px)}ion-item-sliding{box-sizing:border-box}@media (prefers-color-scheme: light){ion-item-sliding ion-item-option:not(.dcf-delete),ion-item-sliding ion-item-option:not(.dcf-update){background:rgba(var(--dcf-color-dark-rgb),.25)!important}ion-item-sliding ion-item-option:not(.dcf-delete) .dcf-ti,ion-item-sliding ion-item-option:not(.dcf-delete) ion-icon,ion-item-sliding ion-item-option:not(.dcf-update) .dcf-ti,ion-item-sliding ion-item-option:not(.dcf-update) ion-icon{color:var(--dcf-color-gray-7)!important}ion-item-sliding ion-item-option.dcf-delete{background:rgba(var(--dcf-color-danger-rgb),.05)!important}ion-item-sliding ion-item-option.dcf-delete .dcf-ti,ion-item-sliding ion-item-option.dcf-delete *,ion-item-sliding ion-item-option.dcf-delete ion-icon{color:var(--dcf-color-danger)!important}ion-item-sliding ion-item-option.dcf-update{background:rgba(var(--dcf-color-primary-rgb),.05)!important}ion-item-sliding ion-item-option.dcf-update .dcf-ti,ion-item-sliding ion-item-option.dcf-update ion-icon{color:var(--dcf-color-primary)!important}}@media (prefers-color-scheme: dark){ion-item-sliding ion-item-option:not(.dcf-delete),ion-item-sliding ion-item-option:not(.dcf-update){background:rgba(var(--dcf-color-dark-rgb),1)!important}ion-item-sliding ion-item-option:not(.dcf-delete) .dcf-ti,ion-item-sliding ion-item-option:not(.dcf-delete) ion-icon,ion-item-sliding ion-item-option:not(.dcf-update) .dcf-ti,ion-item-sliding ion-item-option:not(.dcf-update) ion-icon{color:var(--dcf-color-gray-2)!important}ion-item-sliding ion-item-option.dcf-delete{background:rgba(var(--dcf-color-danger-rgb),.05)!important}ion-item-sliding ion-item-option.dcf-delete .dcf-ti,ion-item-sliding ion-item-option.dcf-delete *,ion-item-sliding ion-item-option.dcf-delete ion-icon{color:var(--dcf-color-danger)!important}ion-item-sliding ion-item-option.dcf-update{background:rgba(var(--dcf-color-primary-rgb),.05)!important}ion-item-sliding ion-item-option.dcf-update .dcf-ti,ion-item-sliding ion-item-option.dcf-update ion-icon{color:var(--dcf-color-gray-2)!important}}ion-item-sliding[class*=active-slide]{border-color:var(--dcf-color-gray-3)}ion-item-sliding ion-item-option{color:var(--dcf-color-gray-5);box-shadow:inset 0 0 5px rgba(var(--dcf-color-dark-rgb),.15)!important;background:var(--dcf-color-gray-3)}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonListHeader, selector: "ion-list-header", inputs: ["color", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonItemSliding, selector: "ion-item-sliding", inputs: ["disabled"] }, { kind: "component", type: IonItemOptions, selector: "ion-item-options", inputs: ["side"] }, { kind: "component", type: IonItemOption, selector: "ion-item-option", inputs: ["color", "disabled", "download", "expandable", "href", "mode", "rel", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonPopover, selector: "ion-popover" }] }); }
|
|
6844
|
-
}
|
|
6845
|
-
|
|
6846
|
-
Dynamic(),
|
|
6847
|
-
__metadata("design:paramtypes", [])
|
|
6848
|
-
], ListItemComponent);
|
|
6849
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ListItemComponent, decorators: [{
|
|
6793
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6794
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: PaginationComponent, isStandalone: true, selector: "ngx-decaf-pagination", inputs: { totalPages: "totalPages", current: "current" }, outputs: { clickEvent: "clickEvent" }, usesInheritance: true, ngImport: i0, template: " <div [id]=\"uid\" class=\"dcf-paginator-container dcf-flex dcf-flex-center\">\n <div class=\"dcf-width-1-1\">\n <div class=\"dcf-pagination-resume\" [innerHTML]=\"locale + '.resume' | translate: {value0: current, value1: last}\"></div>\n <div #paginationComponent class=\"dcf-pagination dcf-flex-center\">\n <div\n aria-label=\"previous\"\n tabindex=\"0\"\n (click)=\"previous()\"\n (keydown.enter)=\"previous()\" [class.dcf-disabled]=\"current === 1\">\n <ion-icon name=\"chevron-back-outline\" aria-hidden=\"true\"></ion-icon>\n </div>\n @for(page of pages; track page) {\n <div tabindex=\"0\" [class]=\"page['class']\" (click)=\"navigate(page['index'])\"\n (keydown.enter)=\"navigate(page['index'])\"\n [class.dcf-active]=\"current === page['index']\">\n <span class=\"page-item\">{{ page['text'] }}</span>\n </div>\n }\n <div\n tabindex=\"0\" (click)=\"next()\"\n (keydown.enter)=\"next()\"\n [class.dcf-disabled]=\"current === last\">\n <ion-icon name=\"chevron-forward-outline\" aria-hidden=\"true\"></ion-icon>\n </div>\n </div>\n </div>\n</div>\n", styles: [".dcf-paginator-container{margin-bottom:1rem}.dcf-pagination{display:flex;flex-wrap:wrap;align-items:center;margin-left:0;padding:0;list-style:none}.dcf-pagination .page-item{display:flex;justify-content:center;align-items:center;text-align:center;font-weight:600;width:34px;line-height:34px;padding:0!important;border-radius:50%;box-sizing:border-box}@media (prefers-color-scheme: dark){.dcf-pagination .page-item{color:var(--dcf-color-gray-3)!important}}@media (prefers-color-scheme: light){.dcf-pagination .page-item{color:var(--dcf-color-gray-7)!important}}.dcf-pagination>*{flex:none;padding-left:0;position:relative;margin:0px .15rem;cursor:pointer}.dcf-pagination>*.dcf-disabled{pointer-events:none;touch-action:none;cursor:text}.dcf-pagination>*.dcf-active{pointer-events:none;touch-action:none}@media (prefers-color-scheme: light){.dcf-pagination>*.dcf-active .page-item{background:rgba(var(--dcf-color-primary-rgb),.15)}.dcf-pagination>*:hover:not(.dcf-active) *{color:var(--dcf-color-primary)!important}}@media (prefers-color-scheme: dark){.dcf-pagination>*.dcf-active .page-item{background:var(--dcf-color-gray-7)}.dcf-pagination>*:hover:not(.dcf-active) *{color:var(--dcf-color-primary)!important}}.dcf-pagination-resume{margin:1rem 0px;text-align:center}@media (prefers-color-scheme: light){.dcf-pagination-resume{color:var(--dcf-color-gray-8)}}\n"], dependencies: [{ kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
6795
|
+
}
|
|
6796
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: PaginationComponent, decorators: [{
|
|
6850
6797
|
type: Component,
|
|
6851
|
-
args: [{ selector: 'ngx-decaf-
|
|
6798
|
+
args: [{ selector: 'ngx-decaf-pagination', imports: [
|
|
6852
6799
|
TranslatePipe,
|
|
6853
|
-
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
IonIcon,
|
|
6860
|
-
IonLabel,
|
|
6861
|
-
IonButton,
|
|
6862
|
-
IonContent,
|
|
6863
|
-
IonPopover
|
|
6864
|
-
], template: "\n@if(title || description) {\n <ion-item-sliding #component>\n <ion-item\n [id]=\"uid\"\n [lines]=\"lines\"\n [button]=\"button\"\n [class]=\"className\"\n (click)=\"operations?.includes('read') ? handleAction('read', $event, component) : ''\n \">\n @if(icon && lines !== 'inset') {\n <div class=\"dcf-icon\" [slot]=\"iconSlot\">\n <ion-avatar>\n <ion-icon aria-hidden=\"true\" name=\"reader-outline\" size=\"default\"></ion-icon>\n </ion-avatar>\n </div>\n }\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-flex dcf-flex-middle dcf-grid-collapse\" dcf-grid>\n @if(icon && lines === 'inset') {\n <div class=\"dcf-icon dcf-grid-icon\">\n <ion-avatar>\n <ion-icon aria-hidden=\"true\" name=\"reader-outline\" size=\"default\"></ion-icon>\n </ion-avatar>\n </div>\n }\n <div class=\"dcf-width-expand@s dcf-width-1-1 dcf-label\">\n <ion-label class=\"dcf-item-title\" [innerHTML]=\"uid + ' - ' + title\" ></ion-label>\n @if(description) {\n <div class=\"dcf-description\" [innerHTML]=\"description\"></div>\n }\n </div>\n @if(info || subinfo) {\n <div class=\"dcf-width-auto@s dcf-width-expand dcf-info dcf-flex dcf-flex-right@s\">\n <div>\n @if(info) {\n <span [innerHTML]=\"info\"></span>\n }\n @if(subinfo) {\n <div class=\"dcf-subinfo dcf-text-truncate\" [innerHTML]=\"subinfo\" ></div>\n }\n </div>\n </div>\n }\n\n <div class=\"dcf-width-auto dcf-flex dcf-flex-middle dcf-flex-right\">\n @if((operations.includes('delete') || operations.includes('update')) && uid) {\n <div class=\"dcf-visible@m\" id=\"dcf-actions\">\n <ion-button class=\"dcf-hidden@m\" shape=\"round\" fill=\"clear\" color=\"primary\" (click)=\"presentActionsMenu($event)\">\n <ion-icon slot=\"icon-only\" aria-hidden=\"true\" name=\"ellipsis-vertical-outline\"></ion-icon>\n </ion-button>\n <ion-popover\n #actionMenuComponent\n side=\"bottom\"\n alignment=\"left\"\n\n [isOpen]=\"actionMenuOpen\"\n (didDismiss)=\"actionMenuOpen = false\">\n <ng-template>\n <ion-content class=\"ion-padding\">\n <ion-list lines=\"none\">\n <ion-list-header>\n <h4 class=\"dcf-text-capitalize\" [innerHTML]=\"'actions' | translate\"></h4>\n </ion-list-header>\n @for (operation of ['update', 'delete']; track operation) {\n @if(operations.includes(operation)) {\n <ion-item [button]=\"true\" (click)=\"handleAction(operation, $event, component)\">\n <ion-avatar class=\"dcf-flex dcf-flex-middle\" aria-hidden=\"true\" slot=\"start\">\n @if(operation === 'update') {\n <ion-icon color=\"primary\" aria-hidden=\"true\" name=\"create-outline\"></ion-icon>\n } @else {\n <ion-icon color=\"danger\" aria-hidden=\"true\" name=\"trash\"></ion-icon>\n }\n </ion-avatar>\n <ion-label class=\"dcf-text-capitalize\">{{ operation | translate }}</ion-label>\n </ion-item>\n }\n }\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n </div>\n }\n <!-- @if(operations?.length && uid) {\n <div class=\"dcf-visible@m\" id=\"dcf-actions\">\n @if(operations?.includes('update')) {\n <ion-button fill=\"clear\" size=\"small\" color=\"primary\" (click)=\"handleAction('update', component)\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"create-outline\"></ion-icon>\n </ion-button>\n }\n @if(operations?.includes('delete')) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleAction('delete', component)\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n }\n </div>\n } -->\n @if(windowWidth > 639) {\n <div id=\"end\">\n <ng-content select=\"[slot='end']\"></ng-content>\n </div>\n }\n </div>\n </div>\n </div>\n </ion-item>\n @if(showSlideItems && uid) {\n <ion-item-options side=\"end\" (ionSwipe)=\"operations.length === 1 ? handleAction(operations[0], $event, component) : ''\">\n @if(operations?.includes('update')) {\n <ion-item-option class=\"dcf-update\" (click)=\"handleAction('update', $event, component)\" [expandable]=\"operations.length === 1\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"create-outline\"></ion-icon>\n </ion-item-option>\n }\n @if(operations?.includes('delete')) {\n <ion-item-option class=\"dcf- delete\" (click)=\"handleAction('delete', $event, component)\" [expandable]=\"operations.length === 1\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-item-option>\n }\n </ion-item-options>\n }\n </ion-item-sliding>\n}\n", styles: ["ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--background-hover: var(--dcf-color-gray-8);--background-focused: var(--dcf-color-gray-8)}@media (prefers-color-scheme: dark){ion-item{--background-hover-opacity: .25;--background-focused-opacity: .25}}@media (prefers-color-scheme: light){ion-item{--background-hover-opacity: .1;--background-focused-opacity: .1}}ion-item.item-lines-full{--padding-top: .5rem;--padding-bottom: .5rem;--padding-start: .25rem;-padding-end:.25rem;padding:0 .65rem}ion-item.item-lines-inset{--padding-top: 0rem !important;--padding-bottom: 0rem !important;--inner-padding-top: .5rem !important;--inner-padding-bottom: .65rem !important}@media (prefers-color-scheme: light){ion-item{--border-color: var(--dcf-color-gray-2)}ion-item .dcf-info{color:var(--dcf-color-gray-6)}ion-item .dcf-item-title{color:var(--dcf-color-gray-8)}ion-item .dcf-description{color:var(--dcf-color-gray-6)}}@media (prefers-color-scheme: dark){ion-item{--border-color: var(--dcf-color-gray-6)}ion-item .dcf-description{color:var(--dcf-color-gray-4)}}ion-item .dcf-info{min-width:10vw;background:transparent!important}ion-item .dcf-grid{padding:0!important;margin:0!important;min-width:100%!important}ion-item .dcf-item-title{font-style:normal;font-weight:700}ion-item .dcf-description{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-style:normal;font-weight:400;font-size:.925rem}ion-item::part(native){min-width:100%}ion-item [slot=start]{margin-right:.5rem!important}ion-item [slot=end]{margin-left:.5rem!important}ion-item .dcf-info{font-size:.9rem}ion-item .dcf-info .dcf-subinfo.dcf-line{margin-left:.5rem}@media (min-width: var(--dcf-width-sm)){ion-item .dcf-info .dcf-subinfo.dcf-line{display:block;margin-left:0}}ion-item #dcf-actions{padding:5px}@media (max-width: var(--dcf-width-m)){ion-item #dcf-actions{display:none;pointer-events:none!important;cursor:text!important}ion-item #dcf-actions *{display:none;pointer-events:none!important;cursor:text!important}}ion-item #dcf-actions ion-button{--padding-start: 1rem;--padding-end: .75rem;--padding-top: .85rem !important;--padding-bottom: .85rem !important;color:#ccc;margin-right:.5rem!important;--background: var(--dcf-color-gray-2) !important}ion-item #dcf-actions ion-button ion-icon{position:relative;left:-1px}@media (max-width: var(--dcf-width-m)){ion-item #dcf-end,ion-item [slot=end]{display:none!important}}ion-item #dcf-end{padding-top:5px;display:flex;align-items:flex-end}ion-item .dcf-icon{display:flex;justify-content:center;align-items:center;text-align:center;margin-right:.5rem!important}ion-item .dcf-icon.dcf-grid-icon{min-width:50px;text-align:left;display:flex;justify-content:flex-start}@media (max-width: var(--dcf-width-s)){ion-item .dcf-icon{align-items:flex-start!important}}@media (prefers-color-scheme: light){ion-item .dcf-icon ion-button{color:var(--dcf-color-gray-7);--background: var(--dcf-color-gray-1) !important}}@media (prefers-color-scheme: dark){ion-item .dcf-icon ion-button{color:var(--dcf-color-gray-1)!important;--background: var(--dcf-color-gray-7) !important}}ion-item .dcf-icon ion-button ion-icon{font-size:20px}ion-item .dcf-icon ion-avatar{width:48px;height:48px;display:flex;justify-content:center;align-items:center;text-align:center}@media (prefers-color-scheme: light){ion-item .dcf-icon ion-avatar{color:var(--dcf-color-gray-7);background:var(--dcf-color-gray-1)!important}}@media (prefers-color-scheme: dark){ion-item .dcf-icon ion-avatar{color:var(--dcf-color-gray-1)!important;background:var(--dcf-background-color)!important}}ion-item .dcf-icon ion-avatar ion-icon{font-size:20px}ion-item .dcf-icon ion-avatar .dcf-icon-large{transform:translateY(5px)}ion-item-sliding{box-sizing:border-box}@media (prefers-color-scheme: light){ion-item-sliding ion-item-option:not(.dcf-delete),ion-item-sliding ion-item-option:not(.dcf-update){background:rgba(var(--dcf-color-dark-rgb),.25)!important}ion-item-sliding ion-item-option:not(.dcf-delete) .dcf-ti,ion-item-sliding ion-item-option:not(.dcf-delete) ion-icon,ion-item-sliding ion-item-option:not(.dcf-update) .dcf-ti,ion-item-sliding ion-item-option:not(.dcf-update) ion-icon{color:var(--dcf-color-gray-7)!important}ion-item-sliding ion-item-option.dcf-delete{background:rgba(var(--dcf-color-danger-rgb),.05)!important}ion-item-sliding ion-item-option.dcf-delete .dcf-ti,ion-item-sliding ion-item-option.dcf-delete *,ion-item-sliding ion-item-option.dcf-delete ion-icon{color:var(--dcf-color-danger)!important}ion-item-sliding ion-item-option.dcf-update{background:rgba(var(--dcf-color-primary-rgb),.05)!important}ion-item-sliding ion-item-option.dcf-update .dcf-ti,ion-item-sliding ion-item-option.dcf-update ion-icon{color:var(--dcf-color-primary)!important}}@media (prefers-color-scheme: dark){ion-item-sliding ion-item-option:not(.dcf-delete),ion-item-sliding ion-item-option:not(.dcf-update){background:rgba(var(--dcf-color-dark-rgb),1)!important}ion-item-sliding ion-item-option:not(.dcf-delete) .dcf-ti,ion-item-sliding ion-item-option:not(.dcf-delete) ion-icon,ion-item-sliding ion-item-option:not(.dcf-update) .dcf-ti,ion-item-sliding ion-item-option:not(.dcf-update) ion-icon{color:var(--dcf-color-gray-2)!important}ion-item-sliding ion-item-option.dcf-delete{background:rgba(var(--dcf-color-danger-rgb),.05)!important}ion-item-sliding ion-item-option.dcf-delete .dcf-ti,ion-item-sliding ion-item-option.dcf-delete *,ion-item-sliding ion-item-option.dcf-delete ion-icon{color:var(--dcf-color-danger)!important}ion-item-sliding ion-item-option.dcf-update{background:rgba(var(--dcf-color-primary-rgb),.05)!important}ion-item-sliding ion-item-option.dcf-update .dcf-ti,ion-item-sliding ion-item-option.dcf-update ion-icon{color:var(--dcf-color-gray-2)!important}}ion-item-sliding[class*=active-slide]{border-color:var(--dcf-color-gray-3)}ion-item-sliding ion-item-option{color:var(--dcf-color-gray-5);box-shadow:inset 0 0 5px rgba(var(--dcf-color-dark-rgb),.15)!important;background:var(--dcf-color-gray-3)}\n"] }]
|
|
6865
|
-
}], ctorParameters: () => [], propDecorators: { actionMenuComponent: [{
|
|
6866
|
-
type: ViewChild,
|
|
6867
|
-
args: ['actionMenuComponent']
|
|
6868
|
-
}], lines: [{
|
|
6869
|
-
type: Input
|
|
6870
|
-
}], item: [{
|
|
6871
|
-
type: Input
|
|
6872
|
-
}], icon: [{
|
|
6873
|
-
type: Input
|
|
6874
|
-
}], iconSlot: [{
|
|
6875
|
-
type: Input
|
|
6876
|
-
}], button: [{
|
|
6877
|
-
type: Input
|
|
6878
|
-
}], title: [{
|
|
6879
|
-
type: Input
|
|
6880
|
-
}], description: [{
|
|
6881
|
-
type: Input
|
|
6882
|
-
}], info: [{
|
|
6883
|
-
type: Input
|
|
6884
|
-
}], subinfo: [{
|
|
6800
|
+
IonIcon
|
|
6801
|
+
], standalone: true, template: " <div [id]=\"uid\" class=\"dcf-paginator-container dcf-flex dcf-flex-center\">\n <div class=\"dcf-width-1-1\">\n <div class=\"dcf-pagination-resume\" [innerHTML]=\"locale + '.resume' | translate: {value0: current, value1: last}\"></div>\n <div #paginationComponent class=\"dcf-pagination dcf-flex-center\">\n <div\n aria-label=\"previous\"\n tabindex=\"0\"\n (click)=\"previous()\"\n (keydown.enter)=\"previous()\" [class.dcf-disabled]=\"current === 1\">\n <ion-icon name=\"chevron-back-outline\" aria-hidden=\"true\"></ion-icon>\n </div>\n @for(page of pages; track page) {\n <div tabindex=\"0\" [class]=\"page['class']\" (click)=\"navigate(page['index'])\"\n (keydown.enter)=\"navigate(page['index'])\"\n [class.dcf-active]=\"current === page['index']\">\n <span class=\"page-item\">{{ page['text'] }}</span>\n </div>\n }\n <div\n tabindex=\"0\" (click)=\"next()\"\n (keydown.enter)=\"next()\"\n [class.dcf-disabled]=\"current === last\">\n <ion-icon name=\"chevron-forward-outline\" aria-hidden=\"true\"></ion-icon>\n </div>\n </div>\n </div>\n</div>\n", styles: [".dcf-paginator-container{margin-bottom:1rem}.dcf-pagination{display:flex;flex-wrap:wrap;align-items:center;margin-left:0;padding:0;list-style:none}.dcf-pagination .page-item{display:flex;justify-content:center;align-items:center;text-align:center;font-weight:600;width:34px;line-height:34px;padding:0!important;border-radius:50%;box-sizing:border-box}@media (prefers-color-scheme: dark){.dcf-pagination .page-item{color:var(--dcf-color-gray-3)!important}}@media (prefers-color-scheme: light){.dcf-pagination .page-item{color:var(--dcf-color-gray-7)!important}}.dcf-pagination>*{flex:none;padding-left:0;position:relative;margin:0px .15rem;cursor:pointer}.dcf-pagination>*.dcf-disabled{pointer-events:none;touch-action:none;cursor:text}.dcf-pagination>*.dcf-active{pointer-events:none;touch-action:none}@media (prefers-color-scheme: light){.dcf-pagination>*.dcf-active .page-item{background:rgba(var(--dcf-color-primary-rgb),.15)}.dcf-pagination>*:hover:not(.dcf-active) *{color:var(--dcf-color-primary)!important}}@media (prefers-color-scheme: dark){.dcf-pagination>*.dcf-active .page-item{background:var(--dcf-color-gray-7)}.dcf-pagination>*:hover:not(.dcf-active) *{color:var(--dcf-color-primary)!important}}.dcf-pagination-resume{margin:1rem 0px;text-align:center}@media (prefers-color-scheme: light){.dcf-pagination-resume{color:var(--dcf-color-gray-8)}}\n"] }]
|
|
6802
|
+
}], ctorParameters: () => [], propDecorators: { totalPages: [{
|
|
6803
|
+
type: Input,
|
|
6804
|
+
args: [{ required: true }]
|
|
6805
|
+
}], current: [{
|
|
6885
6806
|
type: Input
|
|
6886
6807
|
}], clickEvent: [{
|
|
6887
6808
|
type: Output
|
|
6888
|
-
}], enableSlideItems: [{
|
|
6889
|
-
type: HostListener,
|
|
6890
|
-
args: ['window:resize', ['$event']]
|
|
6891
6809
|
}] } });
|
|
6892
6810
|
|
|
6893
6811
|
/**
|
|
6894
|
-
* @description A
|
|
6895
|
-
* @summary This component provides a
|
|
6896
|
-
*
|
|
6897
|
-
*
|
|
6812
|
+
* @description A versatile list component that supports various data display modes.
|
|
6813
|
+
* @summary This component provides a flexible way to display lists of data with support
|
|
6814
|
+
* for infinite scrolling, pagination, searching, and custom item rendering. It can fetch
|
|
6815
|
+
* data from various sources including models, functions, or direct data input.
|
|
6898
6816
|
*
|
|
6899
|
-
* The component
|
|
6900
|
-
*
|
|
6901
|
-
*
|
|
6817
|
+
* The component supports two main display types:
|
|
6818
|
+
* 1. Infinite scrolling - Loads more data as the user scrolls
|
|
6819
|
+
* 2. Pagination - Displays data in pages with navigation controls
|
|
6820
|
+
*
|
|
6821
|
+
* Additional features include:
|
|
6822
|
+
* - Pull-to-refresh functionality
|
|
6823
|
+
* - Search filtering
|
|
6824
|
+
* - Empty state customization
|
|
6825
|
+
* - Custom item rendering
|
|
6826
|
+
* - Event emission for interactions
|
|
6902
6827
|
*
|
|
6903
6828
|
* @mermaid
|
|
6904
6829
|
* sequenceDiagram
|
|
6905
6830
|
* participant U as User
|
|
6906
|
-
* participant
|
|
6907
|
-
* participant
|
|
6831
|
+
* participant L as ListComponent
|
|
6832
|
+
* participant D as Data Source
|
|
6833
|
+
* participant E as External Components
|
|
6908
6834
|
*
|
|
6909
|
-
* U->>
|
|
6910
|
-
*
|
|
6911
|
-
*
|
|
6912
|
-
*
|
|
6835
|
+
* U->>L: Initialize component
|
|
6836
|
+
* L->>L: ngOnInit()
|
|
6837
|
+
* L->>D: Request initial data
|
|
6838
|
+
* D-->>L: Return data
|
|
6839
|
+
* L->>L: Process and display data
|
|
6913
6840
|
*
|
|
6914
|
-
*
|
|
6915
|
-
*
|
|
6916
|
-
*
|
|
6917
|
-
*
|
|
6841
|
+
* alt User scrolls (Infinite mode)
|
|
6842
|
+
* U->>L: Scroll to bottom
|
|
6843
|
+
* L->>D: Request more data
|
|
6844
|
+
* D-->>L: Return additional data
|
|
6845
|
+
* L->>L: Append to existing data
|
|
6846
|
+
* else User changes page (Paginated mode)
|
|
6847
|
+
* U->>L: Click page number
|
|
6848
|
+
* L->>L: handlePaginate()
|
|
6849
|
+
* L->>D: Request data for page
|
|
6850
|
+
* D-->>L: Return page data
|
|
6851
|
+
* L->>L: Replace displayed data
|
|
6852
|
+
* end
|
|
6918
6853
|
*
|
|
6919
|
-
*
|
|
6920
|
-
*
|
|
6921
|
-
*
|
|
6922
|
-
*
|
|
6854
|
+
* alt User searches
|
|
6855
|
+
* U->>L: Enter search term
|
|
6856
|
+
* L->>L: handleSearch()
|
|
6857
|
+
* L->>D: Filter data by search term
|
|
6858
|
+
* D-->>L: Return filtered data
|
|
6859
|
+
* L->>L: Update displayed data
|
|
6860
|
+
* end
|
|
6861
|
+
*
|
|
6862
|
+
* alt User clicks item
|
|
6863
|
+
* U->>L: Click list item
|
|
6864
|
+
* L->>L: handleClick()
|
|
6865
|
+
* L->>E: Emit clickEvent
|
|
6866
|
+
* end
|
|
6923
6867
|
*
|
|
6924
6868
|
* @example
|
|
6925
|
-
* <ngx-decaf-
|
|
6926
|
-
* [
|
|
6927
|
-
* [
|
|
6928
|
-
*
|
|
6929
|
-
*
|
|
6869
|
+
* <ngx-decaf-list
|
|
6870
|
+
* [source]="dataSource"
|
|
6871
|
+
* [limit]="10"
|
|
6872
|
+
* [type]="'infinite'"
|
|
6873
|
+
* [showSearchbar]="true"
|
|
6874
|
+
* (clickEvent)="handleItemClick($event)"
|
|
6875
|
+
* (refreshEvent)="handleRefresh($event)">
|
|
6876
|
+
* </ngx-decaf-list>
|
|
6930
6877
|
*
|
|
6931
6878
|
* @extends {NgxBaseComponent}
|
|
6932
6879
|
* @implements {OnInit}
|
|
6933
6880
|
*/
|
|
6934
|
-
class
|
|
6881
|
+
let ListComponent = class ListComponent extends NgxBaseComponent {
|
|
6935
6882
|
/**
|
|
6936
|
-
* @
|
|
6937
|
-
* @
|
|
6938
|
-
*
|
|
6883
|
+
* @description Initializes a new instance of the ListComponent.
|
|
6884
|
+
* @summary Creates a new ListComponent and sets up the base component with the appropriate
|
|
6885
|
+
* component name. This constructor is called when Angular instantiates the component and
|
|
6886
|
+
* before any input properties are set. It passes the component name to the parent class
|
|
6887
|
+
* constructor to enable proper localization and component identification.
|
|
6888
|
+
*
|
|
6889
|
+
* The constructor is intentionally minimal, with most initialization logic deferred to
|
|
6890
|
+
* the ngOnInit lifecycle hook. This follows Angular best practices by keeping the constructor
|
|
6891
|
+
* focused on dependency injection and basic setup, while complex initialization that depends
|
|
6892
|
+
* on input properties is handled in ngOnInit.
|
|
6893
|
+
*
|
|
6894
|
+
* @memberOf ListComponent
|
|
6939
6895
|
*/
|
|
6940
6896
|
constructor() {
|
|
6941
|
-
super("
|
|
6897
|
+
super("ListComponent");
|
|
6898
|
+
/**
|
|
6899
|
+
* @description The display mode for the list component.
|
|
6900
|
+
* @summary Determines how the list data is loaded and displayed. Options include:
|
|
6901
|
+
* - INFINITE: Loads more data as the user scrolls (infinite scrolling)
|
|
6902
|
+
* - PAGINATED: Displays data in pages with navigation controls
|
|
6903
|
+
*
|
|
6904
|
+
* @type {ListComponentsTypes}
|
|
6905
|
+
* @default ListComponentsTypes.INFINITE
|
|
6906
|
+
* @memberOf ListComponent
|
|
6907
|
+
*/
|
|
6908
|
+
this.type = ListComponentsTypes.INFINITE;
|
|
6942
6909
|
/**
|
|
6943
6910
|
* @description Controls whether the component uses translation services.
|
|
6944
6911
|
* @summary When set to true, the component will attempt to use translation services
|
|
6945
|
-
* for any text content. This allows for internationalization of the
|
|
6912
|
+
* for any text content. This allows for internationalization of the list component.
|
|
6946
6913
|
*
|
|
6947
6914
|
* @type {StringOrBoolean}
|
|
6948
6915
|
* @default true
|
|
6949
|
-
* @memberOf
|
|
6916
|
+
* @memberOf ListComponent
|
|
6950
6917
|
*/
|
|
6951
6918
|
this.translatable = true;
|
|
6952
6919
|
/**
|
|
6953
|
-
* @description
|
|
6954
|
-
* @summary
|
|
6955
|
-
* to
|
|
6920
|
+
* @description Controls the visibility of the search bar.
|
|
6921
|
+
* @summary When set to true, displays a search bar at the top of the list that allows
|
|
6922
|
+
* users to filter the list items. The search functionality works by filtering the
|
|
6923
|
+
* existing data or by triggering a new data fetch with search parameters.
|
|
6924
|
+
*
|
|
6925
|
+
* @type {StringOrBoolean}
|
|
6926
|
+
* @default true
|
|
6927
|
+
* @memberOf ListComponent
|
|
6928
|
+
*/
|
|
6929
|
+
this.showSearchbar = true;
|
|
6930
|
+
/**
|
|
6931
|
+
* @description Direct data input for the list component.
|
|
6932
|
+
* @summary Provides a way to directly pass data to the list component instead of
|
|
6933
|
+
* fetching it from a source. When both data and source are provided, the component
|
|
6934
|
+
* will use the source to fetch data only if the data array is empty.
|
|
6935
|
+
*
|
|
6936
|
+
* @type {KeyValue[] | undefined}
|
|
6937
|
+
* @default undefined
|
|
6938
|
+
* @memberOf ListComponent
|
|
6939
|
+
*/
|
|
6940
|
+
this.data = undefined;
|
|
6941
|
+
/**
|
|
6942
|
+
* @description The starting index for data fetching.
|
|
6943
|
+
* @summary Specifies the index from which to start fetching data. This is used
|
|
6944
|
+
* for pagination and infinite scrolling to determine which subset of data to load.
|
|
6956
6945
|
*
|
|
6957
6946
|
* @type {number}
|
|
6958
|
-
* @default
|
|
6959
|
-
* @memberOf
|
|
6947
|
+
* @default 0
|
|
6948
|
+
* @memberOf ListComponent
|
|
6960
6949
|
*/
|
|
6961
|
-
this.
|
|
6950
|
+
this.start = 0;
|
|
6962
6951
|
/**
|
|
6963
|
-
* @description
|
|
6964
|
-
* @summary
|
|
6965
|
-
*
|
|
6966
|
-
* about the navigation direction and the target page number.
|
|
6952
|
+
* @description The number of items to fetch per page or load operation.
|
|
6953
|
+
* @summary Determines how many items are loaded at once during pagination or
|
|
6954
|
+
* infinite scrolling. This affects the size of data chunks requested from the source.
|
|
6967
6955
|
*
|
|
6968
|
-
* @type {
|
|
6969
|
-
* @
|
|
6970
|
-
|
|
6971
|
-
this.clickEvent = new EventEmitter();
|
|
6972
|
-
addIcons({ chevronBackOutline, chevronForwardOutline });
|
|
6973
|
-
}
|
|
6974
|
-
/**
|
|
6975
|
-
* @description Initializes the component after Angular sets the input properties.
|
|
6976
|
-
* @summary Sets up the component by initializing the locale settings based on the
|
|
6977
|
-
* translatable property, generating the page numbers based on the total pages and
|
|
6978
|
-
* current page, and storing the last page number for boundary checking.
|
|
6979
|
-
*
|
|
6980
|
-
* @mermaid
|
|
6981
|
-
* sequenceDiagram
|
|
6982
|
-
* participant A as Angular Lifecycle
|
|
6983
|
-
* participant P as PaginationComponent
|
|
6984
|
-
*
|
|
6985
|
-
* A->>P: ngOnInit()
|
|
6986
|
-
* P->>P: getLocale(translatable)
|
|
6987
|
-
* P->>P: Set locale
|
|
6988
|
-
* P->>P: getPages(data, current)
|
|
6989
|
-
* P->>P: Set pages array
|
|
6990
|
-
* P->>P: Set last page number
|
|
6991
|
-
*
|
|
6992
|
-
* @returns {void}
|
|
6993
|
-
* @memberOf PaginationComponent
|
|
6994
|
-
*/
|
|
6995
|
-
ngOnInit() {
|
|
6996
|
-
this.locale = this.getLocale(this.translatable);
|
|
6997
|
-
this.pages = this.getPages(this.totalPages, this.current);
|
|
6998
|
-
this.last = this.totalPages;
|
|
6999
|
-
}
|
|
7000
|
-
/**
|
|
7001
|
-
* @description Handles click events on pagination controls.
|
|
7002
|
-
* @summary Processes user interactions with the pagination component, updating the
|
|
7003
|
-
* current page if specified and emitting an event with navigation details. This method
|
|
7004
|
-
* is called when users click on page numbers or navigation buttons.
|
|
7005
|
-
*
|
|
7006
|
-
* @param {('next' | 'previous')} direction - The direction of navigation
|
|
7007
|
-
* @param {number} [page] - Optional page number to navigate to directly
|
|
7008
|
-
* @returns {void}
|
|
7009
|
-
*
|
|
7010
|
-
* @mermaid
|
|
7011
|
-
* sequenceDiagram
|
|
7012
|
-
* participant U as User
|
|
7013
|
-
* participant P as PaginationComponent
|
|
7014
|
-
* participant E as External Component
|
|
7015
|
-
*
|
|
7016
|
-
* U->>P: Click pagination control
|
|
7017
|
-
* P->>P: handleClick(direction, page?)
|
|
7018
|
-
* alt page is provided
|
|
7019
|
-
* P->>P: Update current page
|
|
7020
|
-
* end
|
|
7021
|
-
* P->>E: Emit clickEvent with direction and page
|
|
7022
|
-
*
|
|
7023
|
-
* @memberOf PaginationComponent
|
|
7024
|
-
*/
|
|
7025
|
-
handleClick(direction, page) {
|
|
7026
|
-
if (page)
|
|
7027
|
-
this.current = page;
|
|
7028
|
-
this.clickEvent.emit({
|
|
7029
|
-
name: EventConstants.CLICK,
|
|
7030
|
-
data: {
|
|
7031
|
-
direction,
|
|
7032
|
-
page: this.current
|
|
7033
|
-
},
|
|
7034
|
-
component: this.componentName
|
|
7035
|
-
});
|
|
7036
|
-
}
|
|
7037
|
-
/**
|
|
7038
|
-
* @description Generates the array of page objects for display.
|
|
7039
|
-
* @summary Creates an array of page objects based on the total number of pages and
|
|
7040
|
-
* the current page. For small page counts (≤5), all pages are shown. For larger page
|
|
7041
|
-
* counts, a subset is shown with ellipses to indicate skipped pages. This ensures
|
|
7042
|
-
* the pagination UI remains clean and usable even with many pages.
|
|
7043
|
-
*
|
|
7044
|
-
* @param {number} total - The total number of pages
|
|
7045
|
-
* @param {number} [current] - The current active page (defaults to this.current)
|
|
7046
|
-
* @returns {KeyValue[]} Array of page objects with index and text properties
|
|
7047
|
-
*
|
|
7048
|
-
* @mermaid
|
|
7049
|
-
* flowchart TD
|
|
7050
|
-
* A[Start] --> B{total <= 5?}
|
|
7051
|
-
* B -->|Yes| C[Show all pages]
|
|
7052
|
-
* B -->|No| D[Show first page]
|
|
7053
|
-
* D --> E[Show last pages]
|
|
7054
|
-
* E --> F[Add ellipses for skipped pages]
|
|
7055
|
-
* C --> G[Return pages array]
|
|
7056
|
-
* F --> G
|
|
7057
|
-
*
|
|
7058
|
-
* @memberOf PaginationComponent
|
|
7059
|
-
*/
|
|
7060
|
-
getPages(total, current) {
|
|
7061
|
-
if (!current)
|
|
7062
|
-
current = this.current;
|
|
7063
|
-
const pages = [];
|
|
7064
|
-
function getPage(index, text = '', clazz = 'button') {
|
|
7065
|
-
if (pages.some(item => item['index'] === index))
|
|
7066
|
-
return;
|
|
7067
|
-
pages.push({ index, text: index != null ? index.toString().padStart(2, '0') : text, class: clazz });
|
|
7068
|
-
}
|
|
7069
|
-
if (total <= 5) {
|
|
7070
|
-
for (let i = 1; i <= total; i++)
|
|
7071
|
-
getPage(i);
|
|
7072
|
-
}
|
|
7073
|
-
else {
|
|
7074
|
-
// Adiciona os dois primeiros
|
|
7075
|
-
getPage(1);
|
|
7076
|
-
getPage(2);
|
|
7077
|
-
// Adiciona "..." entre os blocos
|
|
7078
|
-
if (current && current > 3)
|
|
7079
|
-
getPage(null, '...');
|
|
7080
|
-
// Adiciona a página atual (se estiver no meio)
|
|
7081
|
-
if (current && current > 2 && current < total - 1)
|
|
7082
|
-
getPage(current);
|
|
7083
|
-
// Adiciona "..." entre os blocos
|
|
7084
|
-
if (current && current < total - 2)
|
|
7085
|
-
getPage(null, '...', 'separator');
|
|
7086
|
-
// Adiciona os dois últimos
|
|
7087
|
-
getPage(total - 1);
|
|
7088
|
-
getPage(total);
|
|
7089
|
-
}
|
|
7090
|
-
return pages;
|
|
7091
|
-
}
|
|
7092
|
-
/**
|
|
7093
|
-
* @description Gets the current active page number.
|
|
7094
|
-
* @summary Returns the current page number that is active in the pagination component.
|
|
7095
|
-
* This method provides a way to access the current page state from outside the component.
|
|
7096
|
-
*
|
|
7097
|
-
* @returns {number} The current page number
|
|
7098
|
-
* @memberOf PaginationComponent
|
|
7099
|
-
*/
|
|
7100
|
-
getCurrent() {
|
|
7101
|
-
return this.current;
|
|
7102
|
-
}
|
|
7103
|
-
/**
|
|
7104
|
-
* @description Navigates to the next page.
|
|
7105
|
-
* @summary Increments the current page number if not at the last page and triggers
|
|
7106
|
-
* the click event handler with 'next' direction. This method is typically called
|
|
7107
|
-
* when the user clicks on the "next" button in the pagination UI.
|
|
7108
|
-
*
|
|
7109
|
-
* @returns {void}
|
|
7110
|
-
*
|
|
7111
|
-
* @mermaid
|
|
7112
|
-
* sequenceDiagram
|
|
7113
|
-
* participant U as User
|
|
7114
|
-
* participant P as PaginationComponent
|
|
7115
|
-
*
|
|
7116
|
-
* U->>P: Click next button
|
|
7117
|
-
* P->>P: next()
|
|
7118
|
-
* alt page <= max pages
|
|
7119
|
-
* P->>P: Increment current page
|
|
7120
|
-
* P->>P: handleClick('next')
|
|
7121
|
-
* end
|
|
7122
|
-
*
|
|
7123
|
-
* @memberOf PaginationComponent
|
|
7124
|
-
*/
|
|
7125
|
-
next() {
|
|
7126
|
-
const page = this.current + 1;
|
|
7127
|
-
if (page <= Object.keys(this.pages)?.length || 0) {
|
|
7128
|
-
this.current = page;
|
|
7129
|
-
this.handleClick('next');
|
|
7130
|
-
}
|
|
7131
|
-
}
|
|
7132
|
-
/**
|
|
7133
|
-
* @description Navigates to the previous page.
|
|
7134
|
-
* @summary Decrements the current page number if not at the first page and triggers
|
|
7135
|
-
* the click event handler with 'previous' direction. This method is typically called
|
|
7136
|
-
* when the user clicks on the "previous" button in the pagination UI.
|
|
7137
|
-
*
|
|
7138
|
-
* @returns {void}
|
|
7139
|
-
*
|
|
7140
|
-
* @mermaid
|
|
7141
|
-
* sequenceDiagram
|
|
7142
|
-
* participant U as User
|
|
7143
|
-
* participant P as PaginationComponent
|
|
7144
|
-
*
|
|
7145
|
-
* U->>P: Click previous button
|
|
7146
|
-
* P->>P: previous()
|
|
7147
|
-
* alt page > 0
|
|
7148
|
-
* P->>P: Decrement current page
|
|
7149
|
-
* P->>P: handleClick('previous')
|
|
7150
|
-
* end
|
|
7151
|
-
*
|
|
7152
|
-
* @memberOf PaginationComponent
|
|
7153
|
-
*/
|
|
7154
|
-
previous() {
|
|
7155
|
-
const page = this.current - 1;
|
|
7156
|
-
if (page > 0) {
|
|
7157
|
-
this.current = page;
|
|
7158
|
-
this.handleClick('previous');
|
|
7159
|
-
}
|
|
7160
|
-
}
|
|
7161
|
-
/**
|
|
7162
|
-
* @description Navigates to a specific page number.
|
|
7163
|
-
* @summary Updates the current page to the specified page number and triggers
|
|
7164
|
-
* the click event handler with the appropriate direction. This method is typically
|
|
7165
|
-
* called when the user clicks directly on a page number in the pagination UI.
|
|
7166
|
-
*
|
|
7167
|
-
* @param {number | null} page - The page number to navigate to
|
|
7168
|
-
* @returns {void}
|
|
7169
|
-
*
|
|
7170
|
-
* @mermaid
|
|
7171
|
-
* sequenceDiagram
|
|
7172
|
-
* participant U as User
|
|
7173
|
-
* participant P as PaginationComponent
|
|
7174
|
-
*
|
|
7175
|
-
* U->>P: Click page number
|
|
7176
|
-
* P->>P: navigate(page)
|
|
7177
|
-
* alt page is not null and different from current
|
|
7178
|
-
* P->>P: Determine direction (next/previous)
|
|
7179
|
-
* P->>P: handleClick(direction, page)
|
|
7180
|
-
* end
|
|
7181
|
-
*
|
|
7182
|
-
* @memberOf PaginationComponent
|
|
7183
|
-
*/
|
|
7184
|
-
navigate(page) {
|
|
7185
|
-
if (page !== null && this.current !== page)
|
|
7186
|
-
this.handleClick(page > this.current ? 'next' : 'previous', page);
|
|
7187
|
-
}
|
|
7188
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7189
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: PaginationComponent, isStandalone: true, selector: "ngx-decaf-pagination", inputs: { totalPages: "totalPages", current: "current" }, outputs: { clickEvent: "clickEvent" }, usesInheritance: true, ngImport: i0, template: " <div [id]=\"uid\" class=\"dcf-paginator-container dcf-flex dcf-flex-center\">\n <div class=\"dcf-width-1-1\">\n <div class=\"dcf-pagination-resume\" [innerHTML]=\"locale + '.resume' | translate: {value0: current, value1: last}\"></div>\n <div #paginationComponent class=\"dcf-pagination dcf-flex-center\">\n <div\n aria-label=\"previous\"\n tabindex=\"0\"\n (click)=\"previous()\"\n (keydown.enter)=\"previous()\" [class.dcf-disabled]=\"current === 1\">\n <ion-icon name=\"chevron-back-outline\" aria-hidden=\"true\"></ion-icon>\n </div>\n @for(page of pages; track page) {\n <div tabindex=\"0\" [class]=\"page['class']\" (click)=\"navigate(page['index'])\"\n (keydown.enter)=\"navigate(page['index'])\"\n [class.dcf-active]=\"current === page['index']\">\n <span class=\"page-item\">{{ page['text'] }}</span>\n </div>\n }\n <div\n tabindex=\"0\" (click)=\"next()\"\n (keydown.enter)=\"next()\"\n [class.dcf-disabled]=\"current === last\">\n <ion-icon name=\"chevron-forward-outline\" aria-hidden=\"true\"></ion-icon>\n </div>\n </div>\n </div>\n</div>\n", styles: [".dcf-paginator-container{margin-bottom:1rem}.dcf-pagination{display:flex;flex-wrap:wrap;align-items:center;margin-left:0;padding:0;list-style:none}.dcf-pagination .page-item{display:flex;justify-content:center;align-items:center;text-align:center;font-weight:600;width:34px;line-height:34px;padding:0!important;border-radius:50%;box-sizing:border-box}@media (prefers-color-scheme: dark){.dcf-pagination .page-item{color:var(--dcf-color-gray-3)!important}}@media (prefers-color-scheme: light){.dcf-pagination .page-item{color:var(--dcf-color-gray-7)!important}}.dcf-pagination>*{flex:none;padding-left:0;position:relative;margin:0px .15rem;cursor:pointer}.dcf-pagination>*.dcf-disabled{pointer-events:none;touch-action:none;cursor:text}.dcf-pagination>*.dcf-active{pointer-events:none;touch-action:none}@media (prefers-color-scheme: light){.dcf-pagination>*.dcf-active .page-item{background:rgba(var(--dcf-color-primary-rgb),.15)}.dcf-pagination>*:hover:not(.dcf-active) *{color:var(--dcf-color-primary)!important}}@media (prefers-color-scheme: dark){.dcf-pagination>*.dcf-active .page-item{background:var(--dcf-color-gray-7)}.dcf-pagination>*:hover:not(.dcf-active) *{color:var(--dcf-color-primary)!important}}.dcf-pagination-resume{margin:1rem 0px;text-align:center}@media (prefers-color-scheme: light){.dcf-pagination-resume{color:var(--dcf-color-gray-8)}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
|
|
7190
|
-
}
|
|
7191
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PaginationComponent, decorators: [{
|
|
7192
|
-
type: Component,
|
|
7193
|
-
args: [{ selector: 'ngx-decaf-pagination', imports: [
|
|
7194
|
-
TranslatePipe,
|
|
7195
|
-
IonIcon
|
|
7196
|
-
], standalone: true, template: " <div [id]=\"uid\" class=\"dcf-paginator-container dcf-flex dcf-flex-center\">\n <div class=\"dcf-width-1-1\">\n <div class=\"dcf-pagination-resume\" [innerHTML]=\"locale + '.resume' | translate: {value0: current, value1: last}\"></div>\n <div #paginationComponent class=\"dcf-pagination dcf-flex-center\">\n <div\n aria-label=\"previous\"\n tabindex=\"0\"\n (click)=\"previous()\"\n (keydown.enter)=\"previous()\" [class.dcf-disabled]=\"current === 1\">\n <ion-icon name=\"chevron-back-outline\" aria-hidden=\"true\"></ion-icon>\n </div>\n @for(page of pages; track page) {\n <div tabindex=\"0\" [class]=\"page['class']\" (click)=\"navigate(page['index'])\"\n (keydown.enter)=\"navigate(page['index'])\"\n [class.dcf-active]=\"current === page['index']\">\n <span class=\"page-item\">{{ page['text'] }}</span>\n </div>\n }\n <div\n tabindex=\"0\" (click)=\"next()\"\n (keydown.enter)=\"next()\"\n [class.dcf-disabled]=\"current === last\">\n <ion-icon name=\"chevron-forward-outline\" aria-hidden=\"true\"></ion-icon>\n </div>\n </div>\n </div>\n</div>\n", styles: [".dcf-paginator-container{margin-bottom:1rem}.dcf-pagination{display:flex;flex-wrap:wrap;align-items:center;margin-left:0;padding:0;list-style:none}.dcf-pagination .page-item{display:flex;justify-content:center;align-items:center;text-align:center;font-weight:600;width:34px;line-height:34px;padding:0!important;border-radius:50%;box-sizing:border-box}@media (prefers-color-scheme: dark){.dcf-pagination .page-item{color:var(--dcf-color-gray-3)!important}}@media (prefers-color-scheme: light){.dcf-pagination .page-item{color:var(--dcf-color-gray-7)!important}}.dcf-pagination>*{flex:none;padding-left:0;position:relative;margin:0px .15rem;cursor:pointer}.dcf-pagination>*.dcf-disabled{pointer-events:none;touch-action:none;cursor:text}.dcf-pagination>*.dcf-active{pointer-events:none;touch-action:none}@media (prefers-color-scheme: light){.dcf-pagination>*.dcf-active .page-item{background:rgba(var(--dcf-color-primary-rgb),.15)}.dcf-pagination>*:hover:not(.dcf-active) *{color:var(--dcf-color-primary)!important}}@media (prefers-color-scheme: dark){.dcf-pagination>*.dcf-active .page-item{background:var(--dcf-color-gray-7)}.dcf-pagination>*:hover:not(.dcf-active) *{color:var(--dcf-color-primary)!important}}.dcf-pagination-resume{margin:1rem 0px;text-align:center}@media (prefers-color-scheme: light){.dcf-pagination-resume{color:var(--dcf-color-gray-8)}}\n"] }]
|
|
7197
|
-
}], ctorParameters: () => [], propDecorators: { totalPages: [{
|
|
7198
|
-
type: Input,
|
|
7199
|
-
args: [{ required: true }]
|
|
7200
|
-
}], current: [{
|
|
7201
|
-
type: Input
|
|
7202
|
-
}], clickEvent: [{
|
|
7203
|
-
type: Output
|
|
7204
|
-
}] } });
|
|
7205
|
-
|
|
7206
|
-
/**
|
|
7207
|
-
* @description A versatile list component that supports various data display modes.
|
|
7208
|
-
* @summary This component provides a flexible way to display lists of data with support
|
|
7209
|
-
* for infinite scrolling, pagination, searching, and custom item rendering. It can fetch
|
|
7210
|
-
* data from various sources including models, functions, or direct data input.
|
|
7211
|
-
*
|
|
7212
|
-
* The component supports two main display types:
|
|
7213
|
-
* 1. Infinite scrolling - Loads more data as the user scrolls
|
|
7214
|
-
* 2. Pagination - Displays data in pages with navigation controls
|
|
7215
|
-
*
|
|
7216
|
-
* Additional features include:
|
|
7217
|
-
* - Pull-to-refresh functionality
|
|
7218
|
-
* - Search filtering
|
|
7219
|
-
* - Empty state customization
|
|
7220
|
-
* - Custom item rendering
|
|
7221
|
-
* - Event emission for interactions
|
|
7222
|
-
*
|
|
7223
|
-
* @mermaid
|
|
7224
|
-
* sequenceDiagram
|
|
7225
|
-
* participant U as User
|
|
7226
|
-
* participant L as ListComponent
|
|
7227
|
-
* participant D as Data Source
|
|
7228
|
-
* participant E as External Components
|
|
7229
|
-
*
|
|
7230
|
-
* U->>L: Initialize component
|
|
7231
|
-
* L->>L: ngOnInit()
|
|
7232
|
-
* L->>D: Request initial data
|
|
7233
|
-
* D-->>L: Return data
|
|
7234
|
-
* L->>L: Process and display data
|
|
7235
|
-
*
|
|
7236
|
-
* alt User scrolls (Infinite mode)
|
|
7237
|
-
* U->>L: Scroll to bottom
|
|
7238
|
-
* L->>D: Request more data
|
|
7239
|
-
* D-->>L: Return additional data
|
|
7240
|
-
* L->>L: Append to existing data
|
|
7241
|
-
* else User changes page (Paginated mode)
|
|
7242
|
-
* U->>L: Click page number
|
|
7243
|
-
* L->>L: handlePaginate()
|
|
7244
|
-
* L->>D: Request data for page
|
|
7245
|
-
* D-->>L: Return page data
|
|
7246
|
-
* L->>L: Replace displayed data
|
|
7247
|
-
* end
|
|
7248
|
-
*
|
|
7249
|
-
* alt User searches
|
|
7250
|
-
* U->>L: Enter search term
|
|
7251
|
-
* L->>L: handleSearch()
|
|
7252
|
-
* L->>D: Filter data by search term
|
|
7253
|
-
* D-->>L: Return filtered data
|
|
7254
|
-
* L->>L: Update displayed data
|
|
7255
|
-
* end
|
|
7256
|
-
*
|
|
7257
|
-
* alt User clicks item
|
|
7258
|
-
* U->>L: Click list item
|
|
7259
|
-
* L->>L: handleClick()
|
|
7260
|
-
* L->>E: Emit clickEvent
|
|
7261
|
-
* end
|
|
7262
|
-
*
|
|
7263
|
-
* @example
|
|
7264
|
-
* <ngx-decaf-list
|
|
7265
|
-
* [source]="dataSource"
|
|
7266
|
-
* [limit]="10"
|
|
7267
|
-
* [type]="'infinite'"
|
|
7268
|
-
* [showSearchbar]="true"
|
|
7269
|
-
* (clickEvent)="handleItemClick($event)"
|
|
7270
|
-
* (refreshEvent)="handleRefresh($event)">
|
|
7271
|
-
* </ngx-decaf-list>
|
|
7272
|
-
*
|
|
7273
|
-
* @extends {NgxBaseComponent}
|
|
7274
|
-
* @implements {OnInit}
|
|
7275
|
-
*/
|
|
7276
|
-
let ListComponent = class ListComponent extends NgxBaseComponent {
|
|
7277
|
-
/**
|
|
7278
|
-
* @description Initializes a new instance of the ListComponent.
|
|
7279
|
-
* @summary Creates a new ListComponent and sets up the base component with the appropriate
|
|
7280
|
-
* component name. This constructor is called when Angular instantiates the component and
|
|
7281
|
-
* before any input properties are set. It passes the component name to the parent class
|
|
7282
|
-
* constructor to enable proper localization and component identification.
|
|
7283
|
-
*
|
|
7284
|
-
* The constructor is intentionally minimal, with most initialization logic deferred to
|
|
7285
|
-
* the ngOnInit lifecycle hook. This follows Angular best practices by keeping the constructor
|
|
7286
|
-
* focused on dependency injection and basic setup, while complex initialization that depends
|
|
7287
|
-
* on input properties is handled in ngOnInit.
|
|
7288
|
-
*
|
|
7289
|
-
* @memberOf ListComponent
|
|
7290
|
-
*/
|
|
7291
|
-
constructor() {
|
|
7292
|
-
super("ListComponent");
|
|
7293
|
-
/**
|
|
7294
|
-
* @description The display mode for the list component.
|
|
7295
|
-
* @summary Determines how the list data is loaded and displayed. Options include:
|
|
7296
|
-
* - INFINITE: Loads more data as the user scrolls (infinite scrolling)
|
|
7297
|
-
* - PAGINATED: Displays data in pages with navigation controls
|
|
7298
|
-
*
|
|
7299
|
-
* @type {ListComponentsTypes}
|
|
7300
|
-
* @default ListComponentsTypes.INFINITE
|
|
7301
|
-
* @memberOf ListComponent
|
|
7302
|
-
*/
|
|
7303
|
-
this.type = ListComponentsTypes.INFINITE;
|
|
7304
|
-
/**
|
|
7305
|
-
* @description Controls whether the component uses translation services.
|
|
7306
|
-
* @summary When set to true, the component will attempt to use translation services
|
|
7307
|
-
* for any text content. This allows for internationalization of the list component.
|
|
7308
|
-
*
|
|
7309
|
-
* @type {StringOrBoolean}
|
|
7310
|
-
* @default true
|
|
7311
|
-
* @memberOf ListComponent
|
|
7312
|
-
*/
|
|
7313
|
-
this.translatable = true;
|
|
7314
|
-
/**
|
|
7315
|
-
* @description Controls the visibility of the search bar.
|
|
7316
|
-
* @summary When set to true, displays a search bar at the top of the list that allows
|
|
7317
|
-
* users to filter the list items. The search functionality works by filtering the
|
|
7318
|
-
* existing data or by triggering a new data fetch with search parameters.
|
|
7319
|
-
*
|
|
7320
|
-
* @type {StringOrBoolean}
|
|
7321
|
-
* @default true
|
|
7322
|
-
* @memberOf ListComponent
|
|
7323
|
-
*/
|
|
7324
|
-
this.showSearchbar = true;
|
|
7325
|
-
/**
|
|
7326
|
-
* @description Direct data input for the list component.
|
|
7327
|
-
* @summary Provides a way to directly pass data to the list component instead of
|
|
7328
|
-
* fetching it from a source. When both data and source are provided, the component
|
|
7329
|
-
* will use the source to fetch data only if the data array is empty.
|
|
7330
|
-
*
|
|
7331
|
-
* @type {KeyValue[] | undefined}
|
|
7332
|
-
* @default undefined
|
|
7333
|
-
* @memberOf ListComponent
|
|
7334
|
-
*/
|
|
7335
|
-
this.data = undefined;
|
|
7336
|
-
/**
|
|
7337
|
-
* @description The starting index for data fetching.
|
|
7338
|
-
* @summary Specifies the index from which to start fetching data. This is used
|
|
7339
|
-
* for pagination and infinite scrolling to determine which subset of data to load.
|
|
7340
|
-
*
|
|
7341
|
-
* @type {number}
|
|
7342
|
-
* @default 0
|
|
7343
|
-
* @memberOf ListComponent
|
|
7344
|
-
*/
|
|
7345
|
-
this.start = 0;
|
|
7346
|
-
/**
|
|
7347
|
-
* @description The number of items to fetch per page or load operation.
|
|
7348
|
-
* @summary Determines how many items are loaded at once during pagination or
|
|
7349
|
-
* infinite scrolling. This affects the size of data chunks requested from the source.
|
|
7350
|
-
*
|
|
7351
|
-
* @type {number}
|
|
7352
|
-
* @default 10
|
|
7353
|
-
* @memberOf ListComponent
|
|
6956
|
+
* @type {number}
|
|
6957
|
+
* @default 10
|
|
6958
|
+
* @memberOf ListComponent
|
|
7354
6959
|
*/
|
|
7355
6960
|
this.limit = 10;
|
|
7356
6961
|
/**
|
|
@@ -7583,851 +7188,1230 @@ let ListComponent = class ListComponent extends NgxBaseComponent {
|
|
|
7583
7188
|
*/
|
|
7584
7189
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7585
7190
|
this.observerSubjet = new Subject();
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7191
|
+
}
|
|
7192
|
+
/**
|
|
7193
|
+
* @description Initializes the component after Angular sets the input properties.
|
|
7194
|
+
* @summary Sets up the component by initializing event subscriptions, processing boolean
|
|
7195
|
+
* inputs, and loading the initial data. This method prepares the component for user
|
|
7196
|
+
* interaction by ensuring all properties are properly initialized and data is loaded.
|
|
7197
|
+
*
|
|
7198
|
+
* @returns {Promise<void>}
|
|
7199
|
+
*
|
|
7200
|
+
* @mermaid
|
|
7201
|
+
* sequenceDiagram
|
|
7202
|
+
* participant A as Angular Lifecycle
|
|
7203
|
+
* participant L as ListComponent
|
|
7204
|
+
* participant D as Data Source
|
|
7205
|
+
*
|
|
7206
|
+
* A->>L: ngOnInit()
|
|
7207
|
+
* L->>L: Set up click event debouncing
|
|
7208
|
+
* L->>L: Process boolean inputs
|
|
7209
|
+
* L->>L: Configure component based on inputs
|
|
7210
|
+
* L->>L: refresh()
|
|
7211
|
+
* L->>D: Request initial data
|
|
7212
|
+
* D-->>L: Return data
|
|
7213
|
+
* L->>L: Process and display data
|
|
7214
|
+
* L->>L: Configure empty state if needed
|
|
7215
|
+
* L->>L: initialize()
|
|
7216
|
+
*
|
|
7217
|
+
* @memberOf ListComponent
|
|
7218
|
+
*/
|
|
7219
|
+
async ngOnInit() {
|
|
7596
7220
|
this.observer = { refresh: async (...args) => this.observeRepository(...args) };
|
|
7221
|
+
this.clickItemSubject.pipe(debounceTime(100)).subscribe(event => this.clickEventEmit(event));
|
|
7222
|
+
this.observerSubjet.pipe(debounceTime(100)).subscribe(args => this.handleObserveEvent(args[0], args[1], args[2]));
|
|
7223
|
+
this.enableFilter = stringToBoolean(this.enableFilter);
|
|
7224
|
+
this.limit = Number(this.limit);
|
|
7225
|
+
this.start = Number(this.start);
|
|
7226
|
+
this.inset = stringToBoolean(this.inset);
|
|
7227
|
+
this.showRefresher = stringToBoolean(this.showRefresher);
|
|
7228
|
+
this.loadMoreData = stringToBoolean(this.loadMoreData);
|
|
7229
|
+
this.showSearchbar = stringToBoolean(this.showSearchbar);
|
|
7230
|
+
this.disableSort = stringToBoolean(this.disableSort);
|
|
7231
|
+
if (typeof this.item?.['tag'] === 'boolean' && this.item?.['tag'] === true)
|
|
7232
|
+
this.item['tag'] = ComponentsTagNames.LIST_ITEM;
|
|
7233
|
+
await this.refresh();
|
|
7234
|
+
if (this.operations.includes(OperationKeys.CREATE) && this.route)
|
|
7235
|
+
this.empty.link = `${this.route}/${OperationKeys.CREATE}`;
|
|
7236
|
+
await this.initialize();
|
|
7237
|
+
if (this.model instanceof Model && this._repository)
|
|
7238
|
+
this._repository.observe(this.observer);
|
|
7239
|
+
}
|
|
7240
|
+
/**
|
|
7241
|
+
* @description Cleans up resources when the component is destroyed.
|
|
7242
|
+
* @summary Performs cleanup operations when the component is being removed from the DOM.
|
|
7243
|
+
* This includes clearing references to models and data to prevent memory leaks.
|
|
7244
|
+
*
|
|
7245
|
+
* @returns {void}
|
|
7246
|
+
* @memberOf ListComponent
|
|
7247
|
+
*/
|
|
7248
|
+
ngOnDestroy() {
|
|
7249
|
+
if (this._repository)
|
|
7250
|
+
this._repository.unObserve(this.observer);
|
|
7251
|
+
this.data = this.model = this._repository = this.paginator = undefined;
|
|
7252
|
+
}
|
|
7253
|
+
/**
|
|
7254
|
+
* @description Handles repository observation events with debouncing.
|
|
7255
|
+
* @summary Processes repository change notifications and routes them appropriately.
|
|
7256
|
+
* For CREATE events with a UID, handles them immediately. For other events,
|
|
7257
|
+
* passes them to the debounced observer subject to prevent excessive updates.
|
|
7258
|
+
*
|
|
7259
|
+
* @param {...unknown[]} args - The repository event arguments including table, event type, and UID
|
|
7260
|
+
* @returns {Promise<void>}
|
|
7261
|
+
* @memberOf ListComponent
|
|
7262
|
+
*/
|
|
7263
|
+
async observeRepository(...args) {
|
|
7264
|
+
const [table, event, uid] = args;
|
|
7265
|
+
if (event === OperationKeys.CREATE && !!uid)
|
|
7266
|
+
return this.handleObserveEvent(table, event, uid);
|
|
7267
|
+
return this.observerSubjet.next(args);
|
|
7268
|
+
}
|
|
7269
|
+
/**
|
|
7270
|
+
* @description Handles specific repository events and updates the list accordingly.
|
|
7271
|
+
* @summary Processes repository change events (CREATE, UPDATE, DELETE) and performs
|
|
7272
|
+
* the appropriate list operations. This includes adding new items, updating existing
|
|
7273
|
+
* ones, or removing deleted items from the list display.
|
|
7274
|
+
*
|
|
7275
|
+
* @param {string} table - The table/model name that changed
|
|
7276
|
+
* @param {OperationKeys} event - The type of operation (CREATE, UPDATE, DELETE)
|
|
7277
|
+
* @param {string | number} uid - The unique identifier of the affected item
|
|
7278
|
+
* @returns {Promise<void>}
|
|
7279
|
+
* @memberOf ListComponent
|
|
7280
|
+
*/
|
|
7281
|
+
async handleObserveEvent(table, event, uid) {
|
|
7282
|
+
if (event === OperationKeys.CREATE) {
|
|
7283
|
+
if (uid) {
|
|
7284
|
+
await this.handleCreate(uid);
|
|
7285
|
+
}
|
|
7286
|
+
else {
|
|
7287
|
+
await this.refresh(true);
|
|
7288
|
+
}
|
|
7289
|
+
}
|
|
7290
|
+
else {
|
|
7291
|
+
if (event === OperationKeys.UPDATE)
|
|
7292
|
+
await this.handleUpdate(uid);
|
|
7293
|
+
if (event === OperationKeys.DELETE)
|
|
7294
|
+
this.handleDelete(uid);
|
|
7295
|
+
this.refreshEventEmit();
|
|
7296
|
+
}
|
|
7297
|
+
}
|
|
7298
|
+
/**
|
|
7299
|
+
* @description Function for tracking items in the list.
|
|
7300
|
+
* @summary Provides a tracking function for the `*ngFor` directive in the component template.
|
|
7301
|
+
* This function is used to identify and control the rendering of items in the list,
|
|
7302
|
+
* preventing duplicate or unnecessary rendering.
|
|
7303
|
+
*
|
|
7304
|
+
* The `trackItemFn` function takes two parameters: `index` (the index of the item in the list)
|
|
7305
|
+
* and `item` (the actual item from the list). It returns the tracking key, which in this case
|
|
7306
|
+
* is the union of the `uid` of the item with the model name.
|
|
7307
|
+
*
|
|
7308
|
+
* @param {number} index - The index of the item in the list.
|
|
7309
|
+
|
|
7310
|
+
* @param {KeyValue | string | number} item - The actual item from the list.
|
|
7311
|
+
* @returns {string | number} The tracking key for the item.
|
|
7312
|
+
* @memberOf ListComponent
|
|
7313
|
+
*/
|
|
7314
|
+
trackItemFn(index, item) {
|
|
7315
|
+
return `${item?.['uid'] || item?.[this.pk]}-${index}`;
|
|
7316
|
+
}
|
|
7317
|
+
/**
|
|
7318
|
+
* Handles the create event from the repository.
|
|
7319
|
+
*
|
|
7320
|
+
* @param {string | number} uid - The ID of the item to create.
|
|
7321
|
+
* @returns {Promise<void>} A promise that resolves when the item is created and added to the list.
|
|
7322
|
+
*/
|
|
7323
|
+
async handleCreate(uid) {
|
|
7324
|
+
const result = await this._repository?.read(uid);
|
|
7325
|
+
const item = this.mapResults([result])[0];
|
|
7326
|
+
this.items = this.data = [item, ...this.items || []];
|
|
7327
|
+
}
|
|
7328
|
+
/**
|
|
7329
|
+
* @description Handles the update event from the repository.
|
|
7330
|
+
* @summary Updates the list item with the specified ID based on the new data.
|
|
7331
|
+
*
|
|
7332
|
+
* @param {string | number} uid - The ID of the item to update
|
|
7333
|
+
* @returns {Promise<void>}
|
|
7334
|
+
* @private
|
|
7335
|
+
* @memberOf ListComponent
|
|
7336
|
+
*/
|
|
7337
|
+
async handleUpdate(uid) {
|
|
7338
|
+
const item = this.itemMapper(await this._repository?.read(uid) || {}, this.mapper);
|
|
7339
|
+
this.data = [];
|
|
7340
|
+
for (const key in this.items) {
|
|
7341
|
+
const child = this.items[key];
|
|
7342
|
+
if (child['uid'] === item['uid']) {
|
|
7343
|
+
this.items[key] = Object.assign({}, child, item);
|
|
7344
|
+
break;
|
|
7345
|
+
}
|
|
7346
|
+
}
|
|
7347
|
+
setTimeout(() => {
|
|
7348
|
+
this.data = [...this.items];
|
|
7349
|
+
}, 0);
|
|
7350
|
+
}
|
|
7351
|
+
/**
|
|
7352
|
+
* @description Removes an item from the list by ID.
|
|
7353
|
+
* @summary Filters out an item with the specified ID from the data array and
|
|
7354
|
+
* refreshes the list display. This is typically used after a delete operation.
|
|
7355
|
+
*
|
|
7356
|
+
* @param {string} uid - The ID of the item to delete
|
|
7357
|
+
* @param {string} pk - The primary key field name
|
|
7358
|
+
* @returns {Promise<void>}
|
|
7359
|
+
*
|
|
7360
|
+
* @memberOf ListComponent
|
|
7361
|
+
*/
|
|
7362
|
+
handleDelete(uid, pk) {
|
|
7363
|
+
if (!pk)
|
|
7364
|
+
pk = this.pk;
|
|
7365
|
+
this.items = this.data?.filter((item) => item['uid'] !== uid) || [];
|
|
7366
|
+
}
|
|
7367
|
+
/**
|
|
7368
|
+
* @description Handles click events from list items.
|
|
7369
|
+
* @summary Listens for global ListItemClickEvent events and passes them to the
|
|
7370
|
+
* debounced click subject. This allows the component to respond to clicks on
|
|
7371
|
+
* list items regardless of where they originate from.
|
|
7372
|
+
*
|
|
7373
|
+
* @param {ListItemCustomEvent | RendererCustomEvent} event - The click event
|
|
7374
|
+
* @returns {void}
|
|
7375
|
+
*
|
|
7376
|
+
* @memberOf ListComponent
|
|
7377
|
+
*/
|
|
7378
|
+
handleClick(event) {
|
|
7379
|
+
this.clickItemSubject.next(event);
|
|
7597
7380
|
}
|
|
7598
7381
|
/**
|
|
7599
|
-
* @description
|
|
7600
|
-
* @summary
|
|
7601
|
-
*
|
|
7602
|
-
*
|
|
7382
|
+
* @description Handles search events from the search bar.
|
|
7383
|
+
* @summary Processes search queries from the search bar component, updating the
|
|
7384
|
+
* displayed data based on the search term. The behavior differs between infinite
|
|
7385
|
+
* and paginated modes to provide the best user experience for each mode.
|
|
7603
7386
|
*
|
|
7387
|
+
* @param {string | undefined} value - The search term or undefined to clear search
|
|
7604
7388
|
* @returns {Promise<void>}
|
|
7605
7389
|
*
|
|
7606
7390
|
* @mermaid
|
|
7607
|
-
*
|
|
7608
|
-
*
|
|
7609
|
-
*
|
|
7610
|
-
*
|
|
7391
|
+
* flowchart TD
|
|
7392
|
+
* A[Search Event] --> B{Type is Infinite?}
|
|
7393
|
+
* B -->|Yes| C[Disable loadMoreData]
|
|
7394
|
+
* B -->|No| D[Enable loadMoreData]
|
|
7395
|
+
* C --> E{Search value undefined?}
|
|
7396
|
+
* E -->|Yes| F[Enable loadMoreData]
|
|
7397
|
+
* E -->|No| G[Store search value]
|
|
7398
|
+
* D --> G
|
|
7399
|
+
* F --> H[Reset page to 1]
|
|
7400
|
+
* G --> I[Refresh data]
|
|
7401
|
+
* H --> I
|
|
7611
7402
|
*
|
|
7612
|
-
*
|
|
7613
|
-
|
|
7614
|
-
|
|
7615
|
-
|
|
7616
|
-
|
|
7617
|
-
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7403
|
+
* @memberOf ListComponent
|
|
7404
|
+
*/
|
|
7405
|
+
async handleSearch(value) {
|
|
7406
|
+
if (this.type === ListComponentsTypes.INFINITE) {
|
|
7407
|
+
this.loadMoreData = false;
|
|
7408
|
+
if (value === undefined) {
|
|
7409
|
+
this.loadMoreData = true;
|
|
7410
|
+
this.page = 1;
|
|
7411
|
+
}
|
|
7412
|
+
this.searchValue = value;
|
|
7413
|
+
await this.refresh(true);
|
|
7414
|
+
}
|
|
7415
|
+
else {
|
|
7416
|
+
this.loadMoreData = true;
|
|
7417
|
+
this.searchValue = value;
|
|
7418
|
+
if (value === undefined)
|
|
7419
|
+
this.page = this.lastPage;
|
|
7420
|
+
await this.refresh(true);
|
|
7421
|
+
}
|
|
7422
|
+
}
|
|
7423
|
+
/**
|
|
7424
|
+
* @description Handles filter events from the filter component.
|
|
7425
|
+
* @summary Processes filter queries from the filter component and applies them
|
|
7426
|
+
* to the list data. This method acts as a bridge between the filter component
|
|
7427
|
+
* and the search functionality, converting filter queries into search operations.
|
|
7428
|
+
*
|
|
7429
|
+
* @param {IFilterQuery | undefined} value - The filter query object or undefined to clear filters
|
|
7430
|
+
* @returns {Promise<void>}
|
|
7431
|
+
* @memberOf ListComponent
|
|
7432
|
+
*/
|
|
7433
|
+
async handleFilter(value) {
|
|
7434
|
+
await this.handleSearch(value);
|
|
7435
|
+
}
|
|
7436
|
+
/**
|
|
7437
|
+
* @description Clears the current search and resets the list.
|
|
7438
|
+
* @summary Convenience method that clears the search by calling handleSearch
|
|
7439
|
+
* with undefined. This resets the list to show all data without filtering.
|
|
7622
7440
|
*
|
|
7441
|
+
* @returns {Promise<void>}
|
|
7623
7442
|
* @memberOf ListComponent
|
|
7624
7443
|
*/
|
|
7625
|
-
async
|
|
7626
|
-
|
|
7627
|
-
this.observerSubjet.pipe(debounceTime(100)).subscribe(args => this.handleObserveEvent(args[0], args[1], args[2]));
|
|
7628
|
-
this.enableFilter = stringToBoolean(this.enableFilter);
|
|
7629
|
-
this.limit = Number(this.limit);
|
|
7630
|
-
this.start = Number(this.start);
|
|
7631
|
-
this.inset = stringToBoolean(this.inset);
|
|
7632
|
-
this.showRefresher = stringToBoolean(this.showRefresher);
|
|
7633
|
-
this.loadMoreData = stringToBoolean(this.loadMoreData);
|
|
7634
|
-
this.showSearchbar = stringToBoolean(this.showSearchbar);
|
|
7635
|
-
this.disableSort = stringToBoolean(this.disableSort);
|
|
7636
|
-
if (typeof this.item?.['tag'] === 'boolean' && this.item?.['tag'] === true)
|
|
7637
|
-
this.item['tag'] = ComponentsTagNames.LIST_ITEM;
|
|
7638
|
-
await this.refresh();
|
|
7639
|
-
if (this.operations.includes(OperationKeys.CREATE) && this.route)
|
|
7640
|
-
this.empty.link = `${this.route}/${OperationKeys.CREATE}`;
|
|
7641
|
-
await this.initialize();
|
|
7642
|
-
if (this.model instanceof Model && this._repository)
|
|
7643
|
-
this._repository.observe(this.observer);
|
|
7444
|
+
async clearSearch() {
|
|
7445
|
+
await this.handleSearch(undefined);
|
|
7644
7446
|
}
|
|
7645
7447
|
/**
|
|
7646
|
-
* @description
|
|
7647
|
-
* @summary
|
|
7648
|
-
* This
|
|
7448
|
+
* @description Emits a refresh event with the current data.
|
|
7449
|
+
* @summary Creates and emits a refresh event containing the current list data.
|
|
7450
|
+
* This notifies parent components that the list data has been refreshed.
|
|
7649
7451
|
*
|
|
7452
|
+
* @param {KeyValue[]} [data] - Optional data to include in the event
|
|
7650
7453
|
* @returns {void}
|
|
7454
|
+
*
|
|
7651
7455
|
* @memberOf ListComponent
|
|
7652
7456
|
*/
|
|
7653
|
-
|
|
7654
|
-
if (
|
|
7655
|
-
this.
|
|
7656
|
-
this.
|
|
7457
|
+
refreshEventEmit(data) {
|
|
7458
|
+
if (!data)
|
|
7459
|
+
data = this.items;
|
|
7460
|
+
this.skeletonData = new Array(data?.length || 2);
|
|
7461
|
+
this.refreshEvent.emit({
|
|
7462
|
+
name: EventConstants.REFRESH,
|
|
7463
|
+
data: data || [],
|
|
7464
|
+
component: this.componentName
|
|
7465
|
+
});
|
|
7657
7466
|
}
|
|
7658
7467
|
/**
|
|
7659
|
-
* @description
|
|
7660
|
-
* @summary Processes
|
|
7661
|
-
*
|
|
7662
|
-
*
|
|
7468
|
+
* @description Emits a click event for a list item.
|
|
7469
|
+
* @summary Processes and emits a click event when a list item is clicked.
|
|
7470
|
+
* This extracts the relevant data from the event and passes it to parent components.
|
|
7471
|
+
*
|
|
7472
|
+
* @private
|
|
7473
|
+
* @param {ListItemCustomEvent | RendererCustomEvent} event - The click event
|
|
7474
|
+
* @returns {void}
|
|
7663
7475
|
*
|
|
7664
|
-
* @param {...unknown[]} args - The repository event arguments including table, event type, and UID
|
|
7665
|
-
* @returns {Promise<void>}
|
|
7666
7476
|
* @memberOf ListComponent
|
|
7667
7477
|
*/
|
|
7668
|
-
|
|
7669
|
-
|
|
7670
|
-
if (event === OperationKeys.CREATE && !!uid)
|
|
7671
|
-
return this.handleObserveEvent(table, event, uid);
|
|
7672
|
-
return this.observerSubjet.next(args);
|
|
7478
|
+
clickEventEmit(event) {
|
|
7479
|
+
this.clickEvent.emit(event);
|
|
7673
7480
|
}
|
|
7674
7481
|
/**
|
|
7675
|
-
* @description
|
|
7676
|
-
* @summary
|
|
7677
|
-
*
|
|
7678
|
-
*
|
|
7482
|
+
* @description Refreshes the list data from the configured source.
|
|
7483
|
+
* @summary This method handles both initial data loading and subsequent refresh operations,
|
|
7484
|
+
* including pull-to-refresh and infinite scrolling. It manages the data fetching process,
|
|
7485
|
+
* updates the component's state, and handles pagination or infinite scrolling logic based
|
|
7486
|
+
* on the component's configuration.
|
|
7487
|
+
*
|
|
7488
|
+
* The method performs the following steps:
|
|
7489
|
+
* 1. Sets the refreshing flag to indicate a data fetch is in progress
|
|
7490
|
+
* 2. Calculates the appropriate start and limit values based on pagination settings
|
|
7491
|
+
* 3. Fetches data from the appropriate source (model or request)
|
|
7492
|
+
* 4. Updates the component's data and emits a refresh event
|
|
7493
|
+
* 5. Handles pagination or infinite scrolling state updates
|
|
7494
|
+
* 6. Completes any provided event (like InfiniteScrollCustomEvent)
|
|
7495
|
+
*
|
|
7496
|
+
* @param {InfiniteScrollCustomEvent | RefresherCustomEvent | boolean} event - The event that triggered the refresh,
|
|
7497
|
+
* or a boolean flag indicating if this is a forced refresh
|
|
7498
|
+
* @returns {Promise<void>} A promise that resolves when the refresh operation is complete
|
|
7499
|
+
*
|
|
7500
|
+
* @mermaid
|
|
7501
|
+
* sequenceDiagram
|
|
7502
|
+
* participant L as ListComponent
|
|
7503
|
+
* participant D as Data Source
|
|
7504
|
+
* participant E as Event System
|
|
7505
|
+
*
|
|
7506
|
+
* L->>L: refresh(event)
|
|
7507
|
+
* L->>L: Set refreshing flag
|
|
7508
|
+
* L->>L: Calculate start and limit
|
|
7509
|
+
* alt Using model
|
|
7510
|
+
* L->>D: getFromModel(force, start, limit)
|
|
7511
|
+
* D-->>L: Return data
|
|
7512
|
+
* else Using request
|
|
7513
|
+
* L->>D: getFromRequest(force, start, limit)
|
|
7514
|
+
* D-->>L: Return data
|
|
7515
|
+
* end
|
|
7516
|
+
* L->>E: refreshEventEmit()
|
|
7517
|
+
* alt Infinite scrolling mode
|
|
7518
|
+
* L->>L: Check if reached last page
|
|
7519
|
+
* alt Last page reached
|
|
7520
|
+
* L->>L: Complete scroll event
|
|
7521
|
+
* L->>L: Disable loadMoreData
|
|
7522
|
+
* else More pages available
|
|
7523
|
+
* L->>L: Increment page number
|
|
7524
|
+
* L->>L: Complete scroll event after delay
|
|
7525
|
+
* end
|
|
7526
|
+
* else Paginated mode
|
|
7527
|
+
* L->>L: Clear refreshing flag after delay
|
|
7528
|
+
* end
|
|
7679
7529
|
*
|
|
7680
|
-
* @param {string} table - The table/model name that changed
|
|
7681
|
-
* @param {OperationKeys} event - The type of operation (CREATE, UPDATE, DELETE)
|
|
7682
|
-
* @param {string | number} uid - The unique identifier of the affected item
|
|
7683
|
-
* @returns {Promise<void>}
|
|
7684
7530
|
* @memberOf ListComponent
|
|
7685
7531
|
*/
|
|
7686
|
-
async
|
|
7687
|
-
if
|
|
7688
|
-
|
|
7689
|
-
|
|
7532
|
+
async refresh(event = false) {
|
|
7533
|
+
// if(typeof force !== 'boolean' && force.type === EventConstants.BACK_BUTTON_NAVIGATION) {
|
|
7534
|
+
// const {refresh} = (force as CustomEvent).detail;
|
|
7535
|
+
// if(!refresh)
|
|
7536
|
+
// return false;
|
|
7537
|
+
// }
|
|
7538
|
+
this.refreshing = true;
|
|
7539
|
+
const start = this.page > 1 ? (this.page - 1) * this.limit : this.start;
|
|
7540
|
+
const limit = (this.page * (this.limit > 12 ? 12 : this.limit));
|
|
7541
|
+
this.data = !this.model ?
|
|
7542
|
+
await this.getFromRequest(!!event, start, limit)
|
|
7543
|
+
: await this.getFromModel(!!event);
|
|
7544
|
+
this.refreshEventEmit();
|
|
7545
|
+
if (this.type === ListComponentsTypes.INFINITE) {
|
|
7546
|
+
if (this.page === this.pages) {
|
|
7547
|
+
if (event?.target)
|
|
7548
|
+
event.target.complete();
|
|
7549
|
+
this.loadMoreData = false;
|
|
7690
7550
|
}
|
|
7691
7551
|
else {
|
|
7692
|
-
|
|
7552
|
+
this.page += 1;
|
|
7553
|
+
this.refreshing = false;
|
|
7554
|
+
setTimeout(() => {
|
|
7555
|
+
if (event?.target && event?.type !== EventConstants.BACK_BUTTON_NAVIGATION)
|
|
7556
|
+
event.target.complete();
|
|
7557
|
+
}, 200);
|
|
7693
7558
|
}
|
|
7694
7559
|
}
|
|
7695
7560
|
else {
|
|
7696
|
-
|
|
7697
|
-
|
|
7698
|
-
|
|
7699
|
-
this.handleDelete(uid);
|
|
7700
|
-
this.refreshEventEmit();
|
|
7561
|
+
setTimeout(() => {
|
|
7562
|
+
this.refreshing = false;
|
|
7563
|
+
}, 200);
|
|
7701
7564
|
}
|
|
7702
7565
|
}
|
|
7703
7566
|
/**
|
|
7704
|
-
|
|
7705
|
-
|
|
7706
|
-
|
|
7707
|
-
|
|
7708
|
-
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
*/
|
|
7719
|
-
trackItemFn(index, item) {
|
|
7720
|
-
return `${item?.['uid'] || item?.[this.pk]}-${index}`;
|
|
7567
|
+
* @description Handles pagination events from the pagination component.
|
|
7568
|
+
* @summary Processes pagination events by updating the current page number and
|
|
7569
|
+
* refreshing the list data to display the selected page. This method is called
|
|
7570
|
+
* when a user interacts with the pagination controls to navigate between pages.
|
|
7571
|
+
*
|
|
7572
|
+
* @param {PaginationCustomEvent} event - The pagination event containing page information
|
|
7573
|
+
* @returns {void}
|
|
7574
|
+
*
|
|
7575
|
+
* @memberOf ListComponent
|
|
7576
|
+
*/
|
|
7577
|
+
handlePaginate(event) {
|
|
7578
|
+
const { page } = event.data;
|
|
7579
|
+
this.page = page;
|
|
7580
|
+
this.refresh(true);
|
|
7721
7581
|
}
|
|
7722
7582
|
/**
|
|
7723
|
-
* Handles
|
|
7583
|
+
* @description Handles pull-to-refresh events from the refresher component.
|
|
7584
|
+
* @summary Processes refresh events triggered by the user pulling down on the list
|
|
7585
|
+
* or by programmatic refresh requests. This method refreshes the list data and
|
|
7586
|
+
* completes the refresher animation when the data is loaded.
|
|
7724
7587
|
*
|
|
7725
|
-
* @param {
|
|
7726
|
-
* @returns {Promise<void>} A promise that resolves when the
|
|
7727
|
-
*/
|
|
7728
|
-
async handleCreate(uid) {
|
|
7729
|
-
const result = await this._repository?.read(uid);
|
|
7730
|
-
const item = this.mapResults([result])[0];
|
|
7731
|
-
this.items = this.data = [item, ...this.items || []];
|
|
7732
|
-
}
|
|
7733
|
-
/**
|
|
7734
|
-
* @description Handles the update event from the repository.
|
|
7735
|
-
* @summary Updates the list item with the specified ID based on the new data.
|
|
7588
|
+
* @param {InfiniteScrollCustomEvent | CustomEvent} [event] - The refresh event
|
|
7589
|
+
* @returns {Promise<void>} A promise that resolves when the refresh operation is complete
|
|
7736
7590
|
*
|
|
7737
|
-
* @param {string | number} uid - The ID of the item to update
|
|
7738
|
-
* @returns {Promise<void>}
|
|
7739
|
-
* @private
|
|
7740
7591
|
* @memberOf ListComponent
|
|
7741
7592
|
*/
|
|
7742
|
-
async
|
|
7743
|
-
|
|
7744
|
-
|
|
7745
|
-
|
|
7746
|
-
|
|
7747
|
-
|
|
7748
|
-
|
|
7749
|
-
break;
|
|
7750
|
-
}
|
|
7751
|
-
}
|
|
7752
|
-
setTimeout(() => {
|
|
7753
|
-
this.data = [...this.items];
|
|
7754
|
-
}, 0);
|
|
7593
|
+
async handleRefresh(event) {
|
|
7594
|
+
await this.refresh(event || true);
|
|
7595
|
+
if (event instanceof CustomEvent)
|
|
7596
|
+
setTimeout(() => {
|
|
7597
|
+
// Any calls to load data go here
|
|
7598
|
+
event.target.complete();
|
|
7599
|
+
}, 400);
|
|
7755
7600
|
}
|
|
7756
7601
|
/**
|
|
7757
|
-
* @description
|
|
7758
|
-
* @summary
|
|
7759
|
-
*
|
|
7602
|
+
* @description Filters data based on a search string.
|
|
7603
|
+
* @summary Processes the current data array to find items that match the provided
|
|
7604
|
+
* search string. This uses the arrayQueryByString utility to perform the filtering
|
|
7605
|
+
* across all properties of the items.
|
|
7760
7606
|
*
|
|
7761
|
-
* @param {
|
|
7762
|
-
* @param {string}
|
|
7763
|
-
* @returns {
|
|
7607
|
+
* @param {KeyValue[]} results - The array of items to search through
|
|
7608
|
+
* @param {string} search - The search string to filter by
|
|
7609
|
+
* @returns {KeyValue[]} A promise that resolves to the filtered array of items
|
|
7764
7610
|
*
|
|
7765
7611
|
* @memberOf ListComponent
|
|
7766
7612
|
*/
|
|
7767
|
-
|
|
7768
|
-
|
|
7769
|
-
pk = this.pk;
|
|
7770
|
-
this.items = this.data?.filter((item) => item['uid'] !== uid) || [];
|
|
7613
|
+
parseSearchResults(results, search) {
|
|
7614
|
+
return results.filter((item) => Object.values(item).some(value => value.toString().toLowerCase().includes(search?.toLowerCase())));
|
|
7771
7615
|
}
|
|
7772
7616
|
/**
|
|
7773
|
-
* @description
|
|
7774
|
-
* @summary
|
|
7775
|
-
*
|
|
7776
|
-
*
|
|
7617
|
+
* @description Fetches data from a request source.
|
|
7618
|
+
* @summary Retrieves data from the configured source function or URL, processes it,
|
|
7619
|
+
* and updates the component's data state. This method handles both initial data loading
|
|
7620
|
+
* and subsequent refresh operations when using an external data source rather than a model.
|
|
7777
7621
|
*
|
|
7778
|
-
* @param {
|
|
7779
|
-
* @
|
|
7622
|
+
* @param {boolean} force - Whether to force a refresh even if data already exists
|
|
7623
|
+
* @param {number} start - The starting index for pagination
|
|
7624
|
+
* @param {number} limit - The maximum number of items to retrieve
|
|
7625
|
+
* @returns {Promise<KeyValue[]>} A promise that resolves to the fetched data
|
|
7780
7626
|
*
|
|
7781
7627
|
* @memberOf ListComponent
|
|
7782
7628
|
*/
|
|
7783
|
-
|
|
7784
|
-
|
|
7629
|
+
async getFromRequest(force = false, start, limit) {
|
|
7630
|
+
let request = [];
|
|
7631
|
+
if (!this.data?.length || force || this.searchValue?.length || !!this.searchValue) {
|
|
7632
|
+
// (self.data as ListItem[]) = [];
|
|
7633
|
+
if (!this.searchValue?.length && !this.searchValue) {
|
|
7634
|
+
if (!this.source && !this.data?.length) {
|
|
7635
|
+
this.logger.info('No data and source passed to infinite list');
|
|
7636
|
+
return [];
|
|
7637
|
+
}
|
|
7638
|
+
if (this.source instanceof Function)
|
|
7639
|
+
request = await this.source();
|
|
7640
|
+
if (!Array.isArray(request))
|
|
7641
|
+
request = request?.['response']?.['data'] || request?.['results'] || [];
|
|
7642
|
+
this.data = [...await this.parseResult(request)];
|
|
7643
|
+
if (this.data?.length)
|
|
7644
|
+
this.items = this.type === ListComponentsTypes.INFINITE ?
|
|
7645
|
+
(this.items || []).concat([...this.data.slice(start, limit)]) : [...request.slice(start, limit)];
|
|
7646
|
+
}
|
|
7647
|
+
else {
|
|
7648
|
+
this.data = this.parseSearchResults(this.data, this.searchValue);
|
|
7649
|
+
this.items = this.data;
|
|
7650
|
+
}
|
|
7651
|
+
}
|
|
7652
|
+
if (this.loadMoreData && this.type === ListComponentsTypes.PAGINATED)
|
|
7653
|
+
this.getMoreData(this.data?.length || 0);
|
|
7654
|
+
return this.data || [];
|
|
7785
7655
|
}
|
|
7786
7656
|
/**
|
|
7787
|
-
* @description
|
|
7788
|
-
* @summary
|
|
7789
|
-
*
|
|
7790
|
-
* and
|
|
7791
|
-
*
|
|
7792
|
-
* @param {string | undefined} value - The search term or undefined to clear search
|
|
7793
|
-
* @returns {Promise<void>}
|
|
7657
|
+
* @description Fetches data from a model source.
|
|
7658
|
+
* @summary Retrieves data from the configured model using its pagination or find methods,
|
|
7659
|
+
* processes it, and updates the component's data state. This method handles both initial
|
|
7660
|
+
* data loading and subsequent refresh operations when using a model as the data source.
|
|
7794
7661
|
*
|
|
7795
|
-
* @
|
|
7796
|
-
*
|
|
7797
|
-
*
|
|
7798
|
-
*
|
|
7799
|
-
* B -->|No| D[Enable loadMoreData]
|
|
7800
|
-
* C --> E{Search value undefined?}
|
|
7801
|
-
* E -->|Yes| F[Enable loadMoreData]
|
|
7802
|
-
* E -->|No| G[Store search value]
|
|
7803
|
-
* D --> G
|
|
7804
|
-
* F --> H[Reset page to 1]
|
|
7805
|
-
* G --> I[Refresh data]
|
|
7806
|
-
* H --> I
|
|
7662
|
+
* @param {boolean} force - Whether to force a refresh even if data already exists
|
|
7663
|
+
* @param {number} start - The starting index for pagination
|
|
7664
|
+
* @param {number} limit - The maximum number of items to retrieve
|
|
7665
|
+
* @returns {Promise<KeyValue[]>} A promise that resolves to the fetched data
|
|
7807
7666
|
*
|
|
7808
7667
|
* @memberOf ListComponent
|
|
7809
7668
|
*/
|
|
7810
|
-
async
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
7814
|
-
|
|
7815
|
-
|
|
7669
|
+
async getFromModel(force = false) {
|
|
7670
|
+
let data = [...this.data || []];
|
|
7671
|
+
let request = [];
|
|
7672
|
+
// getting model repository
|
|
7673
|
+
if (!this._repository)
|
|
7674
|
+
this._repository = this.repository;
|
|
7675
|
+
const repo = this._repository;
|
|
7676
|
+
if (!this.data?.length || force || this.searchValue?.length || !!this.searchValue) {
|
|
7677
|
+
try {
|
|
7678
|
+
if (!this.searchValue?.length && !this.searchValue) {
|
|
7679
|
+
this.data = [];
|
|
7680
|
+
// const rawQuery = this.parseQuery(self.model as Repository<Model>, start, limit);
|
|
7681
|
+
// request = this.parseResult(await (this.model as any)?.paginate(start, limit));
|
|
7682
|
+
if (!this.paginator) {
|
|
7683
|
+
this.paginator = await repo
|
|
7684
|
+
.select()
|
|
7685
|
+
.orderBy([this.pk, this.sortDirection])
|
|
7686
|
+
.paginate(this.limit);
|
|
7687
|
+
}
|
|
7688
|
+
request = await this.parseResult(this.paginator);
|
|
7689
|
+
}
|
|
7690
|
+
else {
|
|
7691
|
+
if (!this.indexes)
|
|
7692
|
+
this.indexes = (Object.values(this.mapper) || [this.pk]);
|
|
7693
|
+
const condition = this.parseConditions(this.searchValue);
|
|
7694
|
+
request = await this.parseResult(await repo.query(condition, (this.sortBy || this.pk), this.sortDirection));
|
|
7695
|
+
data = [];
|
|
7696
|
+
}
|
|
7697
|
+
data = this.type === ListComponentsTypes.INFINITE ? [...(data).concat(request)] : [...request];
|
|
7698
|
+
}
|
|
7699
|
+
catch (error) {
|
|
7700
|
+
this.logger.error(error?.message || `Unable to find ${this.model} on registry. Return empty array from component`);
|
|
7816
7701
|
}
|
|
7817
|
-
this.searchValue = value;
|
|
7818
|
-
await this.refresh(true);
|
|
7819
7702
|
}
|
|
7820
|
-
|
|
7821
|
-
this.
|
|
7822
|
-
|
|
7823
|
-
|
|
7824
|
-
|
|
7825
|
-
|
|
7703
|
+
if (data?.length) {
|
|
7704
|
+
if (this.searchValue) {
|
|
7705
|
+
this.items = [...data];
|
|
7706
|
+
if (this.items?.length <= this.limit)
|
|
7707
|
+
this.loadMoreData = false;
|
|
7708
|
+
}
|
|
7709
|
+
else {
|
|
7710
|
+
this.items = [...data];
|
|
7711
|
+
}
|
|
7826
7712
|
}
|
|
7713
|
+
if (this.type === ListComponentsTypes.PAGINATED && this.paginator)
|
|
7714
|
+
this.getMoreData(this.paginator.total);
|
|
7715
|
+
return data || [];
|
|
7827
7716
|
}
|
|
7828
7717
|
/**
|
|
7829
|
-
* @description
|
|
7830
|
-
* @summary
|
|
7831
|
-
*
|
|
7832
|
-
*
|
|
7718
|
+
* @description Converts search values or filter queries into database conditions.
|
|
7719
|
+
* @summary Transforms search input or complex filter queries into Condition objects
|
|
7720
|
+
* that can be used for database querying. Handles both simple string/number searches
|
|
7721
|
+
* across indexed fields and complex filter queries with multiple criteria.
|
|
7833
7722
|
*
|
|
7834
|
-
*
|
|
7835
|
-
*
|
|
7836
|
-
*
|
|
7837
|
-
|
|
7838
|
-
async handleFilter(value) {
|
|
7839
|
-
await this.handleSearch(value);
|
|
7840
|
-
}
|
|
7841
|
-
/**
|
|
7842
|
-
* @description Clears the current search and resets the list.
|
|
7843
|
-
* @summary Convenience method that clears the search by calling handleSearch
|
|
7844
|
-
* with undefined. This resets the list to show all data without filtering.
|
|
7723
|
+
* For simple searches (string/number):
|
|
7724
|
+
* - Creates conditions that search across all indexed fields
|
|
7725
|
+
* - Uses equality for numeric values and regex for string values
|
|
7726
|
+
* - Combines conditions with OR logic to search multiple fields
|
|
7845
7727
|
*
|
|
7846
|
-
*
|
|
7728
|
+
* For complex filter queries:
|
|
7729
|
+
* - Processes each filter item with its specific condition type
|
|
7730
|
+
* - Supports Equal, Not Equal, Contains, Not Contains, Greater Than, Less Than
|
|
7731
|
+
* - Updates sort configuration based on the filter query
|
|
7732
|
+
* - Combines multiple filter conditions with OR logic
|
|
7733
|
+
*
|
|
7734
|
+
* @param {string | number | IFilterQuery} value - The search value or filter query object
|
|
7735
|
+
* @returns {Condition<Model>} A Condition object for database querying
|
|
7847
7736
|
* @memberOf ListComponent
|
|
7848
7737
|
*/
|
|
7849
|
-
|
|
7850
|
-
|
|
7738
|
+
parseConditions(value) {
|
|
7739
|
+
let _condition;
|
|
7740
|
+
if (typeof value === Primitives.STRING || typeof value === Primitives.NUMBER) {
|
|
7741
|
+
_condition = Condition.attribute(this.pk).eq(!isNaN(value) ? Number(value) : value);
|
|
7742
|
+
for (const index of this.indexes) {
|
|
7743
|
+
if (index === this.pk)
|
|
7744
|
+
continue;
|
|
7745
|
+
let orCondition;
|
|
7746
|
+
if (!isNaN(value)) {
|
|
7747
|
+
orCondition = Condition.attribute(index).eq(Number(value));
|
|
7748
|
+
}
|
|
7749
|
+
else {
|
|
7750
|
+
orCondition = Condition.attribute(index).regexp(value);
|
|
7751
|
+
}
|
|
7752
|
+
_condition = _condition.or(orCondition);
|
|
7753
|
+
}
|
|
7754
|
+
}
|
|
7755
|
+
else {
|
|
7756
|
+
const { query, sort } = value;
|
|
7757
|
+
_condition = Condition.attribute(this.pk).dif('null');
|
|
7758
|
+
if (query?.length)
|
|
7759
|
+
_condition = undefined;
|
|
7760
|
+
(query || []).forEach((item) => {
|
|
7761
|
+
const { value, condition, index } = item;
|
|
7762
|
+
let val = value;
|
|
7763
|
+
if (index === this.pk || !isNaN(val))
|
|
7764
|
+
val = Number(val);
|
|
7765
|
+
let orCondition;
|
|
7766
|
+
switch (condition) {
|
|
7767
|
+
case "Equal":
|
|
7768
|
+
orCondition = Condition.attribute(index).eq(val);
|
|
7769
|
+
break;
|
|
7770
|
+
case "Not Equal":
|
|
7771
|
+
orCondition = Condition.attribute(index).dif(val);
|
|
7772
|
+
break;
|
|
7773
|
+
case "Not Contains":
|
|
7774
|
+
orCondition = !Condition.attribute(index).regexp(new RegExp(`^(?!.*${val}).*$`));
|
|
7775
|
+
break;
|
|
7776
|
+
case "Contains":
|
|
7777
|
+
orCondition = Condition.attribute(index).regexp(val);
|
|
7778
|
+
break;
|
|
7779
|
+
case "Greater Than":
|
|
7780
|
+
orCondition = Condition.attribute(index).gte(val);
|
|
7781
|
+
break;
|
|
7782
|
+
case "Less Than":
|
|
7783
|
+
orCondition = Condition.attribute(index).lte(val);
|
|
7784
|
+
break;
|
|
7785
|
+
}
|
|
7786
|
+
_condition = (!_condition ?
|
|
7787
|
+
orCondition : _condition.and(orCondition));
|
|
7788
|
+
});
|
|
7789
|
+
this.sortBy = sort?.value || this.pk;
|
|
7790
|
+
this.sortDirection = sort?.direction || this.sortDirection;
|
|
7791
|
+
}
|
|
7792
|
+
return _condition;
|
|
7851
7793
|
}
|
|
7852
7794
|
/**
|
|
7853
|
-
* @description
|
|
7854
|
-
* @summary
|
|
7855
|
-
*
|
|
7795
|
+
* @description Processes query results into a standardized format.
|
|
7796
|
+
* @summary Handles different result formats from various data sources, extracting
|
|
7797
|
+
* pagination information when available and applying any configured data mapping.
|
|
7798
|
+
* This ensures consistent data structure regardless of the source.
|
|
7856
7799
|
*
|
|
7857
|
-
* @
|
|
7858
|
-
* @
|
|
7800
|
+
* @protected
|
|
7801
|
+
* @param {KeyValue[] | Paginator} result - The raw query result
|
|
7802
|
+
* @returns {KeyValue[]} The processed array of items
|
|
7859
7803
|
*
|
|
7860
7804
|
* @memberOf ListComponent
|
|
7861
7805
|
*/
|
|
7862
|
-
|
|
7863
|
-
if (!
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
|
|
7806
|
+
async parseResult(result) {
|
|
7807
|
+
if (!Array.isArray(result) && ('page' in result && 'total' in result)) {
|
|
7808
|
+
const paginator = result;
|
|
7809
|
+
try {
|
|
7810
|
+
result = await paginator.page(this.page);
|
|
7811
|
+
// TODO: Chage for result.total;
|
|
7812
|
+
this.getMoreData(paginator.total);
|
|
7813
|
+
}
|
|
7814
|
+
catch (error) {
|
|
7815
|
+
this.logger.info(error?.message || 'Unable to get page from paginator. Return empty array from component');
|
|
7816
|
+
result = [];
|
|
7817
|
+
}
|
|
7818
|
+
}
|
|
7819
|
+
else {
|
|
7820
|
+
this.getMoreData(result?.length || 0);
|
|
7821
|
+
}
|
|
7822
|
+
return (Object.keys(this.mapper || {}).length) ?
|
|
7823
|
+
this.mapResults(result) : result;
|
|
7871
7824
|
}
|
|
7872
7825
|
/**
|
|
7873
|
-
* @description
|
|
7874
|
-
* @summary
|
|
7875
|
-
*
|
|
7826
|
+
* @description Updates pagination state based on data length.
|
|
7827
|
+
* @summary Calculates whether more data is available and how many pages exist
|
|
7828
|
+
* based on the total number of items and the configured limit per page.
|
|
7829
|
+
* This information is used to control pagination UI and infinite scrolling behavior.
|
|
7876
7830
|
*
|
|
7877
|
-
* @
|
|
7878
|
-
* @param {ListItemCustomEvent | RendererCustomEvent} event - The click event
|
|
7831
|
+
* @param {number} length - The total number of items available
|
|
7879
7832
|
* @returns {void}
|
|
7880
7833
|
*
|
|
7881
7834
|
* @memberOf ListComponent
|
|
7882
7835
|
*/
|
|
7883
|
-
|
|
7884
|
-
this.clickEvent.emit(event);
|
|
7885
|
-
}
|
|
7886
|
-
/**
|
|
7887
|
-
* @description Refreshes the list data from the configured source.
|
|
7888
|
-
* @summary This method handles both initial data loading and subsequent refresh operations,
|
|
7889
|
-
* including pull-to-refresh and infinite scrolling. It manages the data fetching process,
|
|
7890
|
-
* updates the component's state, and handles pagination or infinite scrolling logic based
|
|
7891
|
-
* on the component's configuration.
|
|
7892
|
-
*
|
|
7893
|
-
* The method performs the following steps:
|
|
7894
|
-
* 1. Sets the refreshing flag to indicate a data fetch is in progress
|
|
7895
|
-
* 2. Calculates the appropriate start and limit values based on pagination settings
|
|
7896
|
-
* 3. Fetches data from the appropriate source (model or request)
|
|
7897
|
-
* 4. Updates the component's data and emits a refresh event
|
|
7898
|
-
* 5. Handles pagination or infinite scrolling state updates
|
|
7899
|
-
* 6. Completes any provided event (like InfiniteScrollCustomEvent)
|
|
7900
|
-
*
|
|
7901
|
-
* @param {InfiniteScrollCustomEvent | RefresherCustomEvent | boolean} event - The event that triggered the refresh,
|
|
7902
|
-
* or a boolean flag indicating if this is a forced refresh
|
|
7903
|
-
* @returns {Promise<void>} A promise that resolves when the refresh operation is complete
|
|
7904
|
-
*
|
|
7905
|
-
* @mermaid
|
|
7906
|
-
* sequenceDiagram
|
|
7907
|
-
* participant L as ListComponent
|
|
7908
|
-
* participant D as Data Source
|
|
7909
|
-
* participant E as Event System
|
|
7910
|
-
*
|
|
7911
|
-
* L->>L: refresh(event)
|
|
7912
|
-
* L->>L: Set refreshing flag
|
|
7913
|
-
* L->>L: Calculate start and limit
|
|
7914
|
-
* alt Using model
|
|
7915
|
-
* L->>D: getFromModel(force, start, limit)
|
|
7916
|
-
* D-->>L: Return data
|
|
7917
|
-
* else Using request
|
|
7918
|
-
* L->>D: getFromRequest(force, start, limit)
|
|
7919
|
-
* D-->>L: Return data
|
|
7920
|
-
* end
|
|
7921
|
-
* L->>E: refreshEventEmit()
|
|
7922
|
-
* alt Infinite scrolling mode
|
|
7923
|
-
* L->>L: Check if reached last page
|
|
7924
|
-
* alt Last page reached
|
|
7925
|
-
* L->>L: Complete scroll event
|
|
7926
|
-
* L->>L: Disable loadMoreData
|
|
7927
|
-
* else More pages available
|
|
7928
|
-
* L->>L: Increment page number
|
|
7929
|
-
* L->>L: Complete scroll event after delay
|
|
7930
|
-
* end
|
|
7931
|
-
* else Paginated mode
|
|
7932
|
-
* L->>L: Clear refreshing flag after delay
|
|
7933
|
-
* end
|
|
7934
|
-
*
|
|
7935
|
-
* @memberOf ListComponent
|
|
7936
|
-
*/
|
|
7937
|
-
async refresh(event = false) {
|
|
7938
|
-
// if(typeof force !== 'boolean' && force.type === EventConstants.BACK_BUTTON_NAVIGATION) {
|
|
7939
|
-
// const {refresh} = (force as CustomEvent).detail;
|
|
7940
|
-
// if(!refresh)
|
|
7941
|
-
// return false;
|
|
7942
|
-
// }
|
|
7943
|
-
this.refreshing = true;
|
|
7944
|
-
const start = this.page > 1 ? (this.page - 1) * this.limit : this.start;
|
|
7945
|
-
const limit = (this.page * (this.limit > 12 ? 12 : this.limit));
|
|
7946
|
-
this.data = !this.model ?
|
|
7947
|
-
await this.getFromRequest(!!event, start, limit)
|
|
7948
|
-
: await this.getFromModel(!!event);
|
|
7949
|
-
this.refreshEventEmit();
|
|
7836
|
+
getMoreData(length) {
|
|
7950
7837
|
if (this.type === ListComponentsTypes.INFINITE) {
|
|
7951
|
-
if (this.
|
|
7952
|
-
|
|
7953
|
-
|
|
7838
|
+
if (this.paginator)
|
|
7839
|
+
length = length * this.limit;
|
|
7840
|
+
if (length <= this.limit) {
|
|
7954
7841
|
this.loadMoreData = false;
|
|
7955
7842
|
}
|
|
7956
7843
|
else {
|
|
7957
|
-
this.
|
|
7958
|
-
this.
|
|
7959
|
-
|
|
7960
|
-
|
|
7961
|
-
|
|
7962
|
-
}, 200);
|
|
7844
|
+
this.pages = Math.floor(length / this.limit);
|
|
7845
|
+
if ((this.pages * this.limit) < length)
|
|
7846
|
+
this.pages += 1;
|
|
7847
|
+
if (this.pages === 1)
|
|
7848
|
+
this.loadMoreData = false;
|
|
7963
7849
|
}
|
|
7964
7850
|
}
|
|
7965
7851
|
else {
|
|
7966
|
-
|
|
7967
|
-
|
|
7968
|
-
|
|
7852
|
+
this.pages = length;
|
|
7853
|
+
if (this.pages === 1)
|
|
7854
|
+
this.loadMoreData = false;
|
|
7969
7855
|
}
|
|
7970
7856
|
}
|
|
7971
7857
|
/**
|
|
7972
|
-
|
|
7973
|
-
|
|
7974
|
-
|
|
7975
|
-
|
|
7976
|
-
*
|
|
7977
|
-
* @param {PaginationCustomEvent} event - The pagination event containing page information
|
|
7978
|
-
* @returns {void}
|
|
7979
|
-
*
|
|
7980
|
-
* @memberOf ListComponent
|
|
7981
|
-
*/
|
|
7982
|
-
handlePaginate(event) {
|
|
7983
|
-
const { page } = event.data;
|
|
7984
|
-
this.page = page;
|
|
7985
|
-
this.refresh(true);
|
|
7986
|
-
}
|
|
7987
|
-
/**
|
|
7988
|
-
* @description Handles pull-to-refresh events from the refresher component.
|
|
7989
|
-
* @summary Processes refresh events triggered by the user pulling down on the list
|
|
7990
|
-
* or by programmatic refresh requests. This method refreshes the list data and
|
|
7991
|
-
* completes the refresher animation when the data is loaded.
|
|
7858
|
+
* @description Maps a single item using the configured mapper.
|
|
7859
|
+
* @summary Transforms a data item according to the mapping configuration,
|
|
7860
|
+
* extracting nested properties and formatting values as needed. This allows
|
|
7861
|
+
* the component to display data in a format different from how it's stored.
|
|
7992
7862
|
*
|
|
7993
|
-
* @
|
|
7994
|
-
* @
|
|
7863
|
+
* @protected
|
|
7864
|
+
* @param {KeyValue} item - The item to map
|
|
7865
|
+
* @param {KeyValue} mapper - The mapping configuration
|
|
7866
|
+
* @param {KeyValue} [props] - Additional properties to include
|
|
7867
|
+
* @returns {KeyValue} The mapped item
|
|
7995
7868
|
*
|
|
7996
7869
|
* @memberOf ListComponent
|
|
7997
7870
|
*/
|
|
7998
|
-
|
|
7999
|
-
|
|
8000
|
-
|
|
8001
|
-
|
|
8002
|
-
|
|
8003
|
-
|
|
8004
|
-
|
|
7871
|
+
itemMapper(item, mapper, props) {
|
|
7872
|
+
return Object.entries(mapper).reduce((accum, [key, value]) => {
|
|
7873
|
+
const arrayValue = value.split('.');
|
|
7874
|
+
if (!value) {
|
|
7875
|
+
accum[key] = value;
|
|
7876
|
+
}
|
|
7877
|
+
else {
|
|
7878
|
+
if (arrayValue.length === 1) {
|
|
7879
|
+
value = item?.[value] ? item[value] : value !== key ? value : "";
|
|
7880
|
+
if (isValidDate(value))
|
|
7881
|
+
value = `${formatDate(value)}`;
|
|
7882
|
+
accum[key] = value;
|
|
7883
|
+
}
|
|
7884
|
+
else {
|
|
7885
|
+
let val;
|
|
7886
|
+
for (const _value of arrayValue)
|
|
7887
|
+
val = !val
|
|
7888
|
+
? item[_value]
|
|
7889
|
+
: (typeof val === 'string' ? JSON.parse(val) : val)[_value];
|
|
7890
|
+
if (isValidDate(new Date(val)))
|
|
7891
|
+
val = `${formatDate(val)}`;
|
|
7892
|
+
accum[key] = val === null || val === undefined ? value : val;
|
|
7893
|
+
}
|
|
7894
|
+
}
|
|
7895
|
+
return Object.assign({}, props || {}, accum);
|
|
7896
|
+
}, {});
|
|
8005
7897
|
}
|
|
8006
7898
|
/**
|
|
8007
|
-
* @description
|
|
8008
|
-
* @summary
|
|
8009
|
-
*
|
|
8010
|
-
*
|
|
7899
|
+
* @description Maps all result items using the configured mapper.
|
|
7900
|
+
* @summary Applies the itemMapper to each item in the result set, adding
|
|
7901
|
+
* common properties like operations and route information. This transforms
|
|
7902
|
+
* the raw data into the format expected by the list item components.
|
|
8011
7903
|
*
|
|
8012
|
-
* @param {KeyValue[]}
|
|
8013
|
-
* @
|
|
8014
|
-
* @returns {KeyValue[]} A promise that resolves to the filtered array of items
|
|
7904
|
+
* @param {KeyValue[]} data - The array of items to map
|
|
7905
|
+
* @returns {KeyValue[]} The array of mapped items
|
|
8015
7906
|
*
|
|
8016
7907
|
* @memberOf ListComponent
|
|
8017
7908
|
*/
|
|
8018
|
-
|
|
8019
|
-
|
|
7909
|
+
mapResults(data) {
|
|
7910
|
+
if (!data || !data.length)
|
|
7911
|
+
return [];
|
|
7912
|
+
// passing uid as prop to mapper
|
|
7913
|
+
this.mapper = { ...this.mapper, ...{ uid: this.pk } };
|
|
7914
|
+
const props = Object.assign({
|
|
7915
|
+
operations: this.operations,
|
|
7916
|
+
route: this.route,
|
|
7917
|
+
...Object.keys(this.item).reduce((acc, key) => {
|
|
7918
|
+
acc[key] = this.item[key];
|
|
7919
|
+
return acc;
|
|
7920
|
+
}, {}),
|
|
7921
|
+
// ... (!this.item.render ? {} : Object.keys(this.item).reduce((acc: KeyValue, key: string) => {
|
|
7922
|
+
// acc[key] = this.item[key as keyof IListItemProp];
|
|
7923
|
+
// return acc;
|
|
7924
|
+
// }, {}))
|
|
7925
|
+
});
|
|
7926
|
+
return data.reduce((accum, curr) => {
|
|
7927
|
+
accum.push({ ...this.itemMapper(curr, this.mapper, props), ...{ pk: this.pk } });
|
|
7928
|
+
return accum;
|
|
7929
|
+
}, []);
|
|
8020
7930
|
}
|
|
7931
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7932
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: ListComponent, isStandalone: true, selector: "ngx-decaf-list", inputs: { type: "type", translatable: "translatable", showSearchbar: "showSearchbar", data: "data", source: "source", start: "start", limit: "limit", loadMoreData: "loadMoreData", lines: "lines", inset: "inset", scrollThreshold: "scrollThreshold", scrollPosition: "scrollPosition", loadingText: "loadingText", showRefresher: "showRefresher", loadingSpinner: "loadingSpinner", enableFilter: "enableFilter", sortDirection: "sortDirection", sortBy: "sortBy", disableSort: "disableSort", emptyIcon: "emptyIcon", empty: "empty" }, outputs: { refreshEvent: "refreshEvent", clickEvent: "clickEvent" }, host: { listeners: { "window:ListItemClickEvent": "handleClick($event)", "window:searchbarEvent": "handleSearch($event)", "window:BackButtonNavigationEndEvent": "refresh($event)" } }, usesInheritance: true, ngImport: i0, template: "\n@if(showRefresher) {\n <ion-refresher slot=\"fixed\" [pullFactor]=\"1\" [pullMin]=\"100\" [pullMax]=\"200\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content />\n </ion-refresher>\n}\n\n@if(showSearchbar && data?.length) {\n @if(model && enableFilter) {\n <ngx-decaf-filter\n [model]=\"model\"\n [sortDirection]=\"sortDirection\"\n [disableSort]=\"disableSort\"\n (filterEvent)=\"handleFilter($event)\"\n (searchEvent)=\"handleSearch($event)\"\n />\n } @else {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n }\n}\n\n@if(data?.length) {\n <ion-list [id]=\"uid\" [inset]=\"inset\" [lines]=\"lines\" #component>\n @if(item?.tag) {\n @for(child of items; track trackItemFn($index, child)) {\n <ngx-decaf-component-renderer\n [tag]=\"item.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]='{\n item: child,\n mapper: mapper,\n route: route\n }'>\n </ngx-decaf-component-renderer>\n }\n } @else {\n <ng-content></ng-content>\n }\n </ion-list>\n\n @if(loadMoreData) {\n @if(pages > 0 && type === 'paginated' && !searchValue?.length) {\n <ngx-decaf-pagination\n [totalPages]=\"pages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n\n } @else {\n <ion-infinite-scroll\n [class]=\"searchValue?.length ? 'dcf-hidden' : ''\"\n\n [position]=\"scrollPosition\"\n [threshold]=\"scrollThreshold\"\n (ionInfinite)=\"handleRefresh($event)\">\n <ion-infinite-scroll-content [loadingSpinner]=\"loadingSpinner\" [loadingText]=\"loadingText\" />\n </ion-infinite-scroll>\n }\n }\n} @else {\n @if(refreshing) {\n @for(skl of skeletonData; track $index) {\n <ion-item>\n <ion-thumbnail slot=\"start\">\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n </ion-thumbnail>\n <ion-label>\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n </ion-label>\n </ion-item>\n }\n\n } @else {\n @if(!searchValue?.length) {\n <ngx-decaf-empty-state\n [title]=\"(locale + '.'+ empty.title) | translate\"\n [subtitle]=\"(locale + '.'+ empty.subtitle) | translate\"\n [buttonText]=\"empty.showButton ? (locale + '.'+ empty.button | translate) : ''\"\n [buttonLink]=\"empty.showButton ? empty.route : ''\"\n />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n ngClass=\"empty-search\"\n [translatable]=\"true\"\n title=\"search.title\"\n subtitle=\"search.subtitle\"\n [searchValue]=\"searchValue\"\n />\n }\n }\n}\n\n", styles: ["ion-infinite-scroll{max-height:50px}ion-infinite-scroll:not(.infinite-scroll-loading) ::ng-deep{max-height:1.5rem}ion-infinite-scroll ::ng-deep ion-spinner{--color: var(--dcf-color-primary);padding-top:1rem}@media (max-width: 768px){#end,[slot=end]{display:none!important}}\n"], dependencies: [{ kind: "component", type: IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: PaginationComponent, selector: "ngx-decaf-pagination", inputs: ["totalPages", "current"], outputs: ["clickEvent"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonThumbnail, selector: "ion-thumbnail" }, { kind: "component", type: IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: SearchbarComponent, selector: "ngx-decaf-searchbar", inputs: ["autocomplete", "autocorrect", "animated", "buttonCancelText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value", "queryKeys", "isVisible", "wrapper", "wrapperColor", "emitEventToWindow"], outputs: ["searchEvent"] }, { kind: "component", type: EmptyStateComponent, selector: "ngx-decaf-empty-state", inputs: ["title", "titleColor", "subtitle", "subtitleColor", "showIcon", "icon", "iconSize", "iconColor", "buttonLink", "buttonText", "buttonFill", "buttonColor", "buttonSize", "searchValue"] }, { kind: "component", type: FilterComponent, selector: "ngx-decaf-filter", inputs: ["indexes", "conditions", "sortBy", "disableSort"], outputs: ["filterEvent", "searchEvent"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "globals", "children", "model", "parent"], outputs: ["listenEvent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
7933
|
+
};
|
|
7934
|
+
ListComponent = __decorate([
|
|
7935
|
+
Dynamic(),
|
|
7936
|
+
__metadata("design:paramtypes", [])
|
|
7937
|
+
], ListComponent);
|
|
7938
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ListComponent, decorators: [{
|
|
7939
|
+
type: Component,
|
|
7940
|
+
args: [{ selector: 'ngx-decaf-list', standalone: true, imports: [
|
|
7941
|
+
TranslatePipe,
|
|
7942
|
+
IonRefresher,
|
|
7943
|
+
PaginationComponent,
|
|
7944
|
+
IonList,
|
|
7945
|
+
IonItem,
|
|
7946
|
+
IonThumbnail,
|
|
7947
|
+
IonSkeletonText,
|
|
7948
|
+
IonLabel,
|
|
7949
|
+
IonText,
|
|
7950
|
+
IonRefresherContent,
|
|
7951
|
+
IonInfiniteScroll,
|
|
7952
|
+
IonInfiniteScrollContent,
|
|
7953
|
+
IonThumbnail,
|
|
7954
|
+
IonSkeletonText,
|
|
7955
|
+
SearchbarComponent,
|
|
7956
|
+
EmptyStateComponent,
|
|
7957
|
+
FilterComponent,
|
|
7958
|
+
ComponentRendererComponent
|
|
7959
|
+
], template: "\n@if(showRefresher) {\n <ion-refresher slot=\"fixed\" [pullFactor]=\"1\" [pullMin]=\"100\" [pullMax]=\"200\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content />\n </ion-refresher>\n}\n\n@if(showSearchbar && data?.length) {\n @if(model && enableFilter) {\n <ngx-decaf-filter\n [model]=\"model\"\n [sortDirection]=\"sortDirection\"\n [disableSort]=\"disableSort\"\n (filterEvent)=\"handleFilter($event)\"\n (searchEvent)=\"handleSearch($event)\"\n />\n } @else {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n }\n}\n\n@if(data?.length) {\n <ion-list [id]=\"uid\" [inset]=\"inset\" [lines]=\"lines\" #component>\n @if(item?.tag) {\n @for(child of items; track trackItemFn($index, child)) {\n <ngx-decaf-component-renderer\n [tag]=\"item.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]='{\n item: child,\n mapper: mapper,\n route: route\n }'>\n </ngx-decaf-component-renderer>\n }\n } @else {\n <ng-content></ng-content>\n }\n </ion-list>\n\n @if(loadMoreData) {\n @if(pages > 0 && type === 'paginated' && !searchValue?.length) {\n <ngx-decaf-pagination\n [totalPages]=\"pages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n\n } @else {\n <ion-infinite-scroll\n [class]=\"searchValue?.length ? 'dcf-hidden' : ''\"\n\n [position]=\"scrollPosition\"\n [threshold]=\"scrollThreshold\"\n (ionInfinite)=\"handleRefresh($event)\">\n <ion-infinite-scroll-content [loadingSpinner]=\"loadingSpinner\" [loadingText]=\"loadingText\" />\n </ion-infinite-scroll>\n }\n }\n} @else {\n @if(refreshing) {\n @for(skl of skeletonData; track $index) {\n <ion-item>\n <ion-thumbnail slot=\"start\">\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n </ion-thumbnail>\n <ion-label>\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n </ion-label>\n </ion-item>\n }\n\n } @else {\n @if(!searchValue?.length) {\n <ngx-decaf-empty-state\n [title]=\"(locale + '.'+ empty.title) | translate\"\n [subtitle]=\"(locale + '.'+ empty.subtitle) | translate\"\n [buttonText]=\"empty.showButton ? (locale + '.'+ empty.button | translate) : ''\"\n [buttonLink]=\"empty.showButton ? empty.route : ''\"\n />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n ngClass=\"empty-search\"\n [translatable]=\"true\"\n title=\"search.title\"\n subtitle=\"search.subtitle\"\n [searchValue]=\"searchValue\"\n />\n }\n }\n}\n\n", styles: ["ion-infinite-scroll{max-height:50px}ion-infinite-scroll:not(.infinite-scroll-loading) ::ng-deep{max-height:1.5rem}ion-infinite-scroll ::ng-deep ion-spinner{--color: var(--dcf-color-primary);padding-top:1rem}@media (max-width: 768px){#end,[slot=end]{display:none!important}}\n"] }]
|
|
7960
|
+
}], ctorParameters: () => [], propDecorators: { type: [{
|
|
7961
|
+
type: Input
|
|
7962
|
+
}], translatable: [{
|
|
7963
|
+
type: Input
|
|
7964
|
+
}], showSearchbar: [{
|
|
7965
|
+
type: Input
|
|
7966
|
+
}], data: [{
|
|
7967
|
+
type: Input
|
|
7968
|
+
}], source: [{
|
|
7969
|
+
type: Input
|
|
7970
|
+
}], start: [{
|
|
7971
|
+
type: Input
|
|
7972
|
+
}], limit: [{
|
|
7973
|
+
type: Input
|
|
7974
|
+
}], loadMoreData: [{
|
|
7975
|
+
type: Input
|
|
7976
|
+
}], lines: [{
|
|
7977
|
+
type: Input
|
|
7978
|
+
}], inset: [{
|
|
7979
|
+
type: Input
|
|
7980
|
+
}], scrollThreshold: [{
|
|
7981
|
+
type: Input
|
|
7982
|
+
}], scrollPosition: [{
|
|
7983
|
+
type: Input
|
|
7984
|
+
}], loadingText: [{
|
|
7985
|
+
type: Input
|
|
7986
|
+
}], showRefresher: [{
|
|
7987
|
+
type: Input
|
|
7988
|
+
}], loadingSpinner: [{
|
|
7989
|
+
type: Input
|
|
7990
|
+
}], enableFilter: [{
|
|
7991
|
+
type: Input
|
|
7992
|
+
}], sortDirection: [{
|
|
7993
|
+
type: Input
|
|
7994
|
+
}], sortBy: [{
|
|
7995
|
+
type: Input
|
|
7996
|
+
}], disableSort: [{
|
|
7997
|
+
type: Input
|
|
7998
|
+
}], emptyIcon: [{
|
|
7999
|
+
type: Input
|
|
8000
|
+
}], empty: [{
|
|
8001
|
+
type: Input
|
|
8002
|
+
}], refreshEvent: [{
|
|
8003
|
+
type: Output
|
|
8004
|
+
}], clickEvent: [{
|
|
8005
|
+
type: Output
|
|
8006
|
+
}], handleClick: [{
|
|
8007
|
+
type: HostListener,
|
|
8008
|
+
args: ['window:ListItemClickEvent', ['$event']]
|
|
8009
|
+
}], handleSearch: [{
|
|
8010
|
+
type: HostListener,
|
|
8011
|
+
args: ['window:searchbarEvent', ['$event']]
|
|
8012
|
+
}], refresh: [{
|
|
8013
|
+
type: HostListener,
|
|
8014
|
+
args: ['window:BackButtonNavigationEndEvent', ['$event']]
|
|
8015
|
+
}] } });
|
|
8016
|
+
|
|
8017
|
+
/**
|
|
8018
|
+
* @description A component for displaying a list item with various customization options.
|
|
8019
|
+
* @summary The ListItemComponent is an Angular component that extends NgxBaseComponent. It provides a flexible and customizable list item interface with support for icons, buttons, and various text elements. The component also handles actions and navigation based on user interactions.
|
|
8020
|
+
*
|
|
8021
|
+
* @class
|
|
8022
|
+
* @extends NgxBaseComponent
|
|
8023
|
+
*
|
|
8024
|
+
* @param {string} [lines='none'] - Determines the line style of the item. Can be 'inset', 'inseet', or 'none'.
|
|
8025
|
+
* @param {Record<string, any>} item - The data item to be displayed in the list item.
|
|
8026
|
+
* @param {string} icon - The name of the icon to be displayed.
|
|
8027
|
+
* @param {'start' | 'end'} [iconSlot='start'] - The position of the icon within the item.
|
|
8028
|
+
* @param {StringOrBoolean} [button=true] - Determines if the item should behave as a button.
|
|
8029
|
+
* @param {string} [title] - The main title of the list item.
|
|
8030
|
+
* @param {string} [description] - A description for the list item.
|
|
8031
|
+
* @param {string} [info] - Additional information for the list item.
|
|
8032
|
+
* @param {string} [subinfo] - Sub-information for the list item.
|
|
8033
|
+
*
|
|
8034
|
+
* @example
|
|
8035
|
+
* <ngx-decaf-list-item
|
|
8036
|
+
* [item]="dataItem"
|
|
8037
|
+
* icon="star"
|
|
8038
|
+
* title="Item Title"
|
|
8039
|
+
* description="Item Description"
|
|
8040
|
+
* (clickEvent)="handleItemClick($event)">
|
|
8041
|
+
* </ngx-decaf-list-item>
|
|
8042
|
+
*
|
|
8043
|
+
* @mermaid
|
|
8044
|
+
* sequenceDiagram
|
|
8045
|
+
* participant C as Component
|
|
8046
|
+
* participant V as View
|
|
8047
|
+
* participant U as User
|
|
8048
|
+
* C->>V: Initialize component
|
|
8049
|
+
* V->>U: Display list item
|
|
8050
|
+
* U->>V: Click on item or action
|
|
8051
|
+
* V->>C: Trigger handleAction()
|
|
8052
|
+
* C->>C: Process action
|
|
8053
|
+
* C->>V: Update view or navigate
|
|
8054
|
+
*/
|
|
8055
|
+
let ListItemComponent = class ListItemComponent extends NgxBaseComponent {
|
|
8021
8056
|
/**
|
|
8022
|
-
* @description
|
|
8023
|
-
* @summary
|
|
8024
|
-
*
|
|
8025
|
-
*
|
|
8026
|
-
*
|
|
8027
|
-
* @param {boolean} force - Whether to force a refresh even if data already exists
|
|
8028
|
-
* @param {number} start - The starting index for pagination
|
|
8029
|
-
* @param {number} limit - The maximum number of items to retrieve
|
|
8030
|
-
* @returns {Promise<KeyValue[]>} A promise that resolves to the fetched data
|
|
8057
|
+
* @description Creates an instance of ListItemComponent.
|
|
8058
|
+
* @summary Initializes a new ListItemComponent by calling the parent class constructor
|
|
8059
|
+
* with the component name for logging and identification purposes. Also registers
|
|
8060
|
+
* all available Ionic icons to ensure they can be displayed in the component.
|
|
8031
8061
|
*
|
|
8032
|
-
* @memberOf
|
|
8062
|
+
* @memberOf ListItemComponent
|
|
8033
8063
|
*/
|
|
8034
|
-
|
|
8035
|
-
|
|
8036
|
-
|
|
8037
|
-
|
|
8038
|
-
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
|
|
8064
|
+
constructor() {
|
|
8065
|
+
super("ListItemComponent");
|
|
8066
|
+
/**
|
|
8067
|
+
* @description Controls the display of lines around the list item.
|
|
8068
|
+
* @summary Determines how lines are displayed around the list item borders.
|
|
8069
|
+
* 'inset' shows lines with padding, 'full' shows full-width lines, and 'none'
|
|
8070
|
+
* removes all lines. This affects the visual separation between list items.
|
|
8071
|
+
*
|
|
8072
|
+
* @type {'inset' | 'full' | 'none'}
|
|
8073
|
+
* @default 'inset'
|
|
8074
|
+
* @memberOf ListItemComponent
|
|
8075
|
+
*/
|
|
8076
|
+
this.lines = 'full';
|
|
8077
|
+
/**
|
|
8078
|
+
* @description Position of the icon within the list item.
|
|
8079
|
+
* @summary Determines whether the icon appears at the start (left in LTR languages)
|
|
8080
|
+
* or end (right in LTR languages) of the list item. This affects the overall
|
|
8081
|
+
* layout and visual hierarchy of the item content.
|
|
8082
|
+
*
|
|
8083
|
+
* @type {'start' | 'end'}
|
|
8084
|
+
* @default 'start'
|
|
8085
|
+
* @memberOf ListItemComponent
|
|
8086
|
+
*/
|
|
8087
|
+
this.iconSlot = 'start';
|
|
8088
|
+
/**
|
|
8089
|
+
* @description Controls whether the list item behaves as a clickable button.
|
|
8090
|
+
* @summary When set to true, the list item will have button-like behavior including
|
|
8091
|
+
* hover effects, click handling, and appropriate accessibility attributes.
|
|
8092
|
+
* When false, the item is displayed as static content without interactive behavior.
|
|
8093
|
+
*
|
|
8094
|
+
* @type {StringOrBoolean}
|
|
8095
|
+
* @default true
|
|
8096
|
+
* @memberOf ListItemComponent
|
|
8097
|
+
*/
|
|
8098
|
+
this.button = true;
|
|
8099
|
+
/**
|
|
8100
|
+
* @description Event emitter for list item click interactions.
|
|
8101
|
+
* @summary Emits custom events when the list item is clicked or when actions
|
|
8102
|
+
* are performed on it. The emitted event contains information about the action,
|
|
8103
|
+
* the item data, and other relevant context for parent components to handle.
|
|
8104
|
+
*
|
|
8105
|
+
* @type {EventEmitter<ListItemCustomEvent>}
|
|
8106
|
+
* @memberOf ListItemComponent
|
|
8107
|
+
*/
|
|
8108
|
+
this.clickEvent = new EventEmitter();
|
|
8109
|
+
/**
|
|
8110
|
+
* @description Flag indicating whether slide items are currently enabled.
|
|
8111
|
+
* @summary Controls the visibility of slide actions based on screen size and
|
|
8112
|
+
* available operations. When true, users can swipe on the item to reveal
|
|
8113
|
+
* action buttons for operations like edit and delete.
|
|
8114
|
+
*
|
|
8115
|
+
* @type {boolean}
|
|
8116
|
+
* @default false
|
|
8117
|
+
* @memberOf ListItemComponent
|
|
8118
|
+
*/
|
|
8119
|
+
this.showSlideItems = false;
|
|
8120
|
+
/**
|
|
8121
|
+
* @description Flag indicating whether the action menu popover is currently open.
|
|
8122
|
+
* @summary Tracks the state of the action menu to prevent multiple instances
|
|
8123
|
+
* from being opened simultaneously and to ensure proper cleanup when actions
|
|
8124
|
+
* are performed. Used for managing the popover lifecycle.
|
|
8125
|
+
*
|
|
8126
|
+
* @type {boolean}
|
|
8127
|
+
* @default false
|
|
8128
|
+
* @memberOf ListItemComponent
|
|
8129
|
+
*/
|
|
8130
|
+
this.actionMenuOpen = false;
|
|
8131
|
+
/**
|
|
8132
|
+
* @description Angular NavController service for handling navigation.
|
|
8133
|
+
* @summary Injected service that provides methods for programmatic navigation
|
|
8134
|
+
* within the Ionic application. Used for navigating to different routes when
|
|
8135
|
+
* list item actions are performed or when the item itself is clicked.
|
|
8136
|
+
*
|
|
8137
|
+
* @private
|
|
8138
|
+
* @type {NavController}
|
|
8139
|
+
* @memberOf ListItemComponent
|
|
8140
|
+
*/
|
|
8141
|
+
this.navController = inject(NavController);
|
|
8142
|
+
addIcons(allIcons);
|
|
8060
8143
|
}
|
|
8061
8144
|
/**
|
|
8062
|
-
* @description
|
|
8063
|
-
* @summary
|
|
8064
|
-
*
|
|
8065
|
-
*
|
|
8145
|
+
* @description Initializes the component after Angular first displays the data-bound properties.
|
|
8146
|
+
* @summary Sets up the component by determining slide item visibility, processing boolean inputs,
|
|
8147
|
+
* building CSS class names based on properties, and capturing the current window width.
|
|
8148
|
+
* This method prepares the component for user interaction by ensuring all properties are
|
|
8149
|
+
* properly initialized and responsive behavior is configured.
|
|
8066
8150
|
*
|
|
8067
|
-
* @
|
|
8068
|
-
*
|
|
8069
|
-
*
|
|
8070
|
-
*
|
|
8151
|
+
* @mermaid
|
|
8152
|
+
* sequenceDiagram
|
|
8153
|
+
* participant A as Angular Lifecycle
|
|
8154
|
+
* participant L as ListItemComponent
|
|
8155
|
+
* participant W as Window
|
|
8071
8156
|
*
|
|
8072
|
-
*
|
|
8157
|
+
* A->>L: ngOnInit()
|
|
8158
|
+
* L->>L: enableSlideItems()
|
|
8159
|
+
* L->>L: Process button boolean
|
|
8160
|
+
* L->>L: Build className with flex classes
|
|
8161
|
+
* alt operations exist
|
|
8162
|
+
* L->>L: Add 'action' class
|
|
8163
|
+
* end
|
|
8164
|
+
* L->>W: getWindowWidth()
|
|
8165
|
+
* W-->>L: Return current width
|
|
8166
|
+
* L->>L: Store windowWidth
|
|
8167
|
+
*
|
|
8168
|
+
* @return {Promise<void>}
|
|
8169
|
+
* @memberOf ListItemComponent
|
|
8073
8170
|
*/
|
|
8074
|
-
async
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
if (
|
|
8079
|
-
this.
|
|
8080
|
-
|
|
8081
|
-
if (!this.data?.length || force || this.searchValue?.length || !!this.searchValue) {
|
|
8082
|
-
try {
|
|
8083
|
-
if (!this.searchValue?.length && !this.searchValue) {
|
|
8084
|
-
this.data = [];
|
|
8085
|
-
// const rawQuery = this.parseQuery(self.model as Repository<Model>, start, limit);
|
|
8086
|
-
// request = this.parseResult(await (this.model as any)?.paginate(start, limit));
|
|
8087
|
-
if (!this.paginator) {
|
|
8088
|
-
this.paginator = await repo
|
|
8089
|
-
.select()
|
|
8090
|
-
.orderBy([this.pk, this.sortDirection])
|
|
8091
|
-
.paginate(this.limit);
|
|
8092
|
-
}
|
|
8093
|
-
request = await this.parseResult(this.paginator);
|
|
8094
|
-
}
|
|
8095
|
-
else {
|
|
8096
|
-
if (!this.indexes)
|
|
8097
|
-
this.indexes = (Object.values(this.mapper) || [this.pk]);
|
|
8098
|
-
const condition = this.parseConditions(this.searchValue);
|
|
8099
|
-
request = await this.parseResult(await repo.query(condition, (this.sortBy || this.pk), this.sortDirection));
|
|
8100
|
-
data = [];
|
|
8101
|
-
}
|
|
8102
|
-
data = this.type === ListComponentsTypes.INFINITE ? [...(data).concat(request)] : [...request];
|
|
8103
|
-
}
|
|
8104
|
-
catch (error) {
|
|
8105
|
-
this.logger.error(error?.message || `Unable to find ${this.model} on registry. Return empty array from component`);
|
|
8106
|
-
}
|
|
8107
|
-
}
|
|
8108
|
-
if (data?.length) {
|
|
8109
|
-
if (this.searchValue) {
|
|
8110
|
-
this.items = [...data];
|
|
8111
|
-
if (this.items?.length <= this.limit)
|
|
8112
|
-
this.loadMoreData = false;
|
|
8113
|
-
}
|
|
8114
|
-
else {
|
|
8115
|
-
this.items = [...data];
|
|
8116
|
-
}
|
|
8117
|
-
}
|
|
8118
|
-
if (this.type === ListComponentsTypes.PAGINATED && this.paginator)
|
|
8119
|
-
this.getMoreData(this.paginator.total);
|
|
8120
|
-
return data || [];
|
|
8171
|
+
async ngOnInit() {
|
|
8172
|
+
this.showSlideItems = this.enableSlideItems();
|
|
8173
|
+
this.button = stringToBoolean(this.button);
|
|
8174
|
+
this.className = `${this.className} dcf-flex dcf-flex-middle grid-item`;
|
|
8175
|
+
if (this.operations?.length)
|
|
8176
|
+
this.className += ` action`;
|
|
8177
|
+
this.windowWidth = getWindowWidth();
|
|
8121
8178
|
}
|
|
8122
8179
|
/**
|
|
8123
|
-
* @description
|
|
8124
|
-
* @summary
|
|
8125
|
-
*
|
|
8126
|
-
*
|
|
8180
|
+
* @description Handles user interactions and actions performed on the list item.
|
|
8181
|
+
* @summary This method is the central action handler for list item interactions. It manages
|
|
8182
|
+
* event propagation, dismisses open action menus, removes focus traps, and either emits
|
|
8183
|
+
* events for parent components to handle or performs navigation based on the component's
|
|
8184
|
+
* route configuration. This method supports both event-driven and navigation-driven architectures.
|
|
8127
8185
|
*
|
|
8128
|
-
*
|
|
8129
|
-
* -
|
|
8130
|
-
*
|
|
8131
|
-
*
|
|
8186
|
+
* @param {CrudOperations} action - The type of CRUD operation being performed
|
|
8187
|
+
* @param {Event} event - The browser event that triggered the action
|
|
8188
|
+
* @param {HTMLElement} [target] - Optional target element for the event
|
|
8189
|
+
* @return {Promise<boolean|void>} A promise that resolves to navigation success or void for events
|
|
8132
8190
|
*
|
|
8133
|
-
*
|
|
8134
|
-
*
|
|
8135
|
-
*
|
|
8136
|
-
*
|
|
8137
|
-
*
|
|
8191
|
+
* @mermaid
|
|
8192
|
+
* sequenceDiagram
|
|
8193
|
+
* participant U as User
|
|
8194
|
+
* participant L as ListItemComponent
|
|
8195
|
+
* participant P as Parent Component
|
|
8196
|
+
* participant N as NavController
|
|
8197
|
+
* participant E as Event System
|
|
8138
8198
|
*
|
|
8139
|
-
*
|
|
8140
|
-
*
|
|
8141
|
-
*
|
|
8199
|
+
* U->>L: Perform action (click/swipe)
|
|
8200
|
+
* L->>L: stopImmediatePropagation()
|
|
8201
|
+
* alt actionMenuOpen
|
|
8202
|
+
* L->>L: Dismiss action menu
|
|
8203
|
+
* end
|
|
8204
|
+
* L->>L: removeFocusTrap()
|
|
8205
|
+
* alt No route configured
|
|
8206
|
+
* L->>E: windowEventEmitter()
|
|
8207
|
+
* L->>P: clickEvent.emit()
|
|
8208
|
+
* else Route configured
|
|
8209
|
+
* L->>N: redirect(action, uid)
|
|
8210
|
+
* N-->>L: Return navigation result
|
|
8211
|
+
* end
|
|
8212
|
+
*
|
|
8213
|
+
* @memberOf ListItemComponent
|
|
8142
8214
|
*/
|
|
8143
|
-
|
|
8144
|
-
|
|
8145
|
-
if (
|
|
8146
|
-
|
|
8147
|
-
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
}
|
|
8154
|
-
else {
|
|
8155
|
-
orCondition = Condition.attribute(index).regexp(value);
|
|
8156
|
-
}
|
|
8157
|
-
_condition = _condition.or(orCondition);
|
|
8158
|
-
}
|
|
8159
|
-
}
|
|
8160
|
-
else {
|
|
8161
|
-
const { query, sort } = value;
|
|
8162
|
-
_condition = Condition.attribute(this.pk).dif('null');
|
|
8163
|
-
if (query?.length)
|
|
8164
|
-
_condition = undefined;
|
|
8165
|
-
(query || []).forEach((item) => {
|
|
8166
|
-
const { value, condition, index } = item;
|
|
8167
|
-
let val = value;
|
|
8168
|
-
if (index === this.pk || !isNaN(val))
|
|
8169
|
-
val = Number(val);
|
|
8170
|
-
let orCondition;
|
|
8171
|
-
switch (condition) {
|
|
8172
|
-
case "Equal":
|
|
8173
|
-
orCondition = Condition.attribute(index).eq(val);
|
|
8174
|
-
break;
|
|
8175
|
-
case "Not Equal":
|
|
8176
|
-
orCondition = Condition.attribute(index).dif(val);
|
|
8177
|
-
break;
|
|
8178
|
-
case "Not Contains":
|
|
8179
|
-
orCondition = !Condition.attribute(index).regexp(new RegExp(`^(?!.*${val}).*$`));
|
|
8180
|
-
break;
|
|
8181
|
-
case "Contains":
|
|
8182
|
-
orCondition = Condition.attribute(index).regexp(val);
|
|
8183
|
-
break;
|
|
8184
|
-
case "Greater Than":
|
|
8185
|
-
orCondition = Condition.attribute(index).gte(val);
|
|
8186
|
-
break;
|
|
8187
|
-
case "Less Than":
|
|
8188
|
-
orCondition = Condition.attribute(index).lte(val);
|
|
8189
|
-
break;
|
|
8190
|
-
}
|
|
8191
|
-
_condition = (!_condition ?
|
|
8192
|
-
orCondition : _condition.and(orCondition));
|
|
8193
|
-
});
|
|
8194
|
-
this.sortBy = sort?.value || this.pk;
|
|
8195
|
-
this.sortDirection = sort?.direction || this.sortDirection;
|
|
8215
|
+
async handleAction(action, event, target) {
|
|
8216
|
+
event.stopImmediatePropagation();
|
|
8217
|
+
if (this.actionMenuOpen)
|
|
8218
|
+
await this.actionMenuComponent.dismiss();
|
|
8219
|
+
// forcing trap focus
|
|
8220
|
+
removeFocusTrap();
|
|
8221
|
+
if (!this.route) {
|
|
8222
|
+
const event = { target: target, action, pk: this.pk, data: this.uid, name: EventConstants.CLICK, component: this.componentName };
|
|
8223
|
+
windowEventEmitter(`ListItem${EventConstants.CLICK}`, event);
|
|
8224
|
+
return this.clickEvent.emit(event);
|
|
8196
8225
|
}
|
|
8197
|
-
return
|
|
8226
|
+
return await this.redirect(action, (typeof this.uid === 'number' ? `${this.uid}` : this.uid));
|
|
8198
8227
|
}
|
|
8199
8228
|
/**
|
|
8200
|
-
* @description
|
|
8201
|
-
* @summary
|
|
8202
|
-
*
|
|
8203
|
-
*
|
|
8229
|
+
* @description Responsive handler that enables or disables slide items based on screen size and operations.
|
|
8230
|
+
* @summary This method is automatically called when the window is resized and also during component
|
|
8231
|
+
* initialization. It determines whether slide actions should be available based on the current
|
|
8232
|
+
* window width and the presence of UPDATE or DELETE operations. Slide items are typically hidden
|
|
8233
|
+
* on larger screens where there's space for dedicated action buttons.
|
|
8204
8234
|
*
|
|
8205
|
-
* @
|
|
8206
|
-
* @param {KeyValue[] | Paginator} result - The raw query result
|
|
8207
|
-
* @returns {KeyValue[]} The processed array of items
|
|
8235
|
+
* @return {boolean} True if slide items should be shown, false otherwise
|
|
8208
8236
|
*
|
|
8209
|
-
* @
|
|
8237
|
+
* @mermaid
|
|
8238
|
+
* sequenceDiagram
|
|
8239
|
+
* participant W as Window
|
|
8240
|
+
* participant L as ListItemComponent
|
|
8241
|
+
* participant U as UI
|
|
8242
|
+
*
|
|
8243
|
+
* W->>L: resize event
|
|
8244
|
+
* L->>W: getWindowWidth()
|
|
8245
|
+
* W-->>L: Return current width
|
|
8246
|
+
* L->>L: Store windowWidth
|
|
8247
|
+
* alt No operations OR width > 639px
|
|
8248
|
+
* L->>U: showSlideItems = false
|
|
8249
|
+
* else Operations include UPDATE/DELETE
|
|
8250
|
+
* L->>U: showSlideItems = true
|
|
8251
|
+
* end
|
|
8252
|
+
* L-->>U: Return showSlideItems value
|
|
8253
|
+
*
|
|
8254
|
+
* @memberOf ListItemComponent
|
|
8210
8255
|
*/
|
|
8211
|
-
|
|
8212
|
-
|
|
8213
|
-
|
|
8214
|
-
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
this.getMoreData(paginator.total);
|
|
8218
|
-
}
|
|
8219
|
-
catch (error) {
|
|
8220
|
-
this.logger.info(error?.message || 'Unable to get page from paginator. Return empty array from component');
|
|
8221
|
-
result = [];
|
|
8222
|
-
}
|
|
8223
|
-
}
|
|
8224
|
-
else {
|
|
8225
|
-
this.getMoreData(result?.length || 0);
|
|
8226
|
-
}
|
|
8227
|
-
return (Object.keys(this.mapper || {}).length) ?
|
|
8228
|
-
this.mapResults(result) : result;
|
|
8256
|
+
enableSlideItems() {
|
|
8257
|
+
this.windowWidth = getWindowWidth();
|
|
8258
|
+
if (!this.operations?.length || this.windowWidth > 639)
|
|
8259
|
+
return this.showSlideItems = false;
|
|
8260
|
+
this.showSlideItems = this.operations.includes(OperationKeys.UPDATE) || this.operations.includes(OperationKeys.DELETE);
|
|
8261
|
+
return this.showSlideItems;
|
|
8229
8262
|
}
|
|
8230
8263
|
/**
|
|
8231
|
-
* @description
|
|
8232
|
-
* @summary
|
|
8233
|
-
*
|
|
8234
|
-
*
|
|
8264
|
+
* @description Animates and removes an element from the DOM.
|
|
8265
|
+
* @summary This method applies CSS animation classes to create a smooth fade-out effect
|
|
8266
|
+
* before removing the element from the DOM. The animation enhances user experience by
|
|
8267
|
+
* providing visual feedback when items are deleted or removed from lists. The timing
|
|
8268
|
+
* is coordinated with the CSS animation duration to ensure the element is removed
|
|
8269
|
+
* after the animation completes.
|
|
8235
8270
|
*
|
|
8236
|
-
* @param {
|
|
8237
|
-
* @
|
|
8271
|
+
* @param {HTMLElement} element - The DOM element to animate and remove
|
|
8272
|
+
* @return {void}
|
|
8238
8273
|
*
|
|
8239
|
-
* @
|
|
8274
|
+
* @mermaid
|
|
8275
|
+
* sequenceDiagram
|
|
8276
|
+
* participant L as ListItemComponent
|
|
8277
|
+
* participant E as HTMLElement
|
|
8278
|
+
* participant D as DOM
|
|
8279
|
+
*
|
|
8280
|
+
* L->>E: Add animation classes
|
|
8281
|
+
* Note over E: uk-animation-fade, uk-animation-medium, uk-animation-reverse
|
|
8282
|
+
* E->>E: Start fade animation
|
|
8283
|
+
* L->>L: setTimeout(600ms)
|
|
8284
|
+
* Note over L: Wait for animation to complete
|
|
8285
|
+
* L->>D: element.remove()
|
|
8286
|
+
* D->>D: Remove element from DOM
|
|
8287
|
+
*
|
|
8288
|
+
* @memberOf ListItemComponent
|
|
8240
8289
|
*/
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
length = length * this.limit;
|
|
8245
|
-
if (length <= this.limit) {
|
|
8246
|
-
this.loadMoreData = false;
|
|
8247
|
-
}
|
|
8248
|
-
else {
|
|
8249
|
-
this.pages = Math.floor(length / this.limit);
|
|
8250
|
-
if ((this.pages * this.limit) < length)
|
|
8251
|
-
this.pages += 1;
|
|
8252
|
-
if (this.pages === 1)
|
|
8253
|
-
this.loadMoreData = false;
|
|
8254
|
-
}
|
|
8255
|
-
}
|
|
8256
|
-
else {
|
|
8257
|
-
this.pages = length;
|
|
8258
|
-
if (this.pages === 1)
|
|
8259
|
-
this.loadMoreData = false;
|
|
8260
|
-
}
|
|
8290
|
+
removeElement(element) {
|
|
8291
|
+
element.classList.add('uk-animation-fade', 'uk-animation-medium', 'uk-animation-reverse');
|
|
8292
|
+
setTimeout(() => { element.remove(); }, 600);
|
|
8261
8293
|
}
|
|
8262
8294
|
/**
|
|
8263
|
-
* @description
|
|
8264
|
-
* @summary
|
|
8265
|
-
*
|
|
8266
|
-
*
|
|
8295
|
+
* @description Navigates to a new route based on the specified action and item ID.
|
|
8296
|
+
* @summary This method constructs a navigation URL using the component's route configuration,
|
|
8297
|
+
* the specified action, and an item identifier. It uses Ionic's NavController to perform
|
|
8298
|
+
* forward navigation with appropriate animations. This method is typically used for
|
|
8299
|
+
* CRUD operations where each action (create, read, update, delete) has its own route.
|
|
8267
8300
|
*
|
|
8268
|
-
* @
|
|
8269
|
-
* @param {
|
|
8270
|
-
* @
|
|
8271
|
-
* @param {KeyValue} [props] - Additional properties to include
|
|
8272
|
-
* @returns {KeyValue} The mapped item
|
|
8301
|
+
* @param {string} action - The action to be performed (e.g., 'edit', 'view', 'delete')
|
|
8302
|
+
* @param {string} [id] - The unique identifier of the item to be acted upon
|
|
8303
|
+
* @return {Promise<boolean>} A promise that resolves to true if navigation was successful
|
|
8273
8304
|
*
|
|
8274
|
-
* @
|
|
8305
|
+
* @mermaid
|
|
8306
|
+
* sequenceDiagram
|
|
8307
|
+
* participant L as ListItemComponent
|
|
8308
|
+
* participant N as NavController
|
|
8309
|
+
* participant R as Router
|
|
8310
|
+
*
|
|
8311
|
+
* L->>L: redirect(action, id)
|
|
8312
|
+
* L->>L: Construct URL: /{route}/{action}/{id}
|
|
8313
|
+
* L->>N: navigateForward(url)
|
|
8314
|
+
* N->>R: Navigate to constructed URL
|
|
8315
|
+
* R-->>N: Return navigation result
|
|
8316
|
+
* N-->>L: Return boolean success
|
|
8317
|
+
*
|
|
8318
|
+
* @memberOf ListItemComponent
|
|
8275
8319
|
*/
|
|
8276
|
-
|
|
8277
|
-
return
|
|
8278
|
-
const arrayValue = value.split('.');
|
|
8279
|
-
if (!value) {
|
|
8280
|
-
accum[key] = value;
|
|
8281
|
-
}
|
|
8282
|
-
else {
|
|
8283
|
-
if (arrayValue.length === 1) {
|
|
8284
|
-
value = item?.[value] ? item[value] : value !== key ? value : "";
|
|
8285
|
-
if (isValidDate(value))
|
|
8286
|
-
value = `${formatDate(value)}`;
|
|
8287
|
-
accum[key] = value;
|
|
8288
|
-
}
|
|
8289
|
-
else {
|
|
8290
|
-
let val;
|
|
8291
|
-
for (const _value of arrayValue)
|
|
8292
|
-
val = !val
|
|
8293
|
-
? item[_value]
|
|
8294
|
-
: (typeof val === 'string' ? JSON.parse(val) : val)[_value];
|
|
8295
|
-
if (isValidDate(new Date(val)))
|
|
8296
|
-
val = `${formatDate(val)}`;
|
|
8297
|
-
accum[key] = val === null || val === undefined ? value : val;
|
|
8298
|
-
}
|
|
8299
|
-
}
|
|
8300
|
-
return Object.assign({}, props || {}, accum);
|
|
8301
|
-
}, {});
|
|
8320
|
+
async redirect(action, id) {
|
|
8321
|
+
return await this.navController.navigateForward(`/${this.route}/${action}/${id || this.uid}`);
|
|
8302
8322
|
}
|
|
8303
8323
|
/**
|
|
8304
|
-
* @description
|
|
8305
|
-
* @summary
|
|
8306
|
-
*
|
|
8307
|
-
*
|
|
8324
|
+
* @description Presents the actions menu popover for the list item.
|
|
8325
|
+
* @summary This method handles the display of a contextual action menu when triggered by user
|
|
8326
|
+
* interaction (typically a long press or right-click). It stops event propagation to prevent
|
|
8327
|
+
* unwanted side effects, removes any existing focus traps for accessibility, configures the
|
|
8328
|
+
* popover with the triggering event, and opens the action menu. The menu typically contains
|
|
8329
|
+
* available CRUD operations for the item.
|
|
8308
8330
|
*
|
|
8309
|
-
* @param {
|
|
8310
|
-
* @
|
|
8331
|
+
* @param {Event} event - The event that triggered the action menu request
|
|
8332
|
+
* @return {void}
|
|
8311
8333
|
*
|
|
8312
|
-
* @
|
|
8334
|
+
* @mermaid
|
|
8335
|
+
* sequenceDiagram
|
|
8336
|
+
* participant U as User
|
|
8337
|
+
* participant L as ListItemComponent
|
|
8338
|
+
* participant P as Popover
|
|
8339
|
+
* participant A as Accessibility
|
|
8340
|
+
*
|
|
8341
|
+
* U->>L: Trigger action menu (long press/right-click)
|
|
8342
|
+
* L->>L: stopImmediatePropagation()
|
|
8343
|
+
* L->>A: removeFocusTrap()
|
|
8344
|
+
* L->>P: Set event reference
|
|
8345
|
+
* L->>L: actionMenuOpen = true
|
|
8346
|
+
* L->>P: Display popover with actions
|
|
8347
|
+
*
|
|
8348
|
+
* @memberOf ListItemComponent
|
|
8313
8349
|
*/
|
|
8314
|
-
|
|
8315
|
-
|
|
8316
|
-
|
|
8317
|
-
|
|
8318
|
-
this.
|
|
8319
|
-
|
|
8320
|
-
operations: this.operations,
|
|
8321
|
-
route: this.route,
|
|
8322
|
-
...Object.keys(this.item).reduce((acc, key) => {
|
|
8323
|
-
acc[key] = this.item[key];
|
|
8324
|
-
return acc;
|
|
8325
|
-
}, {}),
|
|
8326
|
-
// ... (!this.item.render ? {} : Object.keys(this.item).reduce((acc: KeyValue, key: string) => {
|
|
8327
|
-
// acc[key] = this.item[key as keyof IListItemProp];
|
|
8328
|
-
// return acc;
|
|
8329
|
-
// }, {}))
|
|
8330
|
-
});
|
|
8331
|
-
return data.reduce((accum, curr) => {
|
|
8332
|
-
accum.push({ ...this.itemMapper(curr, this.mapper, props), ...{ pk: this.pk } });
|
|
8333
|
-
return accum;
|
|
8334
|
-
}, []);
|
|
8350
|
+
presentActionsMenu(event) {
|
|
8351
|
+
event.stopImmediatePropagation();
|
|
8352
|
+
// forcing trap focus
|
|
8353
|
+
removeFocusTrap();
|
|
8354
|
+
this.actionMenuComponent.event = event;
|
|
8355
|
+
this.actionMenuOpen = true;
|
|
8335
8356
|
}
|
|
8336
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8337
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ListComponent, isStandalone: true, selector: "ngx-decaf-list", inputs: { type: "type", translatable: "translatable", showSearchbar: "showSearchbar", data: "data", source: "source", start: "start", limit: "limit", loadMoreData: "loadMoreData", lines: "lines", inset: "inset", scrollThreshold: "scrollThreshold", scrollPosition: "scrollPosition", loadingText: "loadingText", showRefresher: "showRefresher", loadingSpinner: "loadingSpinner", enableFilter: "enableFilter", sortDirection: "sortDirection", sortBy: "sortBy", disableSort: "disableSort", emptyIcon: "emptyIcon", empty: "empty" }, outputs: { refreshEvent: "refreshEvent", clickEvent: "clickEvent" }, host: { listeners: { "window:ListItemClickEvent": "handleClick($event)", "window:searchbarEvent": "handleSearch($event)", "window:BackButtonNavigationEndEvent": "refresh($event)" } }, usesInheritance: true, ngImport: i0, template: "\n@if(showRefresher) {\n <ion-refresher slot=\"fixed\" [pullFactor]=\"1\" [pullMin]=\"100\" [pullMax]=\"200\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content />\n </ion-refresher>\n}\n\n@if(showSearchbar && data?.length) {\n @if(model && enableFilter) {\n <ngx-decaf-filter\n [model]=\"model\"\n [sortDirection]=\"sortDirection\"\n [disableSort]=\"disableSort\"\n (filterEvent)=\"handleFilter($event)\"\n (searchEvent)=\"handleSearch($event)\"\n />\n } @else {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n }\n}\n\n@if(data?.length) {\n <ion-list [id]=\"uid\" [inset]=\"inset\" [lines]=\"lines\" #component>\n @if(item?.tag) {\n @for(child of items; track trackItemFn($index, child)) {\n <ngx-decaf-component-renderer\n [tag]=\"item.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]='{\n item: child,\n mapper: mapper,\n route: route\n }'>\n </ngx-decaf-component-renderer>\n }\n } @else {\n <ng-content></ng-content>\n }\n </ion-list>\n\n @if(loadMoreData) {\n @if(pages > 0 && type === 'paginated' && !searchValue?.length) {\n <ngx-decaf-pagination\n [totalPages]=\"pages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n\n } @else {\n <ion-infinite-scroll\n [class]=\"searchValue?.length ? 'dcf-hidden' : ''\"\n\n [position]=\"scrollPosition\"\n [threshold]=\"scrollThreshold\"\n (ionInfinite)=\"handleRefresh($event)\">\n <ion-infinite-scroll-content [loadingSpinner]=\"loadingSpinner\" [loadingText]=\"loadingText\" />\n </ion-infinite-scroll>\n }\n }\n} @else {\n @if(refreshing) {\n @for(skl of skeletonData; track $index) {\n <ion-item>\n <ion-thumbnail slot=\"start\">\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n </ion-thumbnail>\n <ion-label>\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n </ion-label>\n </ion-item>\n }\n\n } @else {\n @if(!searchValue?.length) {\n <ngx-decaf-empty-state\n [title]=\"(locale + '.'+ empty.title) | translate\"\n [subtitle]=\"(locale + '.'+ empty.subtitle) | translate\"\n [buttonText]=\"empty.showButton ? (locale + '.'+ empty.button | translate) : ''\"\n [buttonLink]=\"empty.showButton ? empty.route : ''\"\n />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n ngClass=\"empty-search\"\n [translatable]=\"true\"\n title=\"search.title\"\n subtitle=\"search.subtitle\"\n [searchValue]=\"searchValue\"\n />\n }\n }\n}\n\n", styles: ["ion-infinite-scroll{max-height:50px}ion-infinite-scroll:not(.infinite-scroll-loading) ::ng-deep{max-height:1.5rem}ion-infinite-scroll ::ng-deep ion-spinner{--color: var(--dcf-color-primary);padding-top:1rem}@media (max-width: 768px){#end,[slot=end]{display:none!important}}\n"], dependencies: [{ kind: "pipe", type: TranslatePipe, name: "translate" }, { kind: "component", type: IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: PaginationComponent, selector: "ngx-decaf-pagination", inputs: ["totalPages", "current"], outputs: ["clickEvent"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonThumbnail, selector: "ion-thumbnail" }, { kind: "component", type: IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: SearchbarComponent, selector: "ngx-decaf-searchbar", inputs: ["autocomplete", "autocorrect", "animated", "buttonCancelText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value", "queryKeys", "isVisible", "wrapper", "wrapperColor", "emitEventToWindow"], outputs: ["searchEvent"] }, { kind: "component", type: EmptyStateComponent, selector: "ngx-decaf-empty-state", inputs: ["title", "titleColor", "subtitle", "subtitleColor", "showIcon", "icon", "iconSize", "iconColor", "buttonLink", "buttonText", "buttonFill", "buttonColor", "buttonSize", "searchValue"] }, { kind: "component", type: FilterComponent, selector: "ngx-decaf-filter", inputs: ["indexes", "conditions", "sortBy", "disableSort"], outputs: ["filterEvent", "searchEvent"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "globals", "children", "model", "parent"], outputs: ["listenEvent"] }] }); }
|
|
8357
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8358
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: ListItemComponent, isStandalone: true, selector: "ngx-decaf-list-item", inputs: { lines: "lines", item: "item", icon: "icon", iconSlot: "iconSlot", button: "button", title: "title", description: "description", info: "info", subinfo: "subinfo" }, outputs: { clickEvent: "clickEvent" }, host: { listeners: { "window:resize": "enableSlideItems($event)" } }, viewQueries: [{ propertyName: "actionMenuComponent", first: true, predicate: ["actionMenuComponent"], descendants: true }], usesInheritance: true, ngImport: i0, template: "\n@if(title || description) {\n <ion-item-sliding #component>\n <ion-item\n [id]=\"uid\"\n [lines]=\"lines\"\n [button]=\"button\"\n [class]=\"className\"\n (click)=\"operations?.includes('read') ? handleAction('read', $event, component) : ''\n \">\n @if(icon && lines !== 'inset') {\n <div class=\"dcf-icon\" [slot]=\"iconSlot\">\n <ion-avatar>\n <ion-icon aria-hidden=\"true\" name=\"reader-outline\" size=\"default\"></ion-icon>\n </ion-avatar>\n </div>\n }\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-flex dcf-flex-middle dcf-grid-collapse\" dcf-grid>\n @if(icon && lines === 'inset') {\n <div class=\"dcf-icon dcf-grid-icon\">\n <ion-avatar>\n <ion-icon aria-hidden=\"true\" name=\"reader-outline\" size=\"default\"></ion-icon>\n </ion-avatar>\n </div>\n }\n <div class=\"dcf-width-expand@s dcf-width-1-1 dcf-label\">\n <ion-label class=\"dcf-item-title\" [innerHTML]=\"uid + ' - ' + title\" ></ion-label>\n @if(description) {\n <div class=\"dcf-description\" [innerHTML]=\"description\"></div>\n }\n </div>\n @if(info || subinfo) {\n <div class=\"dcf-width-auto@s dcf-width-expand dcf-info dcf-flex dcf-flex-right@s\">\n <div>\n @if(info) {\n <span [innerHTML]=\"info\"></span>\n }\n @if(subinfo) {\n <div class=\"dcf-subinfo dcf-text-truncate\" [innerHTML]=\"subinfo\" ></div>\n }\n </div>\n </div>\n }\n\n <div class=\"dcf-width-auto dcf-flex dcf-flex-middle dcf-flex-right\">\n @if((operations.includes('delete') || operations.includes('update')) && uid) {\n <div class=\"dcf-visible@m\" id=\"dcf-actions\">\n <ion-button class=\"dcf-hidden@m\" shape=\"round\" fill=\"clear\" color=\"primary\" (click)=\"presentActionsMenu($event)\">\n <ion-icon slot=\"icon-only\" aria-hidden=\"true\" name=\"ellipsis-vertical-outline\"></ion-icon>\n </ion-button>\n <ion-popover\n #actionMenuComponent\n side=\"bottom\"\n alignment=\"left\"\n\n [isOpen]=\"actionMenuOpen\"\n (didDismiss)=\"actionMenuOpen = false\">\n <ng-template>\n <ion-content class=\"ion-padding\">\n <ion-list lines=\"none\">\n <ion-list-header>\n <h4 class=\"dcf-text-capitalize\" [innerHTML]=\"'actions' | translate\"></h4>\n </ion-list-header>\n @for (operation of ['update', 'delete']; track operation) {\n @if(operations.includes(operation)) {\n <ion-item [button]=\"true\" (click)=\"handleAction(operation, $event, component)\">\n <ion-avatar class=\"dcf-flex dcf-flex-middle\" aria-hidden=\"true\" slot=\"start\">\n @if(operation === 'update') {\n <ion-icon color=\"primary\" aria-hidden=\"true\" name=\"create-outline\"></ion-icon>\n } @else {\n <ion-icon color=\"danger\" aria-hidden=\"true\" name=\"trash\"></ion-icon>\n }\n </ion-avatar>\n <ion-label class=\"dcf-text-capitalize\">{{ operation | translate }}</ion-label>\n </ion-item>\n }\n }\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n </div>\n }\n <!-- @if(operations?.length && uid) {\n <div class=\"dcf-visible@m\" id=\"dcf-actions\">\n @if(operations?.includes('update')) {\n <ion-button fill=\"clear\" size=\"small\" color=\"primary\" (click)=\"handleAction('update', component)\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"create-outline\"></ion-icon>\n </ion-button>\n }\n @if(operations?.includes('delete')) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleAction('delete', component)\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n }\n </div>\n } -->\n @if(windowWidth > 639) {\n <div id=\"end\">\n <ng-content select=\"[slot='end']\"></ng-content>\n </div>\n }\n </div>\n </div>\n </div>\n </ion-item>\n @if(showSlideItems && uid) {\n <ion-item-options side=\"end\" (ionSwipe)=\"operations.length === 1 ? handleAction(operations[0], $event, component) : ''\">\n @if(operations?.includes('update')) {\n <ion-item-option class=\"dcf-update\" (click)=\"handleAction('update', $event, component)\" [expandable]=\"operations.length === 1\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"create-outline\"></ion-icon>\n </ion-item-option>\n }\n @if(operations?.includes('delete')) {\n <ion-item-option class=\"dcf- delete\" (click)=\"handleAction('delete', $event, component)\" [expandable]=\"operations.length === 1\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-item-option>\n }\n </ion-item-options>\n }\n </ion-item-sliding>\n}\n", styles: ["@media (prefers-color-scheme: light){ion-item{--background-hover-opacity: .1;--background-focused-opacity: .1;--border-color: var(--dcf-color-gray-2)}ion-item .dcf-info{color:var(--dcf-color-gray-6)}ion-item .dcf-item-title{color:var(--dcf-color-gray-8)}ion-item .dcf-description{color:var(--dcf-color-gray-6)}ion-button{color:var(--dcf-color-gray-7);--background: var(--dcf-color-gray-1) !important}ion-avatar{color:var(--dcf-color-gray-7);background:var(--dcf-color-gray-1)!important}ion-item-option:not(.dcf-delete),ion-item-option:not(.dcf-update){background:rgba(var(--dcf-color-dark-rgb),.25)!important}ion-item-option:not(.dcf-delete) .dcf-ti,ion-item-option:not(.dcf-delete) ion-icon,ion-item-option:not(.dcf-update) .dcf-ti,ion-item-option:not(.dcf-update) ion-icon{color:var(--dcf-color-gray-7)!important}ion-item-option.dcf-delete{background:rgba(var(--dcf-color-danger-rgb),.05)!important}ion-item-option.dcf-delete .dcf-ti,ion-item-option.dcf-delete *,ion-item-option.dcf-delete ion-icon{color:var(--dcf-color-danger)!important}ion-item-option.dcf-update{background:rgba(var(--dcf-color-primary-rgb),.05)!important}ion-item-option.dcf-update .dcf-ti,ion-item-option.dcf-update ion-icon{color:var(--dcf-color-primary)!important}}@media (prefers-color-scheme: dark){ion-item{--background-hover-opacity: .25;--background-focused-opacity: .25;--border-color: var(--dcf-color-gray-6)}ion-item .dcf-description{color:var(--dcf-color-gray-4)}ion-button{color:var(--dcf-color-gray-1)!important;--background: var(--dcf-color-gray-7) !important}ion-avatar{color:var(--dcf-color-gray-1)!important;background:var(--dcf-background-color)!important}ion-item-option:not(.dcf-delete),ion-item-option:not(.dcf-update){background:rgba(var(--dcf-color-dark-rgb),1)!important}ion-item-option:not(.dcf-delete) .dcf-ti,ion-item-option:not(.dcf-delete) ion-icon,ion-item-option:not(.dcf-update) .dcf-ti,ion-item-option:not(.dcf-update) ion-icon{color:var(--dcf-color-gray-2)!important}ion-item-option.dcf-delete{background:rgba(var(--dcf-color-danger-rgb),.05)!important}ion-item-option.dcf-delete .dcf-ti,ion-item-option.dcf-delete *,ion-item-option.dcf-delete ion-icon{color:var(--dcf-color-danger)!important}ion-item-option.dcf-update{background:rgba(var(--dcf-color-primary-rgb),.05)!important}ion-item-option.dcf-update .dcf-ti,ion-item-option.dcf-update ion-icon{color:var(--dcf-color-gray-2)!important}}ion-item-sliding{box-sizing:border-box}ion-item-sliding[class*=active-slide]{border-color:var(--dcf-color-gray-3)}ion-item-sliding ion-item-option{color:var(--dcf-color-gray-5);box-shadow:inset 0 0 5px rgba(var(--dcf-color-dark-rgb),.15)!important;background:var(--dcf-color-gray-3)}ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--background-hover: var(--dcf-color-gray-8);--background-focused: var(--dcf-color-gray-8)}ion-item.item-lines-full{--padding-top: .5rem;--padding-bottom: .5rem;--padding-start: .25rem;-padding-end:.25rem;padding:0 .65rem}ion-item.item-lines-inset{--padding-top: 0rem !important;--padding-bottom: 0rem !important;--inner-padding-top: .5rem !important;--inner-padding-bottom: .65rem !important}ion-item .dcf-info{min-width:10vw;background:transparent!important}ion-item .dcf-grid{padding:0!important;margin:0!important;min-width:100%!important}ion-item .dcf-item-title{font-style:normal;font-weight:700}ion-item .dcf-description{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-style:normal;font-weight:400;font-size:.925rem}ion-item::part(native){min-width:100%}ion-item [slot=start]{margin-right:.5rem!important}ion-item [slot=end]{margin-left:.5rem!important}ion-item .dcf-info{font-size:.9rem}ion-item .dcf-info .dcf-subinfo.dcf-line{margin-left:.5rem}@media (min-width: var(--dcf-width-sm)){ion-item .dcf-info .dcf-subinfo.dcf-line{display:block;margin-left:0}}ion-item #dcf-actions{padding:5px}@media (max-width: var(--dcf-width-m)){ion-item #dcf-actions{display:none;pointer-events:none!important;cursor:text!important}ion-item #dcf-actions *{display:none;pointer-events:none!important;cursor:text!important}}ion-item #dcf-actions ion-button{--padding-start: 1rem;--padding-end: .75rem;--padding-top: .85rem !important;--padding-bottom: .85rem !important;color:#ccc;margin-right:.5rem!important;--background: var(--dcf-color-gray-2) !important}ion-item #dcf-actions ion-button ion-icon{position:relative;left:-1px}@media (max-width: var(--dcf-width-m)){ion-item #dcf-end,ion-item [slot=end]{display:none!important}}ion-item #dcf-end{padding-top:5px;display:flex;align-items:flex-end}ion-item .dcf-icon{display:flex;justify-content:center;align-items:center;text-align:center;margin-right:.5rem!important}ion-item .dcf-icon.dcf-grid-icon{min-width:50px;text-align:left;display:flex;justify-content:flex-start}@media (max-width: var(--dcf-width-s)){ion-item .dcf-icon{align-items:flex-start!important}}ion-item .dcf-icon ion-button ion-icon{font-size:20px}ion-item .dcf-icon ion-avatar{width:48px;height:48px;display:flex;justify-content:center;align-items:center;text-align:center}ion-item .dcf-icon ion-avatar ion-icon{font-size:20px}ion-item .dcf-icon ion-avatar .dcf-icon-large{transform:translateY(5px)}\n"], dependencies: [{ kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonListHeader, selector: "ion-list-header", inputs: ["color", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonItemSliding, selector: "ion-item-sliding", inputs: ["disabled"] }, { kind: "component", type: IonItemOptions, selector: "ion-item-options", inputs: ["side"] }, { kind: "component", type: IonItemOption, selector: "ion-item-option", inputs: ["color", "disabled", "download", "expandable", "href", "mode", "rel", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonContent, selector: "ion-content", inputs: ["color", "fixedSlotPlacement", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: IonPopover, selector: "ion-popover" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
8338
8359
|
};
|
|
8339
|
-
|
|
8360
|
+
ListItemComponent = __decorate([
|
|
8340
8361
|
Dynamic(),
|
|
8341
8362
|
__metadata("design:paramtypes", [])
|
|
8342
|
-
],
|
|
8343
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8363
|
+
], ListItemComponent);
|
|
8364
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ListItemComponent, decorators: [{
|
|
8344
8365
|
type: Component,
|
|
8345
|
-
args: [{ selector: 'ngx-decaf-list', standalone: true, imports: [
|
|
8366
|
+
args: [{ selector: 'ngx-decaf-list-item', standalone: true, imports: [
|
|
8346
8367
|
TranslatePipe,
|
|
8347
|
-
IonRefresher,
|
|
8348
|
-
IonLoading,
|
|
8349
|
-
PaginationComponent,
|
|
8350
8368
|
IonList,
|
|
8369
|
+
IonListHeader,
|
|
8351
8370
|
IonItem,
|
|
8352
|
-
|
|
8353
|
-
|
|
8371
|
+
IonItemSliding,
|
|
8372
|
+
IonItemOptions,
|
|
8373
|
+
IonItemOption,
|
|
8374
|
+
IonIcon,
|
|
8354
8375
|
IonLabel,
|
|
8355
|
-
|
|
8356
|
-
|
|
8357
|
-
|
|
8358
|
-
IonInfiniteScrollContent,
|
|
8359
|
-
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
EmptyStateComponent,
|
|
8363
|
-
ListItemComponent,
|
|
8364
|
-
FilterComponent,
|
|
8365
|
-
ComponentRendererComponent
|
|
8366
|
-
], template: "\n@if(showRefresher) {\n <ion-refresher slot=\"fixed\" [pullFactor]=\"1\" [pullMin]=\"100\" [pullMax]=\"200\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content />\n </ion-refresher>\n}\n\n@if(showSearchbar && data?.length) {\n @if(model && enableFilter) {\n <ngx-decaf-filter\n [model]=\"model\"\n [sortDirection]=\"sortDirection\"\n [disableSort]=\"disableSort\"\n (filterEvent)=\"handleFilter($event)\"\n (searchEvent)=\"handleSearch($event)\"\n />\n } @else {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n }\n}\n\n@if(data?.length) {\n <ion-list [id]=\"uid\" [inset]=\"inset\" [lines]=\"lines\" #component>\n @if(item?.tag) {\n @for(child of items; track trackItemFn($index, child)) {\n <ngx-decaf-component-renderer\n [tag]=\"item.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]='{\n item: child,\n mapper: mapper,\n route: route\n }'>\n </ngx-decaf-component-renderer>\n }\n } @else {\n <ng-content></ng-content>\n }\n </ion-list>\n\n @if(loadMoreData) {\n @if(pages > 0 && type === 'paginated' && !searchValue?.length) {\n <ngx-decaf-pagination\n [totalPages]=\"pages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n\n } @else {\n <ion-infinite-scroll\n [class]=\"searchValue?.length ? 'dcf-hidden' : ''\"\n\n [position]=\"scrollPosition\"\n [threshold]=\"scrollThreshold\"\n (ionInfinite)=\"handleRefresh($event)\">\n <ion-infinite-scroll-content [loadingSpinner]=\"loadingSpinner\" [loadingText]=\"loadingText\" />\n </ion-infinite-scroll>\n }\n }\n} @else {\n @if(refreshing) {\n @for(skl of skeletonData; track $index) {\n <ion-item>\n <ion-thumbnail slot=\"start\">\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n </ion-thumbnail>\n <ion-label>\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n </ion-label>\n </ion-item>\n }\n\n } @else {\n @if(!searchValue?.length) {\n <ngx-decaf-empty-state\n [title]=\"(locale + '.'+ empty.title) | translate\"\n [subtitle]=\"(locale + '.'+ empty.subtitle) | translate\"\n [buttonText]=\"empty.showButton ? (locale + '.'+ empty.button | translate) : ''\"\n [buttonLink]=\"empty.showButton ? empty.route : ''\"\n />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n ngClass=\"empty-search\"\n [translatable]=\"true\"\n title=\"search.title\"\n subtitle=\"search.subtitle\"\n [searchValue]=\"searchValue\"\n />\n }\n }\n}\n\n", styles: ["ion-infinite-scroll{max-height:50px}ion-infinite-scroll:not(.infinite-scroll-loading) ::ng-deep{max-height:1.5rem}ion-infinite-scroll ::ng-deep ion-spinner{--color: var(--dcf-color-primary);padding-top:1rem}@media (max-width: 768px){#end,[slot=end]{display:none!important}}\n"] }]
|
|
8367
|
-
}], ctorParameters: () => [], propDecorators: { type: [{
|
|
8368
|
-
type: Input
|
|
8369
|
-
}], translatable: [{
|
|
8370
|
-
type: Input
|
|
8371
|
-
}], showSearchbar: [{
|
|
8372
|
-
type: Input
|
|
8373
|
-
}], data: [{
|
|
8374
|
-
type: Input
|
|
8375
|
-
}], source: [{
|
|
8376
|
-
type: Input
|
|
8377
|
-
}], start: [{
|
|
8378
|
-
type: Input
|
|
8379
|
-
}], limit: [{
|
|
8380
|
-
type: Input
|
|
8381
|
-
}], loadMoreData: [{
|
|
8382
|
-
type: Input
|
|
8376
|
+
IonButton,
|
|
8377
|
+
IonContent,
|
|
8378
|
+
IonPopover
|
|
8379
|
+
], template: "\n@if(title || description) {\n <ion-item-sliding #component>\n <ion-item\n [id]=\"uid\"\n [lines]=\"lines\"\n [button]=\"button\"\n [class]=\"className\"\n (click)=\"operations?.includes('read') ? handleAction('read', $event, component) : ''\n \">\n @if(icon && lines !== 'inset') {\n <div class=\"dcf-icon\" [slot]=\"iconSlot\">\n <ion-avatar>\n <ion-icon aria-hidden=\"true\" name=\"reader-outline\" size=\"default\"></ion-icon>\n </ion-avatar>\n </div>\n }\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-flex dcf-flex-middle dcf-grid-collapse\" dcf-grid>\n @if(icon && lines === 'inset') {\n <div class=\"dcf-icon dcf-grid-icon\">\n <ion-avatar>\n <ion-icon aria-hidden=\"true\" name=\"reader-outline\" size=\"default\"></ion-icon>\n </ion-avatar>\n </div>\n }\n <div class=\"dcf-width-expand@s dcf-width-1-1 dcf-label\">\n <ion-label class=\"dcf-item-title\" [innerHTML]=\"uid + ' - ' + title\" ></ion-label>\n @if(description) {\n <div class=\"dcf-description\" [innerHTML]=\"description\"></div>\n }\n </div>\n @if(info || subinfo) {\n <div class=\"dcf-width-auto@s dcf-width-expand dcf-info dcf-flex dcf-flex-right@s\">\n <div>\n @if(info) {\n <span [innerHTML]=\"info\"></span>\n }\n @if(subinfo) {\n <div class=\"dcf-subinfo dcf-text-truncate\" [innerHTML]=\"subinfo\" ></div>\n }\n </div>\n </div>\n }\n\n <div class=\"dcf-width-auto dcf-flex dcf-flex-middle dcf-flex-right\">\n @if((operations.includes('delete') || operations.includes('update')) && uid) {\n <div class=\"dcf-visible@m\" id=\"dcf-actions\">\n <ion-button class=\"dcf-hidden@m\" shape=\"round\" fill=\"clear\" color=\"primary\" (click)=\"presentActionsMenu($event)\">\n <ion-icon slot=\"icon-only\" aria-hidden=\"true\" name=\"ellipsis-vertical-outline\"></ion-icon>\n </ion-button>\n <ion-popover\n #actionMenuComponent\n side=\"bottom\"\n alignment=\"left\"\n\n [isOpen]=\"actionMenuOpen\"\n (didDismiss)=\"actionMenuOpen = false\">\n <ng-template>\n <ion-content class=\"ion-padding\">\n <ion-list lines=\"none\">\n <ion-list-header>\n <h4 class=\"dcf-text-capitalize\" [innerHTML]=\"'actions' | translate\"></h4>\n </ion-list-header>\n @for (operation of ['update', 'delete']; track operation) {\n @if(operations.includes(operation)) {\n <ion-item [button]=\"true\" (click)=\"handleAction(operation, $event, component)\">\n <ion-avatar class=\"dcf-flex dcf-flex-middle\" aria-hidden=\"true\" slot=\"start\">\n @if(operation === 'update') {\n <ion-icon color=\"primary\" aria-hidden=\"true\" name=\"create-outline\"></ion-icon>\n } @else {\n <ion-icon color=\"danger\" aria-hidden=\"true\" name=\"trash\"></ion-icon>\n }\n </ion-avatar>\n <ion-label class=\"dcf-text-capitalize\">{{ operation | translate }}</ion-label>\n </ion-item>\n }\n }\n </ion-list>\n </ion-content>\n </ng-template>\n </ion-popover>\n </div>\n }\n <!-- @if(operations?.length && uid) {\n <div class=\"dcf-visible@m\" id=\"dcf-actions\">\n @if(operations?.includes('update')) {\n <ion-button fill=\"clear\" size=\"small\" color=\"primary\" (click)=\"handleAction('update', component)\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"create-outline\"></ion-icon>\n </ion-button>\n }\n @if(operations?.includes('delete')) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleAction('delete', component)\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-button>\n }\n </div>\n } -->\n @if(windowWidth > 639) {\n <div id=\"end\">\n <ng-content select=\"[slot='end']\"></ng-content>\n </div>\n }\n </div>\n </div>\n </div>\n </ion-item>\n @if(showSlideItems && uid) {\n <ion-item-options side=\"end\" (ionSwipe)=\"operations.length === 1 ? handleAction(operations[0], $event, component) : ''\">\n @if(operations?.includes('update')) {\n <ion-item-option class=\"dcf-update\" (click)=\"handleAction('update', $event, component)\" [expandable]=\"operations.length === 1\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"create-outline\"></ion-icon>\n </ion-item-option>\n }\n @if(operations?.includes('delete')) {\n <ion-item-option class=\"dcf- delete\" (click)=\"handleAction('delete', $event, component)\" [expandable]=\"operations.length === 1\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" name=\"trash\"></ion-icon>\n </ion-item-option>\n }\n </ion-item-options>\n }\n </ion-item-sliding>\n}\n", styles: ["@media (prefers-color-scheme: light){ion-item{--background-hover-opacity: .1;--background-focused-opacity: .1;--border-color: var(--dcf-color-gray-2)}ion-item .dcf-info{color:var(--dcf-color-gray-6)}ion-item .dcf-item-title{color:var(--dcf-color-gray-8)}ion-item .dcf-description{color:var(--dcf-color-gray-6)}ion-button{color:var(--dcf-color-gray-7);--background: var(--dcf-color-gray-1) !important}ion-avatar{color:var(--dcf-color-gray-7);background:var(--dcf-color-gray-1)!important}ion-item-option:not(.dcf-delete),ion-item-option:not(.dcf-update){background:rgba(var(--dcf-color-dark-rgb),.25)!important}ion-item-option:not(.dcf-delete) .dcf-ti,ion-item-option:not(.dcf-delete) ion-icon,ion-item-option:not(.dcf-update) .dcf-ti,ion-item-option:not(.dcf-update) ion-icon{color:var(--dcf-color-gray-7)!important}ion-item-option.dcf-delete{background:rgba(var(--dcf-color-danger-rgb),.05)!important}ion-item-option.dcf-delete .dcf-ti,ion-item-option.dcf-delete *,ion-item-option.dcf-delete ion-icon{color:var(--dcf-color-danger)!important}ion-item-option.dcf-update{background:rgba(var(--dcf-color-primary-rgb),.05)!important}ion-item-option.dcf-update .dcf-ti,ion-item-option.dcf-update ion-icon{color:var(--dcf-color-primary)!important}}@media (prefers-color-scheme: dark){ion-item{--background-hover-opacity: .25;--background-focused-opacity: .25;--border-color: var(--dcf-color-gray-6)}ion-item .dcf-description{color:var(--dcf-color-gray-4)}ion-button{color:var(--dcf-color-gray-1)!important;--background: var(--dcf-color-gray-7) !important}ion-avatar{color:var(--dcf-color-gray-1)!important;background:var(--dcf-background-color)!important}ion-item-option:not(.dcf-delete),ion-item-option:not(.dcf-update){background:rgba(var(--dcf-color-dark-rgb),1)!important}ion-item-option:not(.dcf-delete) .dcf-ti,ion-item-option:not(.dcf-delete) ion-icon,ion-item-option:not(.dcf-update) .dcf-ti,ion-item-option:not(.dcf-update) ion-icon{color:var(--dcf-color-gray-2)!important}ion-item-option.dcf-delete{background:rgba(var(--dcf-color-danger-rgb),.05)!important}ion-item-option.dcf-delete .dcf-ti,ion-item-option.dcf-delete *,ion-item-option.dcf-delete ion-icon{color:var(--dcf-color-danger)!important}ion-item-option.dcf-update{background:rgba(var(--dcf-color-primary-rgb),.05)!important}ion-item-option.dcf-update .dcf-ti,ion-item-option.dcf-update ion-icon{color:var(--dcf-color-gray-2)!important}}ion-item-sliding{box-sizing:border-box}ion-item-sliding[class*=active-slide]{border-color:var(--dcf-color-gray-3)}ion-item-sliding ion-item-option{color:var(--dcf-color-gray-5);box-shadow:inset 0 0 5px rgba(var(--dcf-color-dark-rgb),.15)!important;background:var(--dcf-color-gray-3)}ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--background-hover: var(--dcf-color-gray-8);--background-focused: var(--dcf-color-gray-8)}ion-item.item-lines-full{--padding-top: .5rem;--padding-bottom: .5rem;--padding-start: .25rem;-padding-end:.25rem;padding:0 .65rem}ion-item.item-lines-inset{--padding-top: 0rem !important;--padding-bottom: 0rem !important;--inner-padding-top: .5rem !important;--inner-padding-bottom: .65rem !important}ion-item .dcf-info{min-width:10vw;background:transparent!important}ion-item .dcf-grid{padding:0!important;margin:0!important;min-width:100%!important}ion-item .dcf-item-title{font-style:normal;font-weight:700}ion-item .dcf-description{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-style:normal;font-weight:400;font-size:.925rem}ion-item::part(native){min-width:100%}ion-item [slot=start]{margin-right:.5rem!important}ion-item [slot=end]{margin-left:.5rem!important}ion-item .dcf-info{font-size:.9rem}ion-item .dcf-info .dcf-subinfo.dcf-line{margin-left:.5rem}@media (min-width: var(--dcf-width-sm)){ion-item .dcf-info .dcf-subinfo.dcf-line{display:block;margin-left:0}}ion-item #dcf-actions{padding:5px}@media (max-width: var(--dcf-width-m)){ion-item #dcf-actions{display:none;pointer-events:none!important;cursor:text!important}ion-item #dcf-actions *{display:none;pointer-events:none!important;cursor:text!important}}ion-item #dcf-actions ion-button{--padding-start: 1rem;--padding-end: .75rem;--padding-top: .85rem !important;--padding-bottom: .85rem !important;color:#ccc;margin-right:.5rem!important;--background: var(--dcf-color-gray-2) !important}ion-item #dcf-actions ion-button ion-icon{position:relative;left:-1px}@media (max-width: var(--dcf-width-m)){ion-item #dcf-end,ion-item [slot=end]{display:none!important}}ion-item #dcf-end{padding-top:5px;display:flex;align-items:flex-end}ion-item .dcf-icon{display:flex;justify-content:center;align-items:center;text-align:center;margin-right:.5rem!important}ion-item .dcf-icon.dcf-grid-icon{min-width:50px;text-align:left;display:flex;justify-content:flex-start}@media (max-width: var(--dcf-width-s)){ion-item .dcf-icon{align-items:flex-start!important}}ion-item .dcf-icon ion-button ion-icon{font-size:20px}ion-item .dcf-icon ion-avatar{width:48px;height:48px;display:flex;justify-content:center;align-items:center;text-align:center}ion-item .dcf-icon ion-avatar ion-icon{font-size:20px}ion-item .dcf-icon ion-avatar .dcf-icon-large{transform:translateY(5px)}\n"] }]
|
|
8380
|
+
}], ctorParameters: () => [], propDecorators: { actionMenuComponent: [{
|
|
8381
|
+
type: ViewChild,
|
|
8382
|
+
args: ['actionMenuComponent']
|
|
8383
8383
|
}], lines: [{
|
|
8384
8384
|
type: Input
|
|
8385
|
-
}],
|
|
8386
|
-
type: Input
|
|
8387
|
-
}], scrollThreshold: [{
|
|
8388
|
-
type: Input
|
|
8389
|
-
}], scrollPosition: [{
|
|
8390
|
-
type: Input
|
|
8391
|
-
}], loadingText: [{
|
|
8392
|
-
type: Input
|
|
8393
|
-
}], showRefresher: [{
|
|
8385
|
+
}], item: [{
|
|
8394
8386
|
type: Input
|
|
8395
|
-
}],
|
|
8387
|
+
}], icon: [{
|
|
8396
8388
|
type: Input
|
|
8397
|
-
}],
|
|
8389
|
+
}], iconSlot: [{
|
|
8398
8390
|
type: Input
|
|
8399
|
-
}],
|
|
8391
|
+
}], button: [{
|
|
8400
8392
|
type: Input
|
|
8401
|
-
}],
|
|
8393
|
+
}], title: [{
|
|
8402
8394
|
type: Input
|
|
8403
|
-
}],
|
|
8395
|
+
}], description: [{
|
|
8404
8396
|
type: Input
|
|
8405
|
-
}],
|
|
8397
|
+
}], info: [{
|
|
8406
8398
|
type: Input
|
|
8407
|
-
}],
|
|
8399
|
+
}], subinfo: [{
|
|
8408
8400
|
type: Input
|
|
8409
|
-
}], refreshEvent: [{
|
|
8410
|
-
type: Output
|
|
8411
8401
|
}], clickEvent: [{
|
|
8412
8402
|
type: Output
|
|
8413
|
-
}],
|
|
8414
|
-
type: HostListener,
|
|
8415
|
-
args: ['window:ListItemClickEvent', ['$event']]
|
|
8416
|
-
}], handleSearch: [{
|
|
8417
|
-
type: HostListener,
|
|
8418
|
-
args: ['window:searchbarEvent', ['$event']]
|
|
8419
|
-
}], refresh: [{
|
|
8403
|
+
}], enableSlideItems: [{
|
|
8420
8404
|
type: HostListener,
|
|
8421
|
-
args: ['window:
|
|
8405
|
+
args: ['window:resize', ['$event']]
|
|
8422
8406
|
}] } });
|
|
8423
8407
|
|
|
8424
|
-
let
|
|
8408
|
+
let SteppedFormComponent = class SteppedFormComponent {
|
|
8425
8409
|
/**
|
|
8426
|
-
* @description Creates an instance of
|
|
8427
|
-
* @summary Initializes a new
|
|
8410
|
+
* @description Creates an instance of SteppedFormComponent.
|
|
8411
|
+
* @summary Initializes a new SteppedFormComponent instance and registers the required
|
|
8428
8412
|
* Ionic icons for navigation buttons (forward and back arrows).
|
|
8429
8413
|
*
|
|
8430
|
-
* @memberOf
|
|
8414
|
+
* @memberOf SteppedFormComponent
|
|
8431
8415
|
*/
|
|
8432
8416
|
constructor() {
|
|
8433
8417
|
/**
|
|
@@ -8438,7 +8422,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8438
8422
|
*
|
|
8439
8423
|
* @type {number}
|
|
8440
8424
|
* @default 1
|
|
8441
|
-
* @memberOf
|
|
8425
|
+
* @memberOf SteppedFormComponent
|
|
8442
8426
|
*/
|
|
8443
8427
|
this.pages = 1;
|
|
8444
8428
|
/**
|
|
@@ -8449,7 +8433,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8449
8433
|
*
|
|
8450
8434
|
* @type {CrudOperations}
|
|
8451
8435
|
* @default OperationKeys.CREATE
|
|
8452
|
-
* @memberOf
|
|
8436
|
+
* @memberOf SteppedFormComponent
|
|
8453
8437
|
*/
|
|
8454
8438
|
this.operation = OperationKeys.CREATE;
|
|
8455
8439
|
/**
|
|
@@ -8460,7 +8444,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8460
8444
|
*
|
|
8461
8445
|
* @type {number}
|
|
8462
8446
|
* @default 1
|
|
8463
|
-
* @memberOf
|
|
8447
|
+
* @memberOf SteppedFormComponent
|
|
8464
8448
|
*/
|
|
8465
8449
|
this.startPage = 1;
|
|
8466
8450
|
/**
|
|
@@ -8470,7 +8454,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8470
8454
|
* updated whenever the user navigates between pages.
|
|
8471
8455
|
*
|
|
8472
8456
|
* @type {UIModelMetadata[] | undefined}
|
|
8473
|
-
* @memberOf
|
|
8457
|
+
* @memberOf SteppedFormComponent
|
|
8474
8458
|
*/
|
|
8475
8459
|
this.activeChildren = undefined;
|
|
8476
8460
|
/**
|
|
@@ -8480,7 +8464,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8480
8464
|
* when using FormArray structure.
|
|
8481
8465
|
*
|
|
8482
8466
|
* @type {FormGroup | undefined}
|
|
8483
|
-
* @memberOf
|
|
8467
|
+
* @memberOf SteppedFormComponent
|
|
8484
8468
|
*/
|
|
8485
8469
|
this.activeFormGroup = undefined;
|
|
8486
8470
|
/**
|
|
@@ -8490,7 +8474,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8490
8474
|
* the next/back buttons or programmatic navigation.
|
|
8491
8475
|
*
|
|
8492
8476
|
* @type {number}
|
|
8493
|
-
* @memberOf
|
|
8477
|
+
* @memberOf SteppedFormComponent
|
|
8494
8478
|
*/
|
|
8495
8479
|
this.activePage = 1;
|
|
8496
8480
|
/**
|
|
@@ -8500,7 +8484,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8500
8484
|
* logical pages and provide navigation structure.
|
|
8501
8485
|
*
|
|
8502
8486
|
* @type {UIModelMetadata[]}
|
|
8503
|
-
* @memberOf
|
|
8487
|
+
* @memberOf SteppedFormComponent
|
|
8504
8488
|
*/
|
|
8505
8489
|
this.pagesArray = [];
|
|
8506
8490
|
/**
|
|
@@ -8510,7 +8494,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8510
8494
|
* event type information for parent components to handle.
|
|
8511
8495
|
*
|
|
8512
8496
|
* @type {EventEmitter<BaseCustomEvent>}
|
|
8513
|
-
* @memberOf
|
|
8497
|
+
* @memberOf SteppedFormComponent
|
|
8514
8498
|
*/
|
|
8515
8499
|
this.submitEvent = new EventEmitter();
|
|
8516
8500
|
addIcons({ arrowForwardOutline, arrowBackOutline });
|
|
@@ -8524,7 +8508,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8524
8508
|
* @mermaid
|
|
8525
8509
|
* sequenceDiagram
|
|
8526
8510
|
* participant A as Angular Lifecycle
|
|
8527
|
-
* participant S as
|
|
8511
|
+
* participant S as SteppedFormComponent
|
|
8528
8512
|
* participant F as Form Service
|
|
8529
8513
|
*
|
|
8530
8514
|
* A->>S: ngOnInit()
|
|
@@ -8536,9 +8520,11 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8536
8520
|
* S->>F: Extract FormGroup for active page
|
|
8537
8521
|
* F-->>S: Return activeFormGroup
|
|
8538
8522
|
*
|
|
8539
|
-
* @memberOf
|
|
8523
|
+
* @memberOf SteppedFormComponent
|
|
8540
8524
|
*/
|
|
8541
8525
|
ngOnInit() {
|
|
8526
|
+
if (!this.locale)
|
|
8527
|
+
this.locale = getLocaleContext("SteppedFormComponent");
|
|
8542
8528
|
this.activePage = this.startPage;
|
|
8543
8529
|
this.pagesArray = this.children.reduce((acc, curr, index) => {
|
|
8544
8530
|
const page = curr.props?.['page'] || index + 1;
|
|
@@ -8563,7 +8549,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8563
8549
|
* @summary Unsubscribes from any active timer subscriptions to prevent memory leaks.
|
|
8564
8550
|
* This is part of Angular's component lifecycle and ensures proper resource cleanup.
|
|
8565
8551
|
*
|
|
8566
|
-
* @memberOf
|
|
8552
|
+
* @memberOf SteppedFormComponent
|
|
8567
8553
|
*/
|
|
8568
8554
|
ngOnDestroy() {
|
|
8569
8555
|
if (this.timerSubscription)
|
|
@@ -8581,7 +8567,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8581
8567
|
* @mermaid
|
|
8582
8568
|
* sequenceDiagram
|
|
8583
8569
|
* participant U as User
|
|
8584
|
-
* participant S as
|
|
8570
|
+
* participant S as SteppedFormComponent
|
|
8585
8571
|
* participant F as Form Service
|
|
8586
8572
|
* participant P as Parent Component
|
|
8587
8573
|
*
|
|
@@ -8597,7 +8583,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8597
8583
|
* S->>P: submitEvent.emit({data, name: SUBMIT})
|
|
8598
8584
|
* end
|
|
8599
8585
|
*
|
|
8600
|
-
* @memberOf
|
|
8586
|
+
* @memberOf SteppedFormComponent
|
|
8601
8587
|
*/
|
|
8602
8588
|
handleNext(lastPage = false) {
|
|
8603
8589
|
const isValid = NgxFormService.validateFields(this.activeFormGroup);
|
|
@@ -8628,14 +8614,14 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8628
8614
|
* @mermaid
|
|
8629
8615
|
* sequenceDiagram
|
|
8630
8616
|
* participant U as User
|
|
8631
|
-
* participant S as
|
|
8617
|
+
* participant S as SteppedFormComponent
|
|
8632
8618
|
*
|
|
8633
8619
|
* U->>S: Click Back
|
|
8634
8620
|
* S->>S: activePage--
|
|
8635
8621
|
* S->>S: getCurrentFormGroup(activePage)
|
|
8636
8622
|
* Note over S: Update active form and children
|
|
8637
8623
|
*
|
|
8638
|
-
* @memberOf
|
|
8624
|
+
* @memberOf SteppedFormComponent
|
|
8639
8625
|
*/
|
|
8640
8626
|
handleBack() {
|
|
8641
8627
|
this.activePage = this.activePage - 1;
|
|
@@ -8653,7 +8639,7 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8653
8639
|
* @private
|
|
8654
8640
|
* @mermaid
|
|
8655
8641
|
* sequenceDiagram
|
|
8656
|
-
* participant S as
|
|
8642
|
+
* participant S as SteppedFormComponent
|
|
8657
8643
|
* participant F as FormArray
|
|
8658
8644
|
* participant T as Timer
|
|
8659
8645
|
*
|
|
@@ -8664,27 +8650,36 @@ let StepedFormComponent = class StepedFormComponent {
|
|
|
8664
8650
|
* T-->>S: Filter children for active page
|
|
8665
8651
|
* S->>S: Set activeChildren
|
|
8666
8652
|
*
|
|
8667
|
-
* @memberOf
|
|
8653
|
+
* @memberOf SteppedFormComponent
|
|
8668
8654
|
*/
|
|
8669
8655
|
getCurrentFormGroup(page) {
|
|
8670
8656
|
this.activeFormGroup = this.formGroup.at(page - 1);
|
|
8671
8657
|
this.activeChildren = undefined;
|
|
8672
8658
|
this.timerSubscription = timer(10).subscribe(() => {
|
|
8673
8659
|
this.activeChildren = this.children.filter(c => c.props?.['page'] === page);
|
|
8674
|
-
console.log(this.activeChildren);
|
|
8675
8660
|
});
|
|
8676
8661
|
}
|
|
8677
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8678
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
8662
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SteppedFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8663
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.2", type: SteppedFormComponent, isStandalone: true, selector: "ngx-decaf-stepped-form", inputs: { locale: "locale", pages: "pages", operation: "operation", startPage: "startPage", children: "children", formGroup: "formGroup" }, outputs: { submitEvent: "submitEvent" }, ngImport: i0, template: "<form class=\"dcf-steped-form\" novalidate>\n <div class=\"dcf-page-steps\">\n <div>\n @for(page of pagesArray; track $index;) {\n <div [class.dcf-active]=\"activePage === $index + 1\" [class.dcf-passed]=\"($index + 1) < activePage\">{{ $index + 1 }}</div>\n }\n </div>\n </div>\n @if(formGroup) {\n @for(child of activeChildren; track $index) {\n <ngx-decaf-component-renderer\n [tag]=\"child?.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [children]=\"child?.children || []\"\n [globals]=\"{props: child.props}\"\n />\n }\n } @else {\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n <br />\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n }\n\n <div class=\"dcf-buttons-container dcf-grid dcf-grid-collapse dcf-flex dcf-flex-left\">\n <div class=\"dcf-width-1-2@s\">\n <ion-button fill=\"clear\" (click)=\"handleBack()\" [disabled]=\"activePage <= 1\">\n <ion-icon aria-hidden=\"true\" name=\"arrow-back-outline\"></ion-icon>\n {{locale + '.previous' | translate}}\n </ion-button>\n </div>\n\n <div class=\"dcf-width-1-2@s\">\n <ion-button [fill]=\"activePage === pages ? 'solid' : 'outline'\" (click)=\"handleNext(activePage === pages ? true : false)\">\n @if(activePage === pages) {\n {{locale + '.submit' | translate}}\n } @else {\n {{locale + '.next' | translate}}\n <ion-icon aria-hidden=\"true\" name=\"arrow-forward-outline\"></ion-icon>\n }\n </ion-button>\n </div>\n </div>\n</form>\n", styles: [".dcf-buttons-container{margin-top:1.8rem;margin-bottom:0}@media (min-width: 639px){.dcf-buttons-container.dcf-flex div:nth-child(2){display:flex;justify-content:flex-end}}@media (max-width: 638px){.dcf-buttons-container.dcf-flex div{width:100%}.dcf-buttons-container.dcf-flex ion-button{width:100%;margin-bottom:1rem}}.dcf-steped-form{padding:2rem 1rem}.dcf-page-steps{display:flex;justify-content:center;margin-bottom:2rem}.dcf-page-steps>div{justify-content:center;min-width:200px;max-width:200px;column-gap:.25em;display:flex}.dcf-page-steps>div>div{width:30px;text-align:center;border-bottom:solid var(--dcf-color-gray-3);box-sizing:border-box;border-width:3px;font-size:0px;font-weight:600}.dcf-page-steps>div>div.dcf-active{border-width:5px;font-size:1rem;color:var(--ion-color-gray-7);border-color:var(--ion-color-primary);line-height:1rem}.dcf-page-steps>div>div.dcf-passed{border-width:4px;font-size:.5rem;line-height:1.2rem;border-color:var(--dcf-color-gray-5);color:var(--ion-color-primary)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "component", type: IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "globals", "children", "model", "parent"], outputs: ["listenEvent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
8679
8664
|
};
|
|
8680
|
-
|
|
8665
|
+
SteppedFormComponent = __decorate([
|
|
8681
8666
|
Dynamic(),
|
|
8682
8667
|
__metadata("design:paramtypes", [])
|
|
8683
|
-
],
|
|
8684
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8668
|
+
], SteppedFormComponent);
|
|
8669
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SteppedFormComponent, decorators: [{
|
|
8685
8670
|
type: Component,
|
|
8686
|
-
args: [{ selector: 'ngx-decaf-
|
|
8687
|
-
|
|
8671
|
+
args: [{ selector: 'ngx-decaf-stepped-form', imports: [
|
|
8672
|
+
TranslatePipe,
|
|
8673
|
+
ReactiveFormsModule,
|
|
8674
|
+
IonSkeletonText,
|
|
8675
|
+
IonText,
|
|
8676
|
+
IonButton,
|
|
8677
|
+
IonIcon,
|
|
8678
|
+
ComponentRendererComponent
|
|
8679
|
+
], standalone: true, template: "<form class=\"dcf-steped-form\" novalidate>\n <div class=\"dcf-page-steps\">\n <div>\n @for(page of pagesArray; track $index;) {\n <div [class.dcf-active]=\"activePage === $index + 1\" [class.dcf-passed]=\"($index + 1) < activePage\">{{ $index + 1 }}</div>\n }\n </div>\n </div>\n @if(formGroup) {\n @for(child of activeChildren; track $index) {\n <ngx-decaf-component-renderer\n [tag]=\"child?.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [children]=\"child?.children || []\"\n [globals]=\"{props: child.props}\"\n />\n }\n } @else {\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n <br />\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n }\n\n <div class=\"dcf-buttons-container dcf-grid dcf-grid-collapse dcf-flex dcf-flex-left\">\n <div class=\"dcf-width-1-2@s\">\n <ion-button fill=\"clear\" (click)=\"handleBack()\" [disabled]=\"activePage <= 1\">\n <ion-icon aria-hidden=\"true\" name=\"arrow-back-outline\"></ion-icon>\n {{locale + '.previous' | translate}}\n </ion-button>\n </div>\n\n <div class=\"dcf-width-1-2@s\">\n <ion-button [fill]=\"activePage === pages ? 'solid' : 'outline'\" (click)=\"handleNext(activePage === pages ? true : false)\">\n @if(activePage === pages) {\n {{locale + '.submit' | translate}}\n } @else {\n {{locale + '.next' | translate}}\n <ion-icon aria-hidden=\"true\" name=\"arrow-forward-outline\"></ion-icon>\n }\n </ion-button>\n </div>\n </div>\n</form>\n", styles: [".dcf-buttons-container{margin-top:1.8rem;margin-bottom:0}@media (min-width: 639px){.dcf-buttons-container.dcf-flex div:nth-child(2){display:flex;justify-content:flex-end}}@media (max-width: 638px){.dcf-buttons-container.dcf-flex div{width:100%}.dcf-buttons-container.dcf-flex ion-button{width:100%;margin-bottom:1rem}}.dcf-steped-form{padding:2rem 1rem}.dcf-page-steps{display:flex;justify-content:center;margin-bottom:2rem}.dcf-page-steps>div{justify-content:center;min-width:200px;max-width:200px;column-gap:.25em;display:flex}.dcf-page-steps>div>div{width:30px;text-align:center;border-bottom:solid var(--dcf-color-gray-3);box-sizing:border-box;border-width:3px;font-size:0px;font-weight:600}.dcf-page-steps>div>div.dcf-active{border-width:5px;font-size:1rem;color:var(--ion-color-gray-7);border-color:var(--ion-color-primary);line-height:1rem}.dcf-page-steps>div>div.dcf-passed{border-width:4px;font-size:.5rem;line-height:1.2rem;border-color:var(--dcf-color-gray-5);color:var(--ion-color-primary)}\n"] }]
|
|
8680
|
+
}], ctorParameters: () => [], propDecorators: { locale: [{
|
|
8681
|
+
type: Input
|
|
8682
|
+
}], pages: [{
|
|
8688
8683
|
type: Input
|
|
8689
8684
|
}], operation: [{
|
|
8690
8685
|
type: Input
|
|
@@ -8714,10 +8709,10 @@ class CollapsableDirective {
|
|
|
8714
8709
|
}
|
|
8715
8710
|
}
|
|
8716
8711
|
}
|
|
8717
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8718
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
8712
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CollapsableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
8713
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.2", type: CollapsableDirective, isStandalone: true, selector: "[decafCollapsable]", ngImport: i0 }); }
|
|
8719
8714
|
}
|
|
8720
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8715
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CollapsableDirective, decorators: [{
|
|
8721
8716
|
type: Directive,
|
|
8722
8717
|
args: [{
|
|
8723
8718
|
selector: '[decafCollapsable]',
|
|
@@ -8740,11 +8735,11 @@ const Components = [
|
|
|
8740
8735
|
FieldsetComponent,
|
|
8741
8736
|
LayoutComponent,
|
|
8742
8737
|
FilterComponent,
|
|
8743
|
-
|
|
8738
|
+
SteppedFormComponent
|
|
8744
8739
|
];
|
|
8745
8740
|
class ForAngularComponentsModule {
|
|
8746
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8747
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
8741
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ForAngularComponentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
8742
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.2", ngImport: i0, type: ForAngularComponentsModule, imports: [ModelRendererComponent,
|
|
8748
8743
|
ComponentRendererComponent,
|
|
8749
8744
|
CrudFieldComponent,
|
|
8750
8745
|
CrudFormComponent,
|
|
@@ -8757,7 +8752,7 @@ class ForAngularComponentsModule {
|
|
|
8757
8752
|
FieldsetComponent,
|
|
8758
8753
|
LayoutComponent,
|
|
8759
8754
|
FilterComponent,
|
|
8760
|
-
|
|
8755
|
+
SteppedFormComponent, CollapsableDirective], exports: [ModelRendererComponent,
|
|
8761
8756
|
ComponentRendererComponent,
|
|
8762
8757
|
CrudFieldComponent,
|
|
8763
8758
|
CrudFormComponent,
|
|
@@ -8770,8 +8765,8 @@ class ForAngularComponentsModule {
|
|
|
8770
8765
|
FieldsetComponent,
|
|
8771
8766
|
LayoutComponent,
|
|
8772
8767
|
FilterComponent,
|
|
8773
|
-
|
|
8774
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
8768
|
+
SteppedFormComponent, CollapsableDirective] }); }
|
|
8769
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ForAngularComponentsModule, imports: [CrudFieldComponent,
|
|
8775
8770
|
CrudFormComponent,
|
|
8776
8771
|
EmptyStateComponent,
|
|
8777
8772
|
ListComponent,
|
|
@@ -8781,14 +8776,14 @@ class ForAngularComponentsModule {
|
|
|
8781
8776
|
CrudFormComponent,
|
|
8782
8777
|
FieldsetComponent,
|
|
8783
8778
|
FilterComponent,
|
|
8784
|
-
|
|
8779
|
+
SteppedFormComponent] }); }
|
|
8785
8780
|
}
|
|
8786
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8781
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ForAngularComponentsModule, decorators: [{
|
|
8787
8782
|
type: NgModule,
|
|
8788
8783
|
args: [{
|
|
8789
8784
|
imports: [...Components, ...Directives],
|
|
8790
8785
|
declarations: [],
|
|
8791
|
-
schemas: [
|
|
8786
|
+
schemas: [],
|
|
8792
8787
|
exports: [...Components, ...Directives],
|
|
8793
8788
|
}]
|
|
8794
8789
|
}] });
|
|
@@ -8807,5 +8802,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
8807
8802
|
* Generated bundle index. Do not edit.
|
|
8808
8803
|
*/
|
|
8809
8804
|
|
|
8810
|
-
export { AngularEngineKeys, BaseComponentProps, CollapsableDirective, ComponentRendererComponent, ComponentsTagNames, CrudFieldComponent, CrudFormComponent, CssClasses, DB_ADAPTER_PROVIDER_TOKEN, DefaultFormReactiveOptions, Dynamic, DynamicModule, EmptyStateComponent, EventConstants, FieldsetComponent, FilterComponent, ForAngularCommonModule, ForAngularComponentsModule, FormConstants, I18N_CONFIG_TOKEN, I18nLoader, I18nLoaderFactory, LayoutComponent, ListComponent, ListComponentsTypes, ListItemComponent, LoggerLevels, ModelRendererComponent,
|
|
8805
|
+
export { AngularEngineKeys, BaseComponentProps, CollapsableDirective, ComponentRendererComponent, ComponentsTagNames, CrudFieldComponent, CrudFormComponent, CssClasses, DB_ADAPTER_PROVIDER_TOKEN, DefaultFormReactiveOptions, Dynamic, DynamicModule, EmptyStateComponent, EventConstants, FieldsetComponent, FilterComponent, ForAngularCommonModule, ForAngularComponentsModule, FormConstants, I18N_CONFIG_TOKEN, I18nLoader, I18nLoaderFactory, LayoutComponent, ListComponent, ListComponentsTypes, ListItemComponent, LoggerLevels, ModelRendererComponent, NgxBaseComponent, NgxCrudFormField, NgxFormService, NgxRenderingEngine, PaginationComponent, RouteDirections, SearchbarComponent, SteppedFormComponent, cleanSpaces, dataMapper, formatDate, generateRandomValue, getInjectablesRegistry, getLocaleContext, getLocaleContextByKey, getLocaleFromClassName, getLocaleLanguage, getLogger, getOnWindow, getOnWindowDocument, getWindow, getWindowDocument, getWindowWidth, isDarkMode, isDevelopmentMode, isNotUndefined, isValidDate, itemMapper, parseToValidDate, provideDbAdapter, provideI18nLoader, removeFocusTrap, setOnWindow, stringToBoolean, windowEventEmitter };
|
|
8811
8806
|
//# sourceMappingURL=decaf-ts-for-angular.mjs.map
|