@decaf-ts/for-angular 0.0.25 → 0.0.27
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 +1486 -1505
- package/fesm2022/decaf-ts-for-angular.mjs.map +1 -1
- package/index.d.ts +7482 -3
- package/package.json +15 -18
- 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/stepped-form/stepped-form.component.d.ts +0 -255
- 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/stepped-form/stepped-form.component.mjs +0 -306
- 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 -85
- 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,
|
|
@@ -875,7 +885,6 @@ class NgxFormService {
|
|
|
875
885
|
* @memberOf NgxFormService
|
|
876
886
|
*/
|
|
877
887
|
static { this.formRegistry = new Map(); }
|
|
878
|
-
static { this.pageMapper = {}; }
|
|
879
888
|
/**
|
|
880
889
|
* @description Creates a new form group or form array with the specified identifier.
|
|
881
890
|
* @summary Generates a FormGroup or FormArray based on the provided properties. If pages are specified
|
|
@@ -2382,10 +2391,10 @@ class ComponentRendererComponent {
|
|
|
2382
2391
|
}
|
|
2383
2392
|
}
|
|
2384
2393
|
}
|
|
2385
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
2386
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
2394
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ComponentRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
2395
|
+
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
2396
|
}
|
|
2388
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
2397
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ComponentRendererComponent, decorators: [{
|
|
2389
2398
|
type: Component,
|
|
2390
2399
|
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
2400
|
}], ctorParameters: () => [], propDecorators: { vcr: [{
|
|
@@ -2660,20 +2669,6 @@ var en = {
|
|
|
2660
2669
|
component: component
|
|
2661
2670
|
};
|
|
2662
2671
|
|
|
2663
|
-
class I18nLoader {
|
|
2664
|
-
static loadFromHttp(http) {
|
|
2665
|
-
function getSuffix() {
|
|
2666
|
-
const today = new Date();
|
|
2667
|
-
return `.json?version=${today.getFullYear()}${today.getMonth()}${today.getDay()}`;
|
|
2668
|
-
}
|
|
2669
|
-
return new (class extends TranslateHttpLoader {
|
|
2670
|
-
getTranslation(lang) {
|
|
2671
|
-
const res = super.getTranslation(lang);
|
|
2672
|
-
return res;
|
|
2673
|
-
}
|
|
2674
|
-
})(http, './assets/i18n/', getSuffix());
|
|
2675
|
-
}
|
|
2676
|
-
}
|
|
2677
2672
|
function getLocaleContext(clazz, suffix) {
|
|
2678
2673
|
return getLocaleFromClassName(clazz, suffix);
|
|
2679
2674
|
}
|
|
@@ -2700,22 +2695,21 @@ function getLocaleContextByKey(locale, phrase) {
|
|
|
2700
2695
|
return `${locale}.${cleanSpaces(parts.join('.'), true)}`;
|
|
2701
2696
|
}
|
|
2702
2697
|
function I18nLoaderFactory(http) {
|
|
2703
|
-
const { resources, versionedSuffix } = inject(I18N_CONFIG_TOKEN, { optional: true }) ??
|
|
2704
|
-
return new
|
|
2698
|
+
const { resources, versionedSuffix } = inject(I18N_CONFIG_TOKEN, { optional: true }) ?? provideI18nLoader().useValue;
|
|
2699
|
+
return new I18nLoader(http, resources?.length ? resources : [{ prefix: './app/assets/i18n/', suffix: '.json' }], versionedSuffix);
|
|
2705
2700
|
}
|
|
2706
|
-
function
|
|
2701
|
+
function provideI18nLoader(resources = [], versionedSuffix = false) {
|
|
2707
2702
|
if (!Array.isArray(resources))
|
|
2708
2703
|
resources = [resources];
|
|
2709
2704
|
return {
|
|
2710
2705
|
provide: I18N_CONFIG_TOKEN,
|
|
2711
2706
|
useValue: { resources: [
|
|
2712
|
-
// { prefix: './assets/i18n/', suffix: '.json' },
|
|
2713
2707
|
...resources
|
|
2714
2708
|
], versionedSuffix }
|
|
2715
2709
|
};
|
|
2716
2710
|
}
|
|
2717
2711
|
const libLanguage = { en };
|
|
2718
|
-
class
|
|
2712
|
+
class I18nLoader {
|
|
2719
2713
|
constructor(http, resources = [], versionedSuffix = false) {
|
|
2720
2714
|
this.http = http;
|
|
2721
2715
|
this.resources = resources;
|
|
@@ -3101,13 +3095,13 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxCrudFormField {
|
|
|
3101
3095
|
});
|
|
3102
3096
|
component.dispatchEvent(event);
|
|
3103
3097
|
}
|
|
3104
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3105
|
-
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"] }] }); }
|
|
3098
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CrudFieldComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
3099
|
+
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" }] }); }
|
|
3106
3100
|
};
|
|
3107
3101
|
CrudFieldComponent = __decorate([
|
|
3108
3102
|
Dynamic()
|
|
3109
3103
|
], CrudFieldComponent);
|
|
3110
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3104
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CrudFieldComponent, decorators: [{
|
|
3111
3105
|
type: Component,
|
|
3112
3106
|
args: [{ standalone: true, imports: [
|
|
3113
3107
|
ReactiveFormsModule,
|
|
@@ -3121,9 +3115,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
3121
3115
|
IonSelectOption,
|
|
3122
3116
|
IonLabel,
|
|
3123
3117
|
IonText,
|
|
3124
|
-
IonTextarea
|
|
3125
|
-
|
|
3126
|
-
], 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"] }]
|
|
3118
|
+
IonTextarea
|
|
3119
|
+
], 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"] }]
|
|
3127
3120
|
}], propDecorators: { operation: [{
|
|
3128
3121
|
type: Input,
|
|
3129
3122
|
args: [{ required: true }]
|
|
@@ -3743,10 +3736,10 @@ class NgxBaseComponent {
|
|
|
3743
3736
|
if (!this.initialized)
|
|
3744
3737
|
this.initialized = true;
|
|
3745
3738
|
}
|
|
3746
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
3747
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
3739
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxBaseComponent, deps: [{ token: 'instanceToken' }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
3740
|
+
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 }); }
|
|
3748
3741
|
}
|
|
3749
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
3742
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: NgxBaseComponent, decorators: [{
|
|
3750
3743
|
type: Component,
|
|
3751
3744
|
args: [{
|
|
3752
3745
|
standalone: true,
|
|
@@ -4015,13 +4008,13 @@ let CrudFormComponent = class CrudFormComponent {
|
|
|
4015
4008
|
name: EventConstants.SUBMIT,
|
|
4016
4009
|
});
|
|
4017
4010
|
}
|
|
4018
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
4019
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
4011
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CrudFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4012
|
+
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"] }] }); }
|
|
4020
4013
|
};
|
|
4021
4014
|
CrudFormComponent = __decorate([
|
|
4022
4015
|
Dynamic()
|
|
4023
4016
|
], CrudFormComponent);
|
|
4024
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4017
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CrudFormComponent, decorators: [{
|
|
4025
4018
|
type: Component,
|
|
4026
4019
|
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"] }]
|
|
4027
4020
|
}], propDecorators: { model: [{
|
|
@@ -4347,17 +4340,16 @@ let EmptyStateComponent = class EmptyStateComponent extends NgxBaseComponent {
|
|
|
4347
4340
|
const result = await this.translate.instant(content, { 'value0': this.searchValue });
|
|
4348
4341
|
return this.sanitizer.bypassSecurityTrustHtml(result);
|
|
4349
4342
|
}
|
|
4350
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
4351
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
4343
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: EmptyStateComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4344
|
+
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"] }] }); }
|
|
4352
4345
|
};
|
|
4353
4346
|
EmptyStateComponent = __decorate([
|
|
4354
4347
|
Dynamic(),
|
|
4355
4348
|
__metadata("design:paramtypes", [])
|
|
4356
4349
|
], EmptyStateComponent);
|
|
4357
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
4350
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: EmptyStateComponent, decorators: [{
|
|
4358
4351
|
type: Component,
|
|
4359
4352
|
args: [{ selector: 'ngx-decaf-empty-state', standalone: true, imports: [
|
|
4360
|
-
TranslatePipe,
|
|
4361
4353
|
IonCard,
|
|
4362
4354
|
IonCardContent,
|
|
4363
4355
|
IonIcon
|
|
@@ -5001,14 +4993,14 @@ let FieldsetComponent = class FieldsetComponent extends NgxBaseComponent {
|
|
|
5001
4993
|
}
|
|
5002
4994
|
return this.mapper;
|
|
5003
4995
|
}
|
|
5004
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
5005
|
-
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"] }] }); }
|
|
4996
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FieldsetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
4997
|
+
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" }] }); }
|
|
5006
4998
|
};
|
|
5007
4999
|
FieldsetComponent = __decorate([
|
|
5008
5000
|
Dynamic(),
|
|
5009
5001
|
__metadata("design:paramtypes", [])
|
|
5010
5002
|
], FieldsetComponent);
|
|
5011
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
5003
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FieldsetComponent, decorators: [{
|
|
5012
5004
|
type: Component,
|
|
5013
5005
|
args: [{ standalone: true, selector: 'ngx-decaf-fieldset', schemas: [], imports: [
|
|
5014
5006
|
TranslatePipe,
|
|
@@ -5023,7 +5015,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
5023
5015
|
IonReorderGroup,
|
|
5024
5016
|
IonButton,
|
|
5025
5017
|
IonIcon,
|
|
5026
|
-
], 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}
|
|
5018
|
+
], 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"] }]
|
|
5027
5019
|
}], ctorParameters: () => [], propDecorators: { accordionComponent: [{
|
|
5028
5020
|
type: ViewChild,
|
|
5029
5021
|
args: ['accordionComponent', { static: false }]
|
|
@@ -5481,10 +5473,10 @@ class SearchbarComponent extends NgxBaseComponent {
|
|
|
5481
5473
|
preventChange(event) {
|
|
5482
5474
|
event.preventDefault();
|
|
5483
5475
|
}
|
|
5484
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
5485
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "
|
|
5476
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SearchbarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5477
|
+
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"] }] }); }
|
|
5486
5478
|
}
|
|
5487
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
5479
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SearchbarComponent, decorators: [{
|
|
5488
5480
|
type: Component,
|
|
5489
5481
|
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" }]
|
|
5490
5482
|
}], ctorParameters: () => [], propDecorators: { autocomplete: [{
|
|
@@ -6183,20 +6175,18 @@ let FilterComponent = class FilterComponent extends NgxBaseComponent {
|
|
|
6183
6175
|
handleSearch(value) {
|
|
6184
6176
|
this.searchEvent.emit(value);
|
|
6185
6177
|
}
|
|
6186
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6187
|
-
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"] }] }); }
|
|
6178
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6179
|
+
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" }] }); }
|
|
6188
6180
|
};
|
|
6189
6181
|
FilterComponent = __decorate([
|
|
6190
6182
|
Dynamic(),
|
|
6191
6183
|
__metadata("design:paramtypes", [])
|
|
6192
6184
|
], FilterComponent);
|
|
6193
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6185
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: FilterComponent, decorators: [{
|
|
6194
6186
|
type: Component,
|
|
6195
6187
|
args: [{ selector: 'ngx-decaf-filter', imports: [
|
|
6196
6188
|
FormsModule,
|
|
6197
6189
|
TranslatePipe,
|
|
6198
|
-
IonLabel,
|
|
6199
|
-
IonItem,
|
|
6200
6190
|
IonChip,
|
|
6201
6191
|
IonIcon,
|
|
6202
6192
|
IonButton,
|
|
@@ -6204,7 +6194,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
6204
6194
|
IonSelectOption,
|
|
6205
6195
|
IonIcon,
|
|
6206
6196
|
SearchbarComponent
|
|
6207
|
-
], 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"] }]
|
|
6197
|
+
], 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"] }]
|
|
6208
6198
|
}], ctorParameters: () => [], propDecorators: { optionsFilterElement: [{
|
|
6209
6199
|
type: ViewChild,
|
|
6210
6200
|
args: ['optionsFilterElement', { read: ElementRef, static: false }]
|
|
@@ -6335,10 +6325,10 @@ class ModelRendererComponent {
|
|
|
6335
6325
|
}
|
|
6336
6326
|
}
|
|
6337
6327
|
}
|
|
6338
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6339
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
6328
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ModelRendererComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6329
|
+
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"] }] }); }
|
|
6340
6330
|
}
|
|
6341
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6331
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ModelRendererComponent, decorators: [{
|
|
6342
6332
|
type: Component,
|
|
6343
6333
|
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" }]
|
|
6344
6334
|
}], propDecorators: { model: [{
|
|
@@ -6488,10 +6478,10 @@ class LayoutComponent extends NgxBaseComponent {
|
|
|
6488
6478
|
this.rows = this._rows;
|
|
6489
6479
|
this.initialized = true;
|
|
6490
6480
|
}
|
|
6491
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6492
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
6481
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6482
|
+
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" }] }); }
|
|
6493
6483
|
}
|
|
6494
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
6484
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: LayoutComponent, decorators: [{
|
|
6495
6485
|
type: Component,
|
|
6496
6486
|
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"] }]
|
|
6497
6487
|
}], ctorParameters: () => [], propDecorators: { cols: [{
|
|
@@ -6505,857 +6495,466 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
6505
6495
|
}] } });
|
|
6506
6496
|
|
|
6507
6497
|
/**
|
|
6508
|
-
* @description A component for
|
|
6509
|
-
* @summary
|
|
6510
|
-
*
|
|
6511
|
-
*
|
|
6512
|
-
* @extends NgxBaseComponent
|
|
6513
|
-
*
|
|
6514
|
-
* @param {string} [lines='none'] - Determines the line style of the item. Can be 'inset', 'inseet', or 'none'.
|
|
6515
|
-
* @param {Record<string, any>} item - The data item to be displayed in the list item.
|
|
6516
|
-
* @param {string} icon - The name of the icon to be displayed.
|
|
6517
|
-
* @param {'start' | 'end'} [iconSlot='start'] - The position of the icon within the item.
|
|
6518
|
-
* @param {StringOrBoolean} [button=true] - Determines if the item should behave as a button.
|
|
6519
|
-
* @param {string} [title] - The main title of the list item.
|
|
6520
|
-
* @param {string} [description] - A description for the list item.
|
|
6521
|
-
* @param {string} [info] - Additional information for the list item.
|
|
6522
|
-
* @param {string} [subinfo] - Sub-information for the list item.
|
|
6498
|
+
* @description A pagination component for navigating through multiple pages of content.
|
|
6499
|
+
* @summary This component provides a user interface for paginated content navigation,
|
|
6500
|
+
* displaying page numbers and navigation controls. It supports customizable page counts,
|
|
6501
|
+
* current page tracking, and emits events when users navigate between pages.
|
|
6523
6502
|
*
|
|
6524
|
-
*
|
|
6525
|
-
*
|
|
6526
|
-
*
|
|
6527
|
-
* icon="star"
|
|
6528
|
-
* title="Item Title"
|
|
6529
|
-
* description="Item Description"
|
|
6530
|
-
* (clickEvent)="handleItemClick($event)">
|
|
6531
|
-
* </ngx-decaf-list-item>
|
|
6503
|
+
* The component intelligently handles large numbers of pages by showing a subset of page
|
|
6504
|
+
* numbers with ellipses to indicate skipped pages, ensuring the UI remains clean and usable
|
|
6505
|
+
* even with many pages.
|
|
6532
6506
|
*
|
|
6533
6507
|
* @mermaid
|
|
6534
6508
|
* sequenceDiagram
|
|
6535
|
-
* participant C as Component
|
|
6536
|
-
* participant V as View
|
|
6537
6509
|
* participant U as User
|
|
6538
|
-
*
|
|
6539
|
-
*
|
|
6540
|
-
*
|
|
6541
|
-
*
|
|
6542
|
-
*
|
|
6543
|
-
*
|
|
6510
|
+
* participant P as PaginationComponent
|
|
6511
|
+
* participant E as External Component
|
|
6512
|
+
*
|
|
6513
|
+
* U->>P: Click page number
|
|
6514
|
+
* P->>P: navigate(page)
|
|
6515
|
+
* P->>P: handleClick(direction, page)
|
|
6516
|
+
* P->>E: Emit clickEvent with PaginationCustomEvent
|
|
6517
|
+
*
|
|
6518
|
+
* U->>P: Click next button
|
|
6519
|
+
* P->>P: next()
|
|
6520
|
+
* P->>P: handleClick('next')
|
|
6521
|
+
* P->>E: Emit clickEvent with PaginationCustomEvent
|
|
6522
|
+
*
|
|
6523
|
+
* U->>P: Click previous button
|
|
6524
|
+
* P->>P: previous()
|
|
6525
|
+
* P->>P: handleClick('previous')
|
|
6526
|
+
* P->>E: Emit clickEvent with PaginationCustomEvent
|
|
6527
|
+
*
|
|
6528
|
+
* @example
|
|
6529
|
+
* <ngx-decaf-pagination
|
|
6530
|
+
* [pages]="10"
|
|
6531
|
+
* [current]="3"
|
|
6532
|
+
* (clickEvent)="handlePageChange($event)">
|
|
6533
|
+
* </ngx-decaf-pagination>
|
|
6534
|
+
*
|
|
6535
|
+
* @extends {NgxBaseComponent}
|
|
6536
|
+
* @implements {OnInit}
|
|
6544
6537
|
*/
|
|
6545
|
-
|
|
6538
|
+
class PaginationComponent extends NgxBaseComponent {
|
|
6546
6539
|
/**
|
|
6547
|
-
* @
|
|
6548
|
-
* @
|
|
6549
|
-
* with the component name for
|
|
6550
|
-
* all available Ionic icons to ensure they can be displayed in the component.
|
|
6551
|
-
*
|
|
6552
|
-
* @memberOf ListItemComponent
|
|
6540
|
+
* @constructor
|
|
6541
|
+
* @description Initializes a new instance of the PaginationComponent.
|
|
6542
|
+
* Calls the parent constructor with the component name for generate base locale string.
|
|
6553
6543
|
*/
|
|
6554
6544
|
constructor() {
|
|
6555
|
-
super("
|
|
6556
|
-
/**
|
|
6557
|
-
* @description Controls the display of lines around the list item.
|
|
6558
|
-
* @summary Determines how lines are displayed around the list item borders.
|
|
6559
|
-
* 'inset' shows lines with padding, 'full' shows full-width lines, and 'none'
|
|
6560
|
-
* removes all lines. This affects the visual separation between list items.
|
|
6561
|
-
*
|
|
6562
|
-
* @type {'inset' | 'full' | 'none'}
|
|
6563
|
-
* @default 'inset'
|
|
6564
|
-
* @memberOf ListItemComponent
|
|
6565
|
-
*/
|
|
6566
|
-
this.lines = 'full';
|
|
6567
|
-
/**
|
|
6568
|
-
* @description Position of the icon within the list item.
|
|
6569
|
-
* @summary Determines whether the icon appears at the start (left in LTR languages)
|
|
6570
|
-
* or end (right in LTR languages) of the list item. This affects the overall
|
|
6571
|
-
* layout and visual hierarchy of the item content.
|
|
6572
|
-
*
|
|
6573
|
-
* @type {'start' | 'end'}
|
|
6574
|
-
* @default 'start'
|
|
6575
|
-
* @memberOf ListItemComponent
|
|
6576
|
-
*/
|
|
6577
|
-
this.iconSlot = 'start';
|
|
6545
|
+
super("PaginationComponent");
|
|
6578
6546
|
/**
|
|
6579
|
-
* @description Controls whether the
|
|
6580
|
-
* @summary When set to true, the
|
|
6581
|
-
*
|
|
6582
|
-
* When false, the item is displayed as static content without interactive behavior.
|
|
6547
|
+
* @description Controls whether the component uses translation services.
|
|
6548
|
+
* @summary When set to true, the component will attempt to use translation services
|
|
6549
|
+
* for any text content. This allows for internationalization of the pagination component.
|
|
6583
6550
|
*
|
|
6584
6551
|
* @type {StringOrBoolean}
|
|
6585
6552
|
* @default true
|
|
6586
|
-
* @memberOf
|
|
6587
|
-
*/
|
|
6588
|
-
this.button = true;
|
|
6589
|
-
/**
|
|
6590
|
-
* @description Event emitter for list item click interactions.
|
|
6591
|
-
* @summary Emits custom events when the list item is clicked or when actions
|
|
6592
|
-
* are performed on it. The emitted event contains information about the action,
|
|
6593
|
-
* the item data, and other relevant context for parent components to handle.
|
|
6594
|
-
*
|
|
6595
|
-
* @type {EventEmitter<ListItemCustomEvent>}
|
|
6596
|
-
* @memberOf ListItemComponent
|
|
6597
|
-
*/
|
|
6598
|
-
this.clickEvent = new EventEmitter();
|
|
6599
|
-
/**
|
|
6600
|
-
* @description Flag indicating whether slide items are currently enabled.
|
|
6601
|
-
* @summary Controls the visibility of slide actions based on screen size and
|
|
6602
|
-
* available operations. When true, users can swipe on the item to reveal
|
|
6603
|
-
* action buttons for operations like edit and delete.
|
|
6604
|
-
*
|
|
6605
|
-
* @type {boolean}
|
|
6606
|
-
* @default false
|
|
6607
|
-
* @memberOf ListItemComponent
|
|
6553
|
+
* @memberOf PaginationComponent
|
|
6608
6554
|
*/
|
|
6609
|
-
this.
|
|
6555
|
+
this.translatable = true;
|
|
6610
6556
|
/**
|
|
6611
|
-
* @description
|
|
6612
|
-
* @summary
|
|
6613
|
-
*
|
|
6614
|
-
* are performed. Used for managing the popover lifecycle.
|
|
6557
|
+
* @description The currently active page number.
|
|
6558
|
+
* @summary Specifies which page is currently active or selected. This value is used
|
|
6559
|
+
* to highlight the current page in the UI and as a reference point for navigation.
|
|
6615
6560
|
*
|
|
6616
|
-
* @type {
|
|
6617
|
-
* @default
|
|
6618
|
-
* @memberOf
|
|
6561
|
+
* @type {number}
|
|
6562
|
+
* @default 1
|
|
6563
|
+
* @memberOf PaginationComponent
|
|
6619
6564
|
*/
|
|
6620
|
-
this.
|
|
6565
|
+
this.current = 1;
|
|
6621
6566
|
/**
|
|
6622
|
-
* @description
|
|
6623
|
-
* @summary
|
|
6624
|
-
*
|
|
6625
|
-
*
|
|
6567
|
+
* @description Event emitter for pagination navigation events.
|
|
6568
|
+
* @summary Emits a custom event when users navigate between pages, either by clicking
|
|
6569
|
+
* on page numbers or using the next/previous buttons. The event contains information
|
|
6570
|
+
* about the navigation direction and the target page number.
|
|
6626
6571
|
*
|
|
6627
|
-
* @
|
|
6628
|
-
* @
|
|
6629
|
-
* @memberOf ListItemComponent
|
|
6572
|
+
* @type {EventEmitter<PaginationCustomEvent>}
|
|
6573
|
+
* @memberOf PaginationComponent
|
|
6630
6574
|
*/
|
|
6631
|
-
this.
|
|
6632
|
-
addIcons(
|
|
6575
|
+
this.clickEvent = new EventEmitter();
|
|
6576
|
+
addIcons({ chevronBackOutline, chevronForwardOutline });
|
|
6633
6577
|
}
|
|
6634
6578
|
/**
|
|
6635
|
-
* @description Initializes the component after Angular
|
|
6636
|
-
* @summary Sets up the component by
|
|
6637
|
-
*
|
|
6638
|
-
*
|
|
6639
|
-
* properly initialized and responsive behavior is configured.
|
|
6579
|
+
* @description Initializes the component after Angular sets the input properties.
|
|
6580
|
+
* @summary Sets up the component by initializing the locale settings based on the
|
|
6581
|
+
* translatable property, generating the page numbers based on the total pages and
|
|
6582
|
+
* current page, and storing the last page number for boundary checking.
|
|
6640
6583
|
*
|
|
6641
6584
|
* @mermaid
|
|
6642
6585
|
* sequenceDiagram
|
|
6643
6586
|
* participant A as Angular Lifecycle
|
|
6644
|
-
* participant
|
|
6645
|
-
* participant W as Window
|
|
6587
|
+
* participant P as PaginationComponent
|
|
6646
6588
|
*
|
|
6647
|
-
* A->>
|
|
6648
|
-
*
|
|
6649
|
-
*
|
|
6650
|
-
*
|
|
6651
|
-
*
|
|
6652
|
-
*
|
|
6653
|
-
* end
|
|
6654
|
-
* L->>W: getWindowWidth()
|
|
6655
|
-
* W-->>L: Return current width
|
|
6656
|
-
* L->>L: Store windowWidth
|
|
6589
|
+
* A->>P: ngOnInit()
|
|
6590
|
+
* P->>P: getLocale(translatable)
|
|
6591
|
+
* P->>P: Set locale
|
|
6592
|
+
* P->>P: getPages(data, current)
|
|
6593
|
+
* P->>P: Set pages array
|
|
6594
|
+
* P->>P: Set last page number
|
|
6657
6595
|
*
|
|
6658
|
-
* @
|
|
6659
|
-
* @memberOf
|
|
6596
|
+
* @returns {void}
|
|
6597
|
+
* @memberOf PaginationComponent
|
|
6660
6598
|
*/
|
|
6661
|
-
|
|
6662
|
-
this.
|
|
6663
|
-
this.
|
|
6664
|
-
this.
|
|
6665
|
-
if (this.operations?.length)
|
|
6666
|
-
this.className += ` action`;
|
|
6667
|
-
this.windowWidth = getWindowWidth();
|
|
6599
|
+
ngOnInit() {
|
|
6600
|
+
this.locale = this.getLocale(this.translatable);
|
|
6601
|
+
this.pages = this.getPages(this.totalPages, this.current);
|
|
6602
|
+
this.last = this.totalPages;
|
|
6668
6603
|
}
|
|
6669
6604
|
/**
|
|
6670
|
-
* @description Handles
|
|
6671
|
-
* @summary
|
|
6672
|
-
*
|
|
6673
|
-
*
|
|
6674
|
-
* route configuration. This method supports both event-driven and navigation-driven architectures.
|
|
6605
|
+
* @description Handles click events on pagination controls.
|
|
6606
|
+
* @summary Processes user interactions with the pagination component, updating the
|
|
6607
|
+
* current page if specified and emitting an event with navigation details. This method
|
|
6608
|
+
* is called when users click on page numbers or navigation buttons.
|
|
6675
6609
|
*
|
|
6676
|
-
* @param {
|
|
6677
|
-
* @param {
|
|
6678
|
-
* @
|
|
6679
|
-
* @return {Promise<boolean|void>} A promise that resolves to navigation success or void for events
|
|
6610
|
+
* @param {('next' | 'previous')} direction - The direction of navigation
|
|
6611
|
+
* @param {number} [page] - Optional page number to navigate to directly
|
|
6612
|
+
* @returns {void}
|
|
6680
6613
|
*
|
|
6681
6614
|
* @mermaid
|
|
6682
6615
|
* sequenceDiagram
|
|
6683
6616
|
* participant U as User
|
|
6684
|
-
* participant
|
|
6685
|
-
* participant
|
|
6686
|
-
* participant N as NavController
|
|
6687
|
-
* participant E as Event System
|
|
6617
|
+
* participant P as PaginationComponent
|
|
6618
|
+
* participant E as External Component
|
|
6688
6619
|
*
|
|
6689
|
-
* U->>
|
|
6690
|
-
*
|
|
6691
|
-
* alt
|
|
6692
|
-
*
|
|
6693
|
-
* end
|
|
6694
|
-
* L->>L: removeFocusTrap()
|
|
6695
|
-
* alt No route configured
|
|
6696
|
-
* L->>E: windowEventEmitter()
|
|
6697
|
-
* L->>P: clickEvent.emit()
|
|
6698
|
-
* else Route configured
|
|
6699
|
-
* L->>N: redirect(action, uid)
|
|
6700
|
-
* N-->>L: Return navigation result
|
|
6620
|
+
* U->>P: Click pagination control
|
|
6621
|
+
* P->>P: handleClick(direction, page?)
|
|
6622
|
+
* alt page is provided
|
|
6623
|
+
* P->>P: Update current page
|
|
6701
6624
|
* end
|
|
6625
|
+
* P->>E: Emit clickEvent with direction and page
|
|
6702
6626
|
*
|
|
6703
|
-
* @memberOf
|
|
6627
|
+
* @memberOf PaginationComponent
|
|
6704
6628
|
*/
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
}
|
|
6716
|
-
return await this.redirect(action, (typeof this.uid === 'number' ? `${this.uid}` : this.uid));
|
|
6629
|
+
handleClick(direction, page) {
|
|
6630
|
+
if (page)
|
|
6631
|
+
this.current = page;
|
|
6632
|
+
this.clickEvent.emit({
|
|
6633
|
+
name: EventConstants.CLICK,
|
|
6634
|
+
data: {
|
|
6635
|
+
direction,
|
|
6636
|
+
page: this.current
|
|
6637
|
+
},
|
|
6638
|
+
component: this.componentName
|
|
6639
|
+
});
|
|
6717
6640
|
}
|
|
6718
6641
|
/**
|
|
6719
|
-
* @description
|
|
6720
|
-
* @summary
|
|
6721
|
-
*
|
|
6722
|
-
*
|
|
6723
|
-
*
|
|
6642
|
+
* @description Generates the array of page objects for display.
|
|
6643
|
+
* @summary Creates an array of page objects based on the total number of pages and
|
|
6644
|
+
* the current page. For small page counts (≤5), all pages are shown. For larger page
|
|
6645
|
+
* counts, a subset is shown with ellipses to indicate skipped pages. This ensures
|
|
6646
|
+
* the pagination UI remains clean and usable even with many pages.
|
|
6724
6647
|
*
|
|
6725
|
-
* @
|
|
6648
|
+
* @param {number} total - The total number of pages
|
|
6649
|
+
* @param {number} [current] - The current active page (defaults to this.current)
|
|
6650
|
+
* @returns {KeyValue[]} Array of page objects with index and text properties
|
|
6726
6651
|
*
|
|
6727
6652
|
* @mermaid
|
|
6728
|
-
*
|
|
6729
|
-
*
|
|
6730
|
-
*
|
|
6731
|
-
*
|
|
6653
|
+
* flowchart TD
|
|
6654
|
+
* A[Start] --> B{total <= 5?}
|
|
6655
|
+
* B -->|Yes| C[Show all pages]
|
|
6656
|
+
* B -->|No| D[Show first page]
|
|
6657
|
+
* D --> E[Show last pages]
|
|
6658
|
+
* E --> F[Add ellipses for skipped pages]
|
|
6659
|
+
* C --> G[Return pages array]
|
|
6660
|
+
* F --> G
|
|
6732
6661
|
*
|
|
6733
|
-
*
|
|
6734
|
-
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6662
|
+
* @memberOf PaginationComponent
|
|
6663
|
+
*/
|
|
6664
|
+
getPages(total, current) {
|
|
6665
|
+
if (!current)
|
|
6666
|
+
current = this.current;
|
|
6667
|
+
const pages = [];
|
|
6668
|
+
function getPage(index, text = '', clazz = 'button') {
|
|
6669
|
+
if (pages.some(item => item['index'] === index))
|
|
6670
|
+
return;
|
|
6671
|
+
pages.push({ index, text: index != null ? index.toString().padStart(2, '0') : text, class: clazz });
|
|
6672
|
+
}
|
|
6673
|
+
if (total <= 5) {
|
|
6674
|
+
for (let i = 1; i <= total; i++)
|
|
6675
|
+
getPage(i);
|
|
6676
|
+
}
|
|
6677
|
+
else {
|
|
6678
|
+
// Adiciona os dois primeiros
|
|
6679
|
+
getPage(1);
|
|
6680
|
+
getPage(2);
|
|
6681
|
+
// Adiciona "..." entre os blocos
|
|
6682
|
+
if (current && current > 3)
|
|
6683
|
+
getPage(null, '...');
|
|
6684
|
+
// Adiciona a página atual (se estiver no meio)
|
|
6685
|
+
if (current && current > 2 && current < total - 1)
|
|
6686
|
+
getPage(current);
|
|
6687
|
+
// Adiciona "..." entre os blocos
|
|
6688
|
+
if (current && current < total - 2)
|
|
6689
|
+
getPage(null, '...', 'separator');
|
|
6690
|
+
// Adiciona os dois últimos
|
|
6691
|
+
getPage(total - 1);
|
|
6692
|
+
getPage(total);
|
|
6693
|
+
}
|
|
6694
|
+
return pages;
|
|
6695
|
+
}
|
|
6696
|
+
/**
|
|
6697
|
+
* @description Gets the current active page number.
|
|
6698
|
+
* @summary Returns the current page number that is active in the pagination component.
|
|
6699
|
+
* This method provides a way to access the current page state from outside the component.
|
|
6743
6700
|
*
|
|
6744
|
-
* @
|
|
6701
|
+
* @returns {number} The current page number
|
|
6702
|
+
* @memberOf PaginationComponent
|
|
6745
6703
|
*/
|
|
6746
|
-
|
|
6747
|
-
this.
|
|
6748
|
-
if (!this.operations?.length || this.windowWidth > 639)
|
|
6749
|
-
return this.showSlideItems = false;
|
|
6750
|
-
this.showSlideItems = this.operations.includes(OperationKeys.UPDATE) || this.operations.includes(OperationKeys.DELETE);
|
|
6751
|
-
return this.showSlideItems;
|
|
6704
|
+
getCurrent() {
|
|
6705
|
+
return this.current;
|
|
6752
6706
|
}
|
|
6753
6707
|
/**
|
|
6754
|
-
* @description
|
|
6755
|
-
* @summary
|
|
6756
|
-
*
|
|
6757
|
-
*
|
|
6758
|
-
* is coordinated with the CSS animation duration to ensure the element is removed
|
|
6759
|
-
* after the animation completes.
|
|
6708
|
+
* @description Navigates to the next page.
|
|
6709
|
+
* @summary Increments the current page number if not at the last page and triggers
|
|
6710
|
+
* the click event handler with 'next' direction. This method is typically called
|
|
6711
|
+
* when the user clicks on the "next" button in the pagination UI.
|
|
6760
6712
|
*
|
|
6761
|
-
* @
|
|
6762
|
-
* @return {void}
|
|
6713
|
+
* @returns {void}
|
|
6763
6714
|
*
|
|
6764
6715
|
* @mermaid
|
|
6765
6716
|
* sequenceDiagram
|
|
6766
|
-
* participant
|
|
6767
|
-
* participant
|
|
6768
|
-
* participant D as DOM
|
|
6717
|
+
* participant U as User
|
|
6718
|
+
* participant P as PaginationComponent
|
|
6769
6719
|
*
|
|
6770
|
-
*
|
|
6771
|
-
*
|
|
6772
|
-
*
|
|
6773
|
-
*
|
|
6774
|
-
*
|
|
6775
|
-
*
|
|
6776
|
-
* D->>D: Remove element from DOM
|
|
6720
|
+
* U->>P: Click next button
|
|
6721
|
+
* P->>P: next()
|
|
6722
|
+
* alt page <= max pages
|
|
6723
|
+
* P->>P: Increment current page
|
|
6724
|
+
* P->>P: handleClick('next')
|
|
6725
|
+
* end
|
|
6777
6726
|
*
|
|
6778
|
-
* @memberOf
|
|
6727
|
+
* @memberOf PaginationComponent
|
|
6779
6728
|
*/
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6729
|
+
next() {
|
|
6730
|
+
const page = this.current + 1;
|
|
6731
|
+
if (page <= Object.keys(this.pages)?.length || 0) {
|
|
6732
|
+
this.current = page;
|
|
6733
|
+
this.handleClick('next');
|
|
6734
|
+
}
|
|
6783
6735
|
}
|
|
6784
6736
|
/**
|
|
6785
|
-
* @description Navigates to
|
|
6786
|
-
* @summary
|
|
6787
|
-
* the
|
|
6788
|
-
*
|
|
6789
|
-
* CRUD operations where each action (create, read, update, delete) has its own route.
|
|
6737
|
+
* @description Navigates to the previous page.
|
|
6738
|
+
* @summary Decrements the current page number if not at the first page and triggers
|
|
6739
|
+
* the click event handler with 'previous' direction. This method is typically called
|
|
6740
|
+
* when the user clicks on the "previous" button in the pagination UI.
|
|
6790
6741
|
*
|
|
6791
|
-
* @
|
|
6792
|
-
* @param {string} [id] - The unique identifier of the item to be acted upon
|
|
6793
|
-
* @return {Promise<boolean>} A promise that resolves to true if navigation was successful
|
|
6742
|
+
* @returns {void}
|
|
6794
6743
|
*
|
|
6795
6744
|
* @mermaid
|
|
6796
6745
|
* sequenceDiagram
|
|
6797
|
-
* participant
|
|
6798
|
-
* participant
|
|
6799
|
-
* participant R as Router
|
|
6746
|
+
* participant U as User
|
|
6747
|
+
* participant P as PaginationComponent
|
|
6800
6748
|
*
|
|
6801
|
-
*
|
|
6802
|
-
*
|
|
6803
|
-
*
|
|
6804
|
-
*
|
|
6805
|
-
*
|
|
6806
|
-
*
|
|
6749
|
+
* U->>P: Click previous button
|
|
6750
|
+
* P->>P: previous()
|
|
6751
|
+
* alt page > 0
|
|
6752
|
+
* P->>P: Decrement current page
|
|
6753
|
+
* P->>P: handleClick('previous')
|
|
6754
|
+
* end
|
|
6807
6755
|
*
|
|
6808
|
-
* @memberOf
|
|
6756
|
+
* @memberOf PaginationComponent
|
|
6809
6757
|
*/
|
|
6810
|
-
|
|
6811
|
-
|
|
6758
|
+
previous() {
|
|
6759
|
+
const page = this.current - 1;
|
|
6760
|
+
if (page > 0) {
|
|
6761
|
+
this.current = page;
|
|
6762
|
+
this.handleClick('previous');
|
|
6763
|
+
}
|
|
6812
6764
|
}
|
|
6813
6765
|
/**
|
|
6814
|
-
* @description
|
|
6815
|
-
* @summary
|
|
6816
|
-
*
|
|
6817
|
-
*
|
|
6818
|
-
* popover with the triggering event, and opens the action menu. The menu typically contains
|
|
6819
|
-
* available CRUD operations for the item.
|
|
6766
|
+
* @description Navigates to a specific page number.
|
|
6767
|
+
* @summary Updates the current page to the specified page number and triggers
|
|
6768
|
+
* the click event handler with the appropriate direction. This method is typically
|
|
6769
|
+
* called when the user clicks directly on a page number in the pagination UI.
|
|
6820
6770
|
*
|
|
6821
|
-
* @param {
|
|
6822
|
-
* @
|
|
6771
|
+
* @param {number | null} page - The page number to navigate to
|
|
6772
|
+
* @returns {void}
|
|
6823
6773
|
*
|
|
6824
6774
|
* @mermaid
|
|
6825
6775
|
* sequenceDiagram
|
|
6826
6776
|
* participant U as User
|
|
6827
|
-
* participant
|
|
6828
|
-
* participant P as Popover
|
|
6829
|
-
* participant A as Accessibility
|
|
6777
|
+
* participant P as PaginationComponent
|
|
6830
6778
|
*
|
|
6831
|
-
* U->>
|
|
6832
|
-
*
|
|
6833
|
-
*
|
|
6834
|
-
*
|
|
6835
|
-
*
|
|
6836
|
-
*
|
|
6779
|
+
* U->>P: Click page number
|
|
6780
|
+
* P->>P: navigate(page)
|
|
6781
|
+
* alt page is not null and different from current
|
|
6782
|
+
* P->>P: Determine direction (next/previous)
|
|
6783
|
+
* P->>P: handleClick(direction, page)
|
|
6784
|
+
* end
|
|
6837
6785
|
*
|
|
6838
|
-
* @memberOf
|
|
6786
|
+
* @memberOf PaginationComponent
|
|
6839
6787
|
*/
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
removeFocusTrap();
|
|
6844
|
-
this.actionMenuComponent.event = event;
|
|
6845
|
-
this.actionMenuOpen = true;
|
|
6788
|
+
navigate(page) {
|
|
6789
|
+
if (page !== null && this.current !== page)
|
|
6790
|
+
this.handleClick(page > this.current ? 'next' : 'previous', page);
|
|
6846
6791
|
}
|
|
6847
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
6848
|
-
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" }] }); }
|
|
6849
|
-
}
|
|
6850
|
-
|
|
6851
|
-
Dynamic(),
|
|
6852
|
-
__metadata("design:paramtypes", [])
|
|
6853
|
-
], ListItemComponent);
|
|
6854
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ListItemComponent, decorators: [{
|
|
6792
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
6793
|
+
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" }] }); }
|
|
6794
|
+
}
|
|
6795
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: PaginationComponent, decorators: [{
|
|
6855
6796
|
type: Component,
|
|
6856
|
-
args: [{ selector: 'ngx-decaf-
|
|
6797
|
+
args: [{ selector: 'ngx-decaf-pagination', imports: [
|
|
6857
6798
|
TranslatePipe,
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
IonIcon,
|
|
6865
|
-
IonLabel,
|
|
6866
|
-
IonButton,
|
|
6867
|
-
IonContent,
|
|
6868
|
-
IonPopover
|
|
6869
|
-
], 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"] }]
|
|
6870
|
-
}], ctorParameters: () => [], propDecorators: { actionMenuComponent: [{
|
|
6871
|
-
type: ViewChild,
|
|
6872
|
-
args: ['actionMenuComponent']
|
|
6873
|
-
}], lines: [{
|
|
6874
|
-
type: Input
|
|
6875
|
-
}], item: [{
|
|
6876
|
-
type: Input
|
|
6877
|
-
}], icon: [{
|
|
6878
|
-
type: Input
|
|
6879
|
-
}], iconSlot: [{
|
|
6880
|
-
type: Input
|
|
6881
|
-
}], button: [{
|
|
6882
|
-
type: Input
|
|
6883
|
-
}], title: [{
|
|
6884
|
-
type: Input
|
|
6885
|
-
}], description: [{
|
|
6886
|
-
type: Input
|
|
6887
|
-
}], info: [{
|
|
6888
|
-
type: Input
|
|
6889
|
-
}], subinfo: [{
|
|
6799
|
+
IonIcon
|
|
6800
|
+
], 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"] }]
|
|
6801
|
+
}], ctorParameters: () => [], propDecorators: { totalPages: [{
|
|
6802
|
+
type: Input,
|
|
6803
|
+
args: [{ required: true }]
|
|
6804
|
+
}], current: [{
|
|
6890
6805
|
type: Input
|
|
6891
6806
|
}], clickEvent: [{
|
|
6892
6807
|
type: Output
|
|
6893
|
-
}], enableSlideItems: [{
|
|
6894
|
-
type: HostListener,
|
|
6895
|
-
args: ['window:resize', ['$event']]
|
|
6896
6808
|
}] } });
|
|
6897
6809
|
|
|
6898
6810
|
/**
|
|
6899
|
-
* @description A
|
|
6900
|
-
* @summary This component provides a
|
|
6901
|
-
*
|
|
6902
|
-
*
|
|
6811
|
+
* @description A versatile list component that supports various data display modes.
|
|
6812
|
+
* @summary This component provides a flexible way to display lists of data with support
|
|
6813
|
+
* for infinite scrolling, pagination, searching, and custom item rendering. It can fetch
|
|
6814
|
+
* data from various sources including models, functions, or direct data input.
|
|
6903
6815
|
*
|
|
6904
|
-
* The component
|
|
6905
|
-
*
|
|
6906
|
-
*
|
|
6816
|
+
* The component supports two main display types:
|
|
6817
|
+
* 1. Infinite scrolling - Loads more data as the user scrolls
|
|
6818
|
+
* 2. Pagination - Displays data in pages with navigation controls
|
|
6819
|
+
*
|
|
6820
|
+
* Additional features include:
|
|
6821
|
+
* - Pull-to-refresh functionality
|
|
6822
|
+
* - Search filtering
|
|
6823
|
+
* - Empty state customization
|
|
6824
|
+
* - Custom item rendering
|
|
6825
|
+
* - Event emission for interactions
|
|
6907
6826
|
*
|
|
6908
6827
|
* @mermaid
|
|
6909
6828
|
* sequenceDiagram
|
|
6910
6829
|
* participant U as User
|
|
6911
|
-
* participant
|
|
6912
|
-
* participant
|
|
6830
|
+
* participant L as ListComponent
|
|
6831
|
+
* participant D as Data Source
|
|
6832
|
+
* participant E as External Components
|
|
6913
6833
|
*
|
|
6914
|
-
* U->>
|
|
6915
|
-
*
|
|
6916
|
-
*
|
|
6917
|
-
*
|
|
6834
|
+
* U->>L: Initialize component
|
|
6835
|
+
* L->>L: ngOnInit()
|
|
6836
|
+
* L->>D: Request initial data
|
|
6837
|
+
* D-->>L: Return data
|
|
6838
|
+
* L->>L: Process and display data
|
|
6918
6839
|
*
|
|
6919
|
-
*
|
|
6920
|
-
*
|
|
6921
|
-
*
|
|
6922
|
-
*
|
|
6840
|
+
* alt User scrolls (Infinite mode)
|
|
6841
|
+
* U->>L: Scroll to bottom
|
|
6842
|
+
* L->>D: Request more data
|
|
6843
|
+
* D-->>L: Return additional data
|
|
6844
|
+
* L->>L: Append to existing data
|
|
6845
|
+
* else User changes page (Paginated mode)
|
|
6846
|
+
* U->>L: Click page number
|
|
6847
|
+
* L->>L: handlePaginate()
|
|
6848
|
+
* L->>D: Request data for page
|
|
6849
|
+
* D-->>L: Return page data
|
|
6850
|
+
* L->>L: Replace displayed data
|
|
6851
|
+
* end
|
|
6923
6852
|
*
|
|
6924
|
-
*
|
|
6925
|
-
*
|
|
6926
|
-
*
|
|
6927
|
-
*
|
|
6853
|
+
* alt User searches
|
|
6854
|
+
* U->>L: Enter search term
|
|
6855
|
+
* L->>L: handleSearch()
|
|
6856
|
+
* L->>D: Filter data by search term
|
|
6857
|
+
* D-->>L: Return filtered data
|
|
6858
|
+
* L->>L: Update displayed data
|
|
6859
|
+
* end
|
|
6860
|
+
*
|
|
6861
|
+
* alt User clicks item
|
|
6862
|
+
* U->>L: Click list item
|
|
6863
|
+
* L->>L: handleClick()
|
|
6864
|
+
* L->>E: Emit clickEvent
|
|
6865
|
+
* end
|
|
6928
6866
|
*
|
|
6929
6867
|
* @example
|
|
6930
|
-
* <ngx-decaf-
|
|
6931
|
-
* [
|
|
6932
|
-
* [
|
|
6933
|
-
*
|
|
6934
|
-
*
|
|
6868
|
+
* <ngx-decaf-list
|
|
6869
|
+
* [source]="dataSource"
|
|
6870
|
+
* [limit]="10"
|
|
6871
|
+
* [type]="'infinite'"
|
|
6872
|
+
* [showSearchbar]="true"
|
|
6873
|
+
* (clickEvent)="handleItemClick($event)"
|
|
6874
|
+
* (refreshEvent)="handleRefresh($event)">
|
|
6875
|
+
* </ngx-decaf-list>
|
|
6935
6876
|
*
|
|
6936
6877
|
* @extends {NgxBaseComponent}
|
|
6937
6878
|
* @implements {OnInit}
|
|
6938
6879
|
*/
|
|
6939
|
-
class
|
|
6880
|
+
let ListComponent = class ListComponent extends NgxBaseComponent {
|
|
6940
6881
|
/**
|
|
6941
|
-
* @
|
|
6942
|
-
* @
|
|
6943
|
-
*
|
|
6882
|
+
* @description Initializes a new instance of the ListComponent.
|
|
6883
|
+
* @summary Creates a new ListComponent and sets up the base component with the appropriate
|
|
6884
|
+
* component name. This constructor is called when Angular instantiates the component and
|
|
6885
|
+
* before any input properties are set. It passes the component name to the parent class
|
|
6886
|
+
* constructor to enable proper localization and component identification.
|
|
6887
|
+
*
|
|
6888
|
+
* The constructor is intentionally minimal, with most initialization logic deferred to
|
|
6889
|
+
* the ngOnInit lifecycle hook. This follows Angular best practices by keeping the constructor
|
|
6890
|
+
* focused on dependency injection and basic setup, while complex initialization that depends
|
|
6891
|
+
* on input properties is handled in ngOnInit.
|
|
6892
|
+
*
|
|
6893
|
+
* @memberOf ListComponent
|
|
6944
6894
|
*/
|
|
6945
6895
|
constructor() {
|
|
6946
|
-
super("
|
|
6896
|
+
super("ListComponent");
|
|
6897
|
+
/**
|
|
6898
|
+
* @description The display mode for the list component.
|
|
6899
|
+
* @summary Determines how the list data is loaded and displayed. Options include:
|
|
6900
|
+
* - INFINITE: Loads more data as the user scrolls (infinite scrolling)
|
|
6901
|
+
* - PAGINATED: Displays data in pages with navigation controls
|
|
6902
|
+
*
|
|
6903
|
+
* @type {ListComponentsTypes}
|
|
6904
|
+
* @default ListComponentsTypes.INFINITE
|
|
6905
|
+
* @memberOf ListComponent
|
|
6906
|
+
*/
|
|
6907
|
+
this.type = ListComponentsTypes.INFINITE;
|
|
6947
6908
|
/**
|
|
6948
6909
|
* @description Controls whether the component uses translation services.
|
|
6949
6910
|
* @summary When set to true, the component will attempt to use translation services
|
|
6950
|
-
* for any text content. This allows for internationalization of the
|
|
6911
|
+
* for any text content. This allows for internationalization of the list component.
|
|
6951
6912
|
*
|
|
6952
6913
|
* @type {StringOrBoolean}
|
|
6953
6914
|
* @default true
|
|
6954
|
-
* @memberOf
|
|
6915
|
+
* @memberOf ListComponent
|
|
6955
6916
|
*/
|
|
6956
6917
|
this.translatable = true;
|
|
6957
6918
|
/**
|
|
6958
|
-
* @description
|
|
6959
|
-
* @summary
|
|
6960
|
-
* to
|
|
6919
|
+
* @description Controls the visibility of the search bar.
|
|
6920
|
+
* @summary When set to true, displays a search bar at the top of the list that allows
|
|
6921
|
+
* users to filter the list items. The search functionality works by filtering the
|
|
6922
|
+
* existing data or by triggering a new data fetch with search parameters.
|
|
6923
|
+
*
|
|
6924
|
+
* @type {StringOrBoolean}
|
|
6925
|
+
* @default true
|
|
6926
|
+
* @memberOf ListComponent
|
|
6927
|
+
*/
|
|
6928
|
+
this.showSearchbar = true;
|
|
6929
|
+
/**
|
|
6930
|
+
* @description Direct data input for the list component.
|
|
6931
|
+
* @summary Provides a way to directly pass data to the list component instead of
|
|
6932
|
+
* fetching it from a source. When both data and source are provided, the component
|
|
6933
|
+
* will use the source to fetch data only if the data array is empty.
|
|
6934
|
+
*
|
|
6935
|
+
* @type {KeyValue[] | undefined}
|
|
6936
|
+
* @default undefined
|
|
6937
|
+
* @memberOf ListComponent
|
|
6938
|
+
*/
|
|
6939
|
+
this.data = undefined;
|
|
6940
|
+
/**
|
|
6941
|
+
* @description The starting index for data fetching.
|
|
6942
|
+
* @summary Specifies the index from which to start fetching data. This is used
|
|
6943
|
+
* for pagination and infinite scrolling to determine which subset of data to load.
|
|
6961
6944
|
*
|
|
6962
6945
|
* @type {number}
|
|
6963
|
-
* @default
|
|
6964
|
-
* @memberOf
|
|
6946
|
+
* @default 0
|
|
6947
|
+
* @memberOf ListComponent
|
|
6965
6948
|
*/
|
|
6966
|
-
this.
|
|
6949
|
+
this.start = 0;
|
|
6967
6950
|
/**
|
|
6968
|
-
* @description
|
|
6969
|
-
* @summary
|
|
6970
|
-
*
|
|
6971
|
-
* about the navigation direction and the target page number.
|
|
6951
|
+
* @description The number of items to fetch per page or load operation.
|
|
6952
|
+
* @summary Determines how many items are loaded at once during pagination or
|
|
6953
|
+
* infinite scrolling. This affects the size of data chunks requested from the source.
|
|
6972
6954
|
*
|
|
6973
|
-
* @type {
|
|
6974
|
-
* @
|
|
6975
|
-
|
|
6976
|
-
this.clickEvent = new EventEmitter();
|
|
6977
|
-
addIcons({ chevronBackOutline, chevronForwardOutline });
|
|
6978
|
-
}
|
|
6979
|
-
/**
|
|
6980
|
-
* @description Initializes the component after Angular sets the input properties.
|
|
6981
|
-
* @summary Sets up the component by initializing the locale settings based on the
|
|
6982
|
-
* translatable property, generating the page numbers based on the total pages and
|
|
6983
|
-
* current page, and storing the last page number for boundary checking.
|
|
6984
|
-
*
|
|
6985
|
-
* @mermaid
|
|
6986
|
-
* sequenceDiagram
|
|
6987
|
-
* participant A as Angular Lifecycle
|
|
6988
|
-
* participant P as PaginationComponent
|
|
6989
|
-
*
|
|
6990
|
-
* A->>P: ngOnInit()
|
|
6991
|
-
* P->>P: getLocale(translatable)
|
|
6992
|
-
* P->>P: Set locale
|
|
6993
|
-
* P->>P: getPages(data, current)
|
|
6994
|
-
* P->>P: Set pages array
|
|
6995
|
-
* P->>P: Set last page number
|
|
6996
|
-
*
|
|
6997
|
-
* @returns {void}
|
|
6998
|
-
* @memberOf PaginationComponent
|
|
6999
|
-
*/
|
|
7000
|
-
ngOnInit() {
|
|
7001
|
-
this.locale = this.getLocale(this.translatable);
|
|
7002
|
-
this.pages = this.getPages(this.totalPages, this.current);
|
|
7003
|
-
this.last = this.totalPages;
|
|
7004
|
-
}
|
|
7005
|
-
/**
|
|
7006
|
-
* @description Handles click events on pagination controls.
|
|
7007
|
-
* @summary Processes user interactions with the pagination component, updating the
|
|
7008
|
-
* current page if specified and emitting an event with navigation details. This method
|
|
7009
|
-
* is called when users click on page numbers or navigation buttons.
|
|
7010
|
-
*
|
|
7011
|
-
* @param {('next' | 'previous')} direction - The direction of navigation
|
|
7012
|
-
* @param {number} [page] - Optional page number to navigate to directly
|
|
7013
|
-
* @returns {void}
|
|
7014
|
-
*
|
|
7015
|
-
* @mermaid
|
|
7016
|
-
* sequenceDiagram
|
|
7017
|
-
* participant U as User
|
|
7018
|
-
* participant P as PaginationComponent
|
|
7019
|
-
* participant E as External Component
|
|
7020
|
-
*
|
|
7021
|
-
* U->>P: Click pagination control
|
|
7022
|
-
* P->>P: handleClick(direction, page?)
|
|
7023
|
-
* alt page is provided
|
|
7024
|
-
* P->>P: Update current page
|
|
7025
|
-
* end
|
|
7026
|
-
* P->>E: Emit clickEvent with direction and page
|
|
7027
|
-
*
|
|
7028
|
-
* @memberOf PaginationComponent
|
|
7029
|
-
*/
|
|
7030
|
-
handleClick(direction, page) {
|
|
7031
|
-
if (page)
|
|
7032
|
-
this.current = page;
|
|
7033
|
-
this.clickEvent.emit({
|
|
7034
|
-
name: EventConstants.CLICK,
|
|
7035
|
-
data: {
|
|
7036
|
-
direction,
|
|
7037
|
-
page: this.current
|
|
7038
|
-
},
|
|
7039
|
-
component: this.componentName
|
|
7040
|
-
});
|
|
7041
|
-
}
|
|
7042
|
-
/**
|
|
7043
|
-
* @description Generates the array of page objects for display.
|
|
7044
|
-
* @summary Creates an array of page objects based on the total number of pages and
|
|
7045
|
-
* the current page. For small page counts (≤5), all pages are shown. For larger page
|
|
7046
|
-
* counts, a subset is shown with ellipses to indicate skipped pages. This ensures
|
|
7047
|
-
* the pagination UI remains clean and usable even with many pages.
|
|
7048
|
-
*
|
|
7049
|
-
* @param {number} total - The total number of pages
|
|
7050
|
-
* @param {number} [current] - The current active page (defaults to this.current)
|
|
7051
|
-
* @returns {KeyValue[]} Array of page objects with index and text properties
|
|
7052
|
-
*
|
|
7053
|
-
* @mermaid
|
|
7054
|
-
* flowchart TD
|
|
7055
|
-
* A[Start] --> B{total <= 5?}
|
|
7056
|
-
* B -->|Yes| C[Show all pages]
|
|
7057
|
-
* B -->|No| D[Show first page]
|
|
7058
|
-
* D --> E[Show last pages]
|
|
7059
|
-
* E --> F[Add ellipses for skipped pages]
|
|
7060
|
-
* C --> G[Return pages array]
|
|
7061
|
-
* F --> G
|
|
7062
|
-
*
|
|
7063
|
-
* @memberOf PaginationComponent
|
|
7064
|
-
*/
|
|
7065
|
-
getPages(total, current) {
|
|
7066
|
-
if (!current)
|
|
7067
|
-
current = this.current;
|
|
7068
|
-
const pages = [];
|
|
7069
|
-
function getPage(index, text = '', clazz = 'button') {
|
|
7070
|
-
if (pages.some(item => item['index'] === index))
|
|
7071
|
-
return;
|
|
7072
|
-
pages.push({ index, text: index != null ? index.toString().padStart(2, '0') : text, class: clazz });
|
|
7073
|
-
}
|
|
7074
|
-
if (total <= 5) {
|
|
7075
|
-
for (let i = 1; i <= total; i++)
|
|
7076
|
-
getPage(i);
|
|
7077
|
-
}
|
|
7078
|
-
else {
|
|
7079
|
-
// Adiciona os dois primeiros
|
|
7080
|
-
getPage(1);
|
|
7081
|
-
getPage(2);
|
|
7082
|
-
// Adiciona "..." entre os blocos
|
|
7083
|
-
if (current && current > 3)
|
|
7084
|
-
getPage(null, '...');
|
|
7085
|
-
// Adiciona a página atual (se estiver no meio)
|
|
7086
|
-
if (current && current > 2 && current < total - 1)
|
|
7087
|
-
getPage(current);
|
|
7088
|
-
// Adiciona "..." entre os blocos
|
|
7089
|
-
if (current && current < total - 2)
|
|
7090
|
-
getPage(null, '...', 'separator');
|
|
7091
|
-
// Adiciona os dois últimos
|
|
7092
|
-
getPage(total - 1);
|
|
7093
|
-
getPage(total);
|
|
7094
|
-
}
|
|
7095
|
-
return pages;
|
|
7096
|
-
}
|
|
7097
|
-
/**
|
|
7098
|
-
* @description Gets the current active page number.
|
|
7099
|
-
* @summary Returns the current page number that is active in the pagination component.
|
|
7100
|
-
* This method provides a way to access the current page state from outside the component.
|
|
7101
|
-
*
|
|
7102
|
-
* @returns {number} The current page number
|
|
7103
|
-
* @memberOf PaginationComponent
|
|
7104
|
-
*/
|
|
7105
|
-
getCurrent() {
|
|
7106
|
-
return this.current;
|
|
7107
|
-
}
|
|
7108
|
-
/**
|
|
7109
|
-
* @description Navigates to the next page.
|
|
7110
|
-
* @summary Increments the current page number if not at the last page and triggers
|
|
7111
|
-
* the click event handler with 'next' direction. This method is typically called
|
|
7112
|
-
* when the user clicks on the "next" button in the pagination UI.
|
|
7113
|
-
*
|
|
7114
|
-
* @returns {void}
|
|
7115
|
-
*
|
|
7116
|
-
* @mermaid
|
|
7117
|
-
* sequenceDiagram
|
|
7118
|
-
* participant U as User
|
|
7119
|
-
* participant P as PaginationComponent
|
|
7120
|
-
*
|
|
7121
|
-
* U->>P: Click next button
|
|
7122
|
-
* P->>P: next()
|
|
7123
|
-
* alt page <= max pages
|
|
7124
|
-
* P->>P: Increment current page
|
|
7125
|
-
* P->>P: handleClick('next')
|
|
7126
|
-
* end
|
|
7127
|
-
*
|
|
7128
|
-
* @memberOf PaginationComponent
|
|
7129
|
-
*/
|
|
7130
|
-
next() {
|
|
7131
|
-
const page = this.current + 1;
|
|
7132
|
-
if (page <= Object.keys(this.pages)?.length || 0) {
|
|
7133
|
-
this.current = page;
|
|
7134
|
-
this.handleClick('next');
|
|
7135
|
-
}
|
|
7136
|
-
}
|
|
7137
|
-
/**
|
|
7138
|
-
* @description Navigates to the previous page.
|
|
7139
|
-
* @summary Decrements the current page number if not at the first page and triggers
|
|
7140
|
-
* the click event handler with 'previous' direction. This method is typically called
|
|
7141
|
-
* when the user clicks on the "previous" button in the pagination UI.
|
|
7142
|
-
*
|
|
7143
|
-
* @returns {void}
|
|
7144
|
-
*
|
|
7145
|
-
* @mermaid
|
|
7146
|
-
* sequenceDiagram
|
|
7147
|
-
* participant U as User
|
|
7148
|
-
* participant P as PaginationComponent
|
|
7149
|
-
*
|
|
7150
|
-
* U->>P: Click previous button
|
|
7151
|
-
* P->>P: previous()
|
|
7152
|
-
* alt page > 0
|
|
7153
|
-
* P->>P: Decrement current page
|
|
7154
|
-
* P->>P: handleClick('previous')
|
|
7155
|
-
* end
|
|
7156
|
-
*
|
|
7157
|
-
* @memberOf PaginationComponent
|
|
7158
|
-
*/
|
|
7159
|
-
previous() {
|
|
7160
|
-
const page = this.current - 1;
|
|
7161
|
-
if (page > 0) {
|
|
7162
|
-
this.current = page;
|
|
7163
|
-
this.handleClick('previous');
|
|
7164
|
-
}
|
|
7165
|
-
}
|
|
7166
|
-
/**
|
|
7167
|
-
* @description Navigates to a specific page number.
|
|
7168
|
-
* @summary Updates the current page to the specified page number and triggers
|
|
7169
|
-
* the click event handler with the appropriate direction. This method is typically
|
|
7170
|
-
* called when the user clicks directly on a page number in the pagination UI.
|
|
7171
|
-
*
|
|
7172
|
-
* @param {number | null} page - The page number to navigate to
|
|
7173
|
-
* @returns {void}
|
|
7174
|
-
*
|
|
7175
|
-
* @mermaid
|
|
7176
|
-
* sequenceDiagram
|
|
7177
|
-
* participant U as User
|
|
7178
|
-
* participant P as PaginationComponent
|
|
7179
|
-
*
|
|
7180
|
-
* U->>P: Click page number
|
|
7181
|
-
* P->>P: navigate(page)
|
|
7182
|
-
* alt page is not null and different from current
|
|
7183
|
-
* P->>P: Determine direction (next/previous)
|
|
7184
|
-
* P->>P: handleClick(direction, page)
|
|
7185
|
-
* end
|
|
7186
|
-
*
|
|
7187
|
-
* @memberOf PaginationComponent
|
|
7188
|
-
*/
|
|
7189
|
-
navigate(page) {
|
|
7190
|
-
if (page !== null && this.current !== page)
|
|
7191
|
-
this.handleClick(page > this.current ? 'next' : 'previous', page);
|
|
7192
|
-
}
|
|
7193
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7194
|
-
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"] }] }); }
|
|
7195
|
-
}
|
|
7196
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: PaginationComponent, decorators: [{
|
|
7197
|
-
type: Component,
|
|
7198
|
-
args: [{ selector: 'ngx-decaf-pagination', imports: [
|
|
7199
|
-
TranslatePipe,
|
|
7200
|
-
IonIcon
|
|
7201
|
-
], 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"] }]
|
|
7202
|
-
}], ctorParameters: () => [], propDecorators: { totalPages: [{
|
|
7203
|
-
type: Input,
|
|
7204
|
-
args: [{ required: true }]
|
|
7205
|
-
}], current: [{
|
|
7206
|
-
type: Input
|
|
7207
|
-
}], clickEvent: [{
|
|
7208
|
-
type: Output
|
|
7209
|
-
}] } });
|
|
7210
|
-
|
|
7211
|
-
/**
|
|
7212
|
-
* @description A versatile list component that supports various data display modes.
|
|
7213
|
-
* @summary This component provides a flexible way to display lists of data with support
|
|
7214
|
-
* for infinite scrolling, pagination, searching, and custom item rendering. It can fetch
|
|
7215
|
-
* data from various sources including models, functions, or direct data input.
|
|
7216
|
-
*
|
|
7217
|
-
* The component supports two main display types:
|
|
7218
|
-
* 1. Infinite scrolling - Loads more data as the user scrolls
|
|
7219
|
-
* 2. Pagination - Displays data in pages with navigation controls
|
|
7220
|
-
*
|
|
7221
|
-
* Additional features include:
|
|
7222
|
-
* - Pull-to-refresh functionality
|
|
7223
|
-
* - Search filtering
|
|
7224
|
-
* - Empty state customization
|
|
7225
|
-
* - Custom item rendering
|
|
7226
|
-
* - Event emission for interactions
|
|
7227
|
-
*
|
|
7228
|
-
* @mermaid
|
|
7229
|
-
* sequenceDiagram
|
|
7230
|
-
* participant U as User
|
|
7231
|
-
* participant L as ListComponent
|
|
7232
|
-
* participant D as Data Source
|
|
7233
|
-
* participant E as External Components
|
|
7234
|
-
*
|
|
7235
|
-
* U->>L: Initialize component
|
|
7236
|
-
* L->>L: ngOnInit()
|
|
7237
|
-
* L->>D: Request initial data
|
|
7238
|
-
* D-->>L: Return data
|
|
7239
|
-
* L->>L: Process and display data
|
|
7240
|
-
*
|
|
7241
|
-
* alt User scrolls (Infinite mode)
|
|
7242
|
-
* U->>L: Scroll to bottom
|
|
7243
|
-
* L->>D: Request more data
|
|
7244
|
-
* D-->>L: Return additional data
|
|
7245
|
-
* L->>L: Append to existing data
|
|
7246
|
-
* else User changes page (Paginated mode)
|
|
7247
|
-
* U->>L: Click page number
|
|
7248
|
-
* L->>L: handlePaginate()
|
|
7249
|
-
* L->>D: Request data for page
|
|
7250
|
-
* D-->>L: Return page data
|
|
7251
|
-
* L->>L: Replace displayed data
|
|
7252
|
-
* end
|
|
7253
|
-
*
|
|
7254
|
-
* alt User searches
|
|
7255
|
-
* U->>L: Enter search term
|
|
7256
|
-
* L->>L: handleSearch()
|
|
7257
|
-
* L->>D: Filter data by search term
|
|
7258
|
-
* D-->>L: Return filtered data
|
|
7259
|
-
* L->>L: Update displayed data
|
|
7260
|
-
* end
|
|
7261
|
-
*
|
|
7262
|
-
* alt User clicks item
|
|
7263
|
-
* U->>L: Click list item
|
|
7264
|
-
* L->>L: handleClick()
|
|
7265
|
-
* L->>E: Emit clickEvent
|
|
7266
|
-
* end
|
|
7267
|
-
*
|
|
7268
|
-
* @example
|
|
7269
|
-
* <ngx-decaf-list
|
|
7270
|
-
* [source]="dataSource"
|
|
7271
|
-
* [limit]="10"
|
|
7272
|
-
* [type]="'infinite'"
|
|
7273
|
-
* [showSearchbar]="true"
|
|
7274
|
-
* (clickEvent)="handleItemClick($event)"
|
|
7275
|
-
* (refreshEvent)="handleRefresh($event)">
|
|
7276
|
-
* </ngx-decaf-list>
|
|
7277
|
-
*
|
|
7278
|
-
* @extends {NgxBaseComponent}
|
|
7279
|
-
* @implements {OnInit}
|
|
7280
|
-
*/
|
|
7281
|
-
let ListComponent = class ListComponent extends NgxBaseComponent {
|
|
7282
|
-
/**
|
|
7283
|
-
* @description Initializes a new instance of the ListComponent.
|
|
7284
|
-
* @summary Creates a new ListComponent and sets up the base component with the appropriate
|
|
7285
|
-
* component name. This constructor is called when Angular instantiates the component and
|
|
7286
|
-
* before any input properties are set. It passes the component name to the parent class
|
|
7287
|
-
* constructor to enable proper localization and component identification.
|
|
7288
|
-
*
|
|
7289
|
-
* The constructor is intentionally minimal, with most initialization logic deferred to
|
|
7290
|
-
* the ngOnInit lifecycle hook. This follows Angular best practices by keeping the constructor
|
|
7291
|
-
* focused on dependency injection and basic setup, while complex initialization that depends
|
|
7292
|
-
* on input properties is handled in ngOnInit.
|
|
7293
|
-
*
|
|
7294
|
-
* @memberOf ListComponent
|
|
7295
|
-
*/
|
|
7296
|
-
constructor() {
|
|
7297
|
-
super("ListComponent");
|
|
7298
|
-
/**
|
|
7299
|
-
* @description The display mode for the list component.
|
|
7300
|
-
* @summary Determines how the list data is loaded and displayed. Options include:
|
|
7301
|
-
* - INFINITE: Loads more data as the user scrolls (infinite scrolling)
|
|
7302
|
-
* - PAGINATED: Displays data in pages with navigation controls
|
|
7303
|
-
*
|
|
7304
|
-
* @type {ListComponentsTypes}
|
|
7305
|
-
* @default ListComponentsTypes.INFINITE
|
|
7306
|
-
* @memberOf ListComponent
|
|
7307
|
-
*/
|
|
7308
|
-
this.type = ListComponentsTypes.INFINITE;
|
|
7309
|
-
/**
|
|
7310
|
-
* @description Controls whether the component uses translation services.
|
|
7311
|
-
* @summary When set to true, the component will attempt to use translation services
|
|
7312
|
-
* for any text content. This allows for internationalization of the list component.
|
|
7313
|
-
*
|
|
7314
|
-
* @type {StringOrBoolean}
|
|
7315
|
-
* @default true
|
|
7316
|
-
* @memberOf ListComponent
|
|
7317
|
-
*/
|
|
7318
|
-
this.translatable = true;
|
|
7319
|
-
/**
|
|
7320
|
-
* @description Controls the visibility of the search bar.
|
|
7321
|
-
* @summary When set to true, displays a search bar at the top of the list that allows
|
|
7322
|
-
* users to filter the list items. The search functionality works by filtering the
|
|
7323
|
-
* existing data or by triggering a new data fetch with search parameters.
|
|
7324
|
-
*
|
|
7325
|
-
* @type {StringOrBoolean}
|
|
7326
|
-
* @default true
|
|
7327
|
-
* @memberOf ListComponent
|
|
7328
|
-
*/
|
|
7329
|
-
this.showSearchbar = true;
|
|
7330
|
-
/**
|
|
7331
|
-
* @description Direct data input for the list component.
|
|
7332
|
-
* @summary Provides a way to directly pass data to the list component instead of
|
|
7333
|
-
* fetching it from a source. When both data and source are provided, the component
|
|
7334
|
-
* will use the source to fetch data only if the data array is empty.
|
|
7335
|
-
*
|
|
7336
|
-
* @type {KeyValue[] | undefined}
|
|
7337
|
-
* @default undefined
|
|
7338
|
-
* @memberOf ListComponent
|
|
7339
|
-
*/
|
|
7340
|
-
this.data = undefined;
|
|
7341
|
-
/**
|
|
7342
|
-
* @description The starting index for data fetching.
|
|
7343
|
-
* @summary Specifies the index from which to start fetching data. This is used
|
|
7344
|
-
* for pagination and infinite scrolling to determine which subset of data to load.
|
|
7345
|
-
*
|
|
7346
|
-
* @type {number}
|
|
7347
|
-
* @default 0
|
|
7348
|
-
* @memberOf ListComponent
|
|
7349
|
-
*/
|
|
7350
|
-
this.start = 0;
|
|
7351
|
-
/**
|
|
7352
|
-
* @description The number of items to fetch per page or load operation.
|
|
7353
|
-
* @summary Determines how many items are loaded at once during pagination or
|
|
7354
|
-
* infinite scrolling. This affects the size of data chunks requested from the source.
|
|
7355
|
-
*
|
|
7356
|
-
* @type {number}
|
|
7357
|
-
* @default 10
|
|
7358
|
-
* @memberOf ListComponent
|
|
6955
|
+
* @type {number}
|
|
6956
|
+
* @default 10
|
|
6957
|
+
* @memberOf ListComponent
|
|
7359
6958
|
*/
|
|
7360
6959
|
this.limit = 10;
|
|
7361
6960
|
/**
|
|
@@ -7588,842 +7187,1221 @@ let ListComponent = class ListComponent extends NgxBaseComponent {
|
|
|
7588
7187
|
*/
|
|
7589
7188
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7590
7189
|
this.observerSubjet = new Subject();
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
|
|
7597
|
-
|
|
7598
|
-
|
|
7599
|
-
|
|
7600
|
-
|
|
7190
|
+
}
|
|
7191
|
+
/**
|
|
7192
|
+
* @description Initializes the component after Angular sets the input properties.
|
|
7193
|
+
* @summary Sets up the component by initializing event subscriptions, processing boolean
|
|
7194
|
+
* inputs, and loading the initial data. This method prepares the component for user
|
|
7195
|
+
* interaction by ensuring all properties are properly initialized and data is loaded.
|
|
7196
|
+
*
|
|
7197
|
+
* @returns {Promise<void>}
|
|
7198
|
+
*
|
|
7199
|
+
* @mermaid
|
|
7200
|
+
* sequenceDiagram
|
|
7201
|
+
* participant A as Angular Lifecycle
|
|
7202
|
+
* participant L as ListComponent
|
|
7203
|
+
* participant D as Data Source
|
|
7204
|
+
*
|
|
7205
|
+
* A->>L: ngOnInit()
|
|
7206
|
+
* L->>L: Set up click event debouncing
|
|
7207
|
+
* L->>L: Process boolean inputs
|
|
7208
|
+
* L->>L: Configure component based on inputs
|
|
7209
|
+
* L->>L: refresh()
|
|
7210
|
+
* L->>D: Request initial data
|
|
7211
|
+
* D-->>L: Return data
|
|
7212
|
+
* L->>L: Process and display data
|
|
7213
|
+
* L->>L: Configure empty state if needed
|
|
7214
|
+
* L->>L: initialize()
|
|
7215
|
+
*
|
|
7216
|
+
* @memberOf ListComponent
|
|
7217
|
+
*/
|
|
7218
|
+
async ngOnInit() {
|
|
7601
7219
|
this.observer = { refresh: async (...args) => this.observeRepository(...args) };
|
|
7220
|
+
this.clickItemSubject.pipe(debounceTime(100)).subscribe(event => this.clickEventEmit(event));
|
|
7221
|
+
this.observerSubjet.pipe(debounceTime(100)).subscribe(args => this.handleObserveEvent(args[0], args[1], args[2]));
|
|
7222
|
+
this.enableFilter = stringToBoolean(this.enableFilter);
|
|
7223
|
+
this.limit = Number(this.limit);
|
|
7224
|
+
this.start = Number(this.start);
|
|
7225
|
+
this.inset = stringToBoolean(this.inset);
|
|
7226
|
+
this.showRefresher = stringToBoolean(this.showRefresher);
|
|
7227
|
+
this.loadMoreData = stringToBoolean(this.loadMoreData);
|
|
7228
|
+
this.showSearchbar = stringToBoolean(this.showSearchbar);
|
|
7229
|
+
this.disableSort = stringToBoolean(this.disableSort);
|
|
7230
|
+
if (typeof this.item?.['tag'] === 'boolean' && this.item?.['tag'] === true)
|
|
7231
|
+
this.item['tag'] = ComponentsTagNames.LIST_ITEM;
|
|
7232
|
+
await this.refresh();
|
|
7233
|
+
if (this.operations.includes(OperationKeys.CREATE) && this.route)
|
|
7234
|
+
this.empty.link = `${this.route}/${OperationKeys.CREATE}`;
|
|
7235
|
+
await this.initialize();
|
|
7236
|
+
if (this.model instanceof Model && this._repository)
|
|
7237
|
+
this._repository.observe(this.observer);
|
|
7238
|
+
}
|
|
7239
|
+
/**
|
|
7240
|
+
* @description Cleans up resources when the component is destroyed.
|
|
7241
|
+
* @summary Performs cleanup operations when the component is being removed from the DOM.
|
|
7242
|
+
* This includes clearing references to models and data to prevent memory leaks.
|
|
7243
|
+
*
|
|
7244
|
+
* @returns {void}
|
|
7245
|
+
* @memberOf ListComponent
|
|
7246
|
+
*/
|
|
7247
|
+
ngOnDestroy() {
|
|
7248
|
+
if (this._repository)
|
|
7249
|
+
this._repository.unObserve(this.observer);
|
|
7250
|
+
this.data = this.model = this._repository = this.paginator = undefined;
|
|
7251
|
+
}
|
|
7252
|
+
/**
|
|
7253
|
+
* @description Handles repository observation events with debouncing.
|
|
7254
|
+
* @summary Processes repository change notifications and routes them appropriately.
|
|
7255
|
+
* For CREATE events with a UID, handles them immediately. For other events,
|
|
7256
|
+
* passes them to the debounced observer subject to prevent excessive updates.
|
|
7257
|
+
*
|
|
7258
|
+
* @param {...unknown[]} args - The repository event arguments including table, event type, and UID
|
|
7259
|
+
* @returns {Promise<void>}
|
|
7260
|
+
* @memberOf ListComponent
|
|
7261
|
+
*/
|
|
7262
|
+
async observeRepository(...args) {
|
|
7263
|
+
const [table, event, uid] = args;
|
|
7264
|
+
if (event === OperationKeys.CREATE && !!uid)
|
|
7265
|
+
return this.handleObserveEvent(table, event, uid);
|
|
7266
|
+
return this.observerSubjet.next(args);
|
|
7267
|
+
}
|
|
7268
|
+
/**
|
|
7269
|
+
* @description Handles specific repository events and updates the list accordingly.
|
|
7270
|
+
* @summary Processes repository change events (CREATE, UPDATE, DELETE) and performs
|
|
7271
|
+
* the appropriate list operations. This includes adding new items, updating existing
|
|
7272
|
+
* ones, or removing deleted items from the list display.
|
|
7273
|
+
*
|
|
7274
|
+
* @param {string} table - The table/model name that changed
|
|
7275
|
+
* @param {OperationKeys} event - The type of operation (CREATE, UPDATE, DELETE)
|
|
7276
|
+
* @param {string | number} uid - The unique identifier of the affected item
|
|
7277
|
+
* @returns {Promise<void>}
|
|
7278
|
+
* @memberOf ListComponent
|
|
7279
|
+
*/
|
|
7280
|
+
async handleObserveEvent(table, event, uid) {
|
|
7281
|
+
if (event === OperationKeys.CREATE) {
|
|
7282
|
+
if (uid) {
|
|
7283
|
+
await this.handleCreate(uid);
|
|
7284
|
+
}
|
|
7285
|
+
else {
|
|
7286
|
+
await this.refresh(true);
|
|
7287
|
+
}
|
|
7288
|
+
}
|
|
7289
|
+
else {
|
|
7290
|
+
if (event === OperationKeys.UPDATE)
|
|
7291
|
+
await this.handleUpdate(uid);
|
|
7292
|
+
if (event === OperationKeys.DELETE)
|
|
7293
|
+
this.handleDelete(uid);
|
|
7294
|
+
this.refreshEventEmit();
|
|
7295
|
+
}
|
|
7296
|
+
}
|
|
7297
|
+
/**
|
|
7298
|
+
* @description Function for tracking items in the list.
|
|
7299
|
+
* @summary Provides a tracking function for the `*ngFor` directive in the component template.
|
|
7300
|
+
* This function is used to identify and control the rendering of items in the list,
|
|
7301
|
+
* preventing duplicate or unnecessary rendering.
|
|
7302
|
+
*
|
|
7303
|
+
* The `trackItemFn` function takes two parameters: `index` (the index of the item in the list)
|
|
7304
|
+
* and `item` (the actual item from the list). It returns the tracking key, which in this case
|
|
7305
|
+
* is the union of the `uid` of the item with the model name.
|
|
7306
|
+
*
|
|
7307
|
+
* @param {number} index - The index of the item in the list.
|
|
7308
|
+
|
|
7309
|
+
* @param {KeyValue | string | number} item - The actual item from the list.
|
|
7310
|
+
* @returns {string | number} The tracking key for the item.
|
|
7311
|
+
* @memberOf ListComponent
|
|
7312
|
+
*/
|
|
7313
|
+
trackItemFn(index, item) {
|
|
7314
|
+
return `${item?.['uid'] || item?.[this.pk]}-${index}`;
|
|
7315
|
+
}
|
|
7316
|
+
/**
|
|
7317
|
+
* Handles the create event from the repository.
|
|
7318
|
+
*
|
|
7319
|
+
* @param {string | number} uid - The ID of the item to create.
|
|
7320
|
+
* @returns {Promise<void>} A promise that resolves when the item is created and added to the list.
|
|
7321
|
+
*/
|
|
7322
|
+
async handleCreate(uid) {
|
|
7323
|
+
const result = await this._repository?.read(uid);
|
|
7324
|
+
const item = this.mapResults([result])[0];
|
|
7325
|
+
this.items = this.data = [item, ...this.items || []];
|
|
7326
|
+
}
|
|
7327
|
+
/**
|
|
7328
|
+
* @description Handles the update event from the repository.
|
|
7329
|
+
* @summary Updates the list item with the specified ID based on the new data.
|
|
7330
|
+
*
|
|
7331
|
+
* @param {string | number} uid - The ID of the item to update
|
|
7332
|
+
* @returns {Promise<void>}
|
|
7333
|
+
* @private
|
|
7334
|
+
* @memberOf ListComponent
|
|
7335
|
+
*/
|
|
7336
|
+
async handleUpdate(uid) {
|
|
7337
|
+
const item = this.itemMapper(await this._repository?.read(uid) || {}, this.mapper);
|
|
7338
|
+
this.data = [];
|
|
7339
|
+
for (const key in this.items) {
|
|
7340
|
+
const child = this.items[key];
|
|
7341
|
+
if (child['uid'] === item['uid']) {
|
|
7342
|
+
this.items[key] = Object.assign({}, child, item);
|
|
7343
|
+
break;
|
|
7344
|
+
}
|
|
7345
|
+
}
|
|
7346
|
+
setTimeout(() => {
|
|
7347
|
+
this.data = [...this.items];
|
|
7348
|
+
}, 0);
|
|
7349
|
+
}
|
|
7350
|
+
/**
|
|
7351
|
+
* @description Removes an item from the list by ID.
|
|
7352
|
+
* @summary Filters out an item with the specified ID from the data array and
|
|
7353
|
+
* refreshes the list display. This is typically used after a delete operation.
|
|
7354
|
+
*
|
|
7355
|
+
* @param {string} uid - The ID of the item to delete
|
|
7356
|
+
* @param {string} pk - The primary key field name
|
|
7357
|
+
* @returns {Promise<void>}
|
|
7358
|
+
*
|
|
7359
|
+
* @memberOf ListComponent
|
|
7360
|
+
*/
|
|
7361
|
+
handleDelete(uid, pk) {
|
|
7362
|
+
if (!pk)
|
|
7363
|
+
pk = this.pk;
|
|
7364
|
+
this.items = this.data?.filter((item) => item['uid'] !== uid) || [];
|
|
7365
|
+
}
|
|
7366
|
+
/**
|
|
7367
|
+
* @description Handles click events from list items.
|
|
7368
|
+
* @summary Listens for global ListItemClickEvent events and passes them to the
|
|
7369
|
+
* debounced click subject. This allows the component to respond to clicks on
|
|
7370
|
+
* list items regardless of where they originate from.
|
|
7371
|
+
*
|
|
7372
|
+
* @param {ListItemCustomEvent | RendererCustomEvent} event - The click event
|
|
7373
|
+
* @returns {void}
|
|
7374
|
+
*
|
|
7375
|
+
* @memberOf ListComponent
|
|
7376
|
+
*/
|
|
7377
|
+
handleClick(event) {
|
|
7378
|
+
this.clickItemSubject.next(event);
|
|
7602
7379
|
}
|
|
7603
7380
|
/**
|
|
7604
|
-
* @description
|
|
7605
|
-
* @summary
|
|
7606
|
-
*
|
|
7607
|
-
*
|
|
7381
|
+
* @description Handles search events from the search bar.
|
|
7382
|
+
* @summary Processes search queries from the search bar component, updating the
|
|
7383
|
+
* displayed data based on the search term. The behavior differs between infinite
|
|
7384
|
+
* and paginated modes to provide the best user experience for each mode.
|
|
7608
7385
|
*
|
|
7386
|
+
* @param {string | undefined} value - The search term or undefined to clear search
|
|
7609
7387
|
* @returns {Promise<void>}
|
|
7610
7388
|
*
|
|
7611
7389
|
* @mermaid
|
|
7612
|
-
*
|
|
7613
|
-
*
|
|
7614
|
-
*
|
|
7615
|
-
*
|
|
7390
|
+
* flowchart TD
|
|
7391
|
+
* A[Search Event] --> B{Type is Infinite?}
|
|
7392
|
+
* B -->|Yes| C[Disable loadMoreData]
|
|
7393
|
+
* B -->|No| D[Enable loadMoreData]
|
|
7394
|
+
* C --> E{Search value undefined?}
|
|
7395
|
+
* E -->|Yes| F[Enable loadMoreData]
|
|
7396
|
+
* E -->|No| G[Store search value]
|
|
7397
|
+
* D --> G
|
|
7398
|
+
* F --> H[Reset page to 1]
|
|
7399
|
+
* G --> I[Refresh data]
|
|
7400
|
+
* H --> I
|
|
7616
7401
|
*
|
|
7617
|
-
*
|
|
7618
|
-
|
|
7619
|
-
|
|
7620
|
-
|
|
7621
|
-
|
|
7622
|
-
|
|
7623
|
-
|
|
7624
|
-
|
|
7625
|
-
|
|
7626
|
-
|
|
7402
|
+
* @memberOf ListComponent
|
|
7403
|
+
*/
|
|
7404
|
+
async handleSearch(value) {
|
|
7405
|
+
if (this.type === ListComponentsTypes.INFINITE) {
|
|
7406
|
+
this.loadMoreData = false;
|
|
7407
|
+
if (value === undefined) {
|
|
7408
|
+
this.loadMoreData = true;
|
|
7409
|
+
this.page = 1;
|
|
7410
|
+
}
|
|
7411
|
+
this.searchValue = value;
|
|
7412
|
+
await this.refresh(true);
|
|
7413
|
+
}
|
|
7414
|
+
else {
|
|
7415
|
+
this.loadMoreData = true;
|
|
7416
|
+
this.searchValue = value;
|
|
7417
|
+
if (value === undefined)
|
|
7418
|
+
this.page = this.lastPage;
|
|
7419
|
+
await this.refresh(true);
|
|
7420
|
+
}
|
|
7421
|
+
}
|
|
7422
|
+
/**
|
|
7423
|
+
* @description Handles filter events from the filter component.
|
|
7424
|
+
* @summary Processes filter queries from the filter component and applies them
|
|
7425
|
+
* to the list data. This method acts as a bridge between the filter component
|
|
7426
|
+
* and the search functionality, converting filter queries into search operations.
|
|
7427
|
+
*
|
|
7428
|
+
* @param {IFilterQuery | undefined} value - The filter query object or undefined to clear filters
|
|
7429
|
+
* @returns {Promise<void>}
|
|
7430
|
+
* @memberOf ListComponent
|
|
7431
|
+
*/
|
|
7432
|
+
async handleFilter(value) {
|
|
7433
|
+
await this.handleSearch(value);
|
|
7434
|
+
}
|
|
7435
|
+
/**
|
|
7436
|
+
* @description Clears the current search and resets the list.
|
|
7437
|
+
* @summary Convenience method that clears the search by calling handleSearch
|
|
7438
|
+
* with undefined. This resets the list to show all data without filtering.
|
|
7627
7439
|
*
|
|
7440
|
+
* @returns {Promise<void>}
|
|
7628
7441
|
* @memberOf ListComponent
|
|
7629
7442
|
*/
|
|
7630
|
-
async
|
|
7631
|
-
|
|
7632
|
-
this.observerSubjet.pipe(debounceTime(100)).subscribe(args => this.handleObserveEvent(args[0], args[1], args[2]));
|
|
7633
|
-
this.enableFilter = stringToBoolean(this.enableFilter);
|
|
7634
|
-
this.limit = Number(this.limit);
|
|
7635
|
-
this.start = Number(this.start);
|
|
7636
|
-
this.inset = stringToBoolean(this.inset);
|
|
7637
|
-
this.showRefresher = stringToBoolean(this.showRefresher);
|
|
7638
|
-
this.loadMoreData = stringToBoolean(this.loadMoreData);
|
|
7639
|
-
this.showSearchbar = stringToBoolean(this.showSearchbar);
|
|
7640
|
-
this.disableSort = stringToBoolean(this.disableSort);
|
|
7641
|
-
if (typeof this.item?.['tag'] === 'boolean' && this.item?.['tag'] === true)
|
|
7642
|
-
this.item['tag'] = ComponentsTagNames.LIST_ITEM;
|
|
7643
|
-
await this.refresh();
|
|
7644
|
-
if (this.operations.includes(OperationKeys.CREATE) && this.route)
|
|
7645
|
-
this.empty.link = `${this.route}/${OperationKeys.CREATE}`;
|
|
7646
|
-
await this.initialize();
|
|
7647
|
-
if (this.model instanceof Model && this._repository)
|
|
7648
|
-
this._repository.observe(this.observer);
|
|
7443
|
+
async clearSearch() {
|
|
7444
|
+
await this.handleSearch(undefined);
|
|
7649
7445
|
}
|
|
7650
7446
|
/**
|
|
7651
|
-
* @description
|
|
7652
|
-
* @summary
|
|
7653
|
-
* This
|
|
7447
|
+
* @description Emits a refresh event with the current data.
|
|
7448
|
+
* @summary Creates and emits a refresh event containing the current list data.
|
|
7449
|
+
* This notifies parent components that the list data has been refreshed.
|
|
7654
7450
|
*
|
|
7451
|
+
* @param {KeyValue[]} [data] - Optional data to include in the event
|
|
7655
7452
|
* @returns {void}
|
|
7453
|
+
*
|
|
7656
7454
|
* @memberOf ListComponent
|
|
7657
7455
|
*/
|
|
7658
|
-
|
|
7659
|
-
if (
|
|
7660
|
-
this.
|
|
7661
|
-
this.
|
|
7456
|
+
refreshEventEmit(data) {
|
|
7457
|
+
if (!data)
|
|
7458
|
+
data = this.items;
|
|
7459
|
+
this.skeletonData = new Array(data?.length || 2);
|
|
7460
|
+
this.refreshEvent.emit({
|
|
7461
|
+
name: EventConstants.REFRESH,
|
|
7462
|
+
data: data || [],
|
|
7463
|
+
component: this.componentName
|
|
7464
|
+
});
|
|
7662
7465
|
}
|
|
7663
7466
|
/**
|
|
7664
|
-
* @description
|
|
7665
|
-
* @summary Processes
|
|
7666
|
-
*
|
|
7667
|
-
*
|
|
7467
|
+
* @description Emits a click event for a list item.
|
|
7468
|
+
* @summary Processes and emits a click event when a list item is clicked.
|
|
7469
|
+
* This extracts the relevant data from the event and passes it to parent components.
|
|
7470
|
+
*
|
|
7471
|
+
* @private
|
|
7472
|
+
* @param {ListItemCustomEvent | RendererCustomEvent} event - The click event
|
|
7473
|
+
* @returns {void}
|
|
7668
7474
|
*
|
|
7669
|
-
* @param {...unknown[]} args - The repository event arguments including table, event type, and UID
|
|
7670
|
-
* @returns {Promise<void>}
|
|
7671
7475
|
* @memberOf ListComponent
|
|
7672
7476
|
*/
|
|
7673
|
-
|
|
7674
|
-
|
|
7675
|
-
if (event === OperationKeys.CREATE && !!uid)
|
|
7676
|
-
return this.handleObserveEvent(table, event, uid);
|
|
7677
|
-
return this.observerSubjet.next(args);
|
|
7477
|
+
clickEventEmit(event) {
|
|
7478
|
+
this.clickEvent.emit(event);
|
|
7678
7479
|
}
|
|
7679
7480
|
/**
|
|
7680
|
-
* @description
|
|
7681
|
-
* @summary
|
|
7682
|
-
*
|
|
7683
|
-
*
|
|
7481
|
+
* @description Refreshes the list data from the configured source.
|
|
7482
|
+
* @summary This method handles both initial data loading and subsequent refresh operations,
|
|
7483
|
+
* including pull-to-refresh and infinite scrolling. It manages the data fetching process,
|
|
7484
|
+
* updates the component's state, and handles pagination or infinite scrolling logic based
|
|
7485
|
+
* on the component's configuration.
|
|
7486
|
+
*
|
|
7487
|
+
* The method performs the following steps:
|
|
7488
|
+
* 1. Sets the refreshing flag to indicate a data fetch is in progress
|
|
7489
|
+
* 2. Calculates the appropriate start and limit values based on pagination settings
|
|
7490
|
+
* 3. Fetches data from the appropriate source (model or request)
|
|
7491
|
+
* 4. Updates the component's data and emits a refresh event
|
|
7492
|
+
* 5. Handles pagination or infinite scrolling state updates
|
|
7493
|
+
* 6. Completes any provided event (like InfiniteScrollCustomEvent)
|
|
7494
|
+
*
|
|
7495
|
+
* @param {InfiniteScrollCustomEvent | RefresherCustomEvent | boolean} event - The event that triggered the refresh,
|
|
7496
|
+
* or a boolean flag indicating if this is a forced refresh
|
|
7497
|
+
* @returns {Promise<void>} A promise that resolves when the refresh operation is complete
|
|
7498
|
+
*
|
|
7499
|
+
* @mermaid
|
|
7500
|
+
* sequenceDiagram
|
|
7501
|
+
* participant L as ListComponent
|
|
7502
|
+
* participant D as Data Source
|
|
7503
|
+
* participant E as Event System
|
|
7504
|
+
*
|
|
7505
|
+
* L->>L: refresh(event)
|
|
7506
|
+
* L->>L: Set refreshing flag
|
|
7507
|
+
* L->>L: Calculate start and limit
|
|
7508
|
+
* alt Using model
|
|
7509
|
+
* L->>D: getFromModel(force, start, limit)
|
|
7510
|
+
* D-->>L: Return data
|
|
7511
|
+
* else Using request
|
|
7512
|
+
* L->>D: getFromRequest(force, start, limit)
|
|
7513
|
+
* D-->>L: Return data
|
|
7514
|
+
* end
|
|
7515
|
+
* L->>E: refreshEventEmit()
|
|
7516
|
+
* alt Infinite scrolling mode
|
|
7517
|
+
* L->>L: Check if reached last page
|
|
7518
|
+
* alt Last page reached
|
|
7519
|
+
* L->>L: Complete scroll event
|
|
7520
|
+
* L->>L: Disable loadMoreData
|
|
7521
|
+
* else More pages available
|
|
7522
|
+
* L->>L: Increment page number
|
|
7523
|
+
* L->>L: Complete scroll event after delay
|
|
7524
|
+
* end
|
|
7525
|
+
* else Paginated mode
|
|
7526
|
+
* L->>L: Clear refreshing flag after delay
|
|
7527
|
+
* end
|
|
7684
7528
|
*
|
|
7685
|
-
* @param {string} table - The table/model name that changed
|
|
7686
|
-
* @param {OperationKeys} event - The type of operation (CREATE, UPDATE, DELETE)
|
|
7687
|
-
* @param {string | number} uid - The unique identifier of the affected item
|
|
7688
|
-
* @returns {Promise<void>}
|
|
7689
7529
|
* @memberOf ListComponent
|
|
7690
7530
|
*/
|
|
7691
|
-
async
|
|
7692
|
-
if
|
|
7693
|
-
|
|
7694
|
-
|
|
7531
|
+
async refresh(event = false) {
|
|
7532
|
+
// if(typeof force !== 'boolean' && force.type === EventConstants.BACK_BUTTON_NAVIGATION) {
|
|
7533
|
+
// const {refresh} = (force as CustomEvent).detail;
|
|
7534
|
+
// if(!refresh)
|
|
7535
|
+
// return false;
|
|
7536
|
+
// }
|
|
7537
|
+
this.refreshing = true;
|
|
7538
|
+
const start = this.page > 1 ? (this.page - 1) * this.limit : this.start;
|
|
7539
|
+
const limit = (this.page * (this.limit > 12 ? 12 : this.limit));
|
|
7540
|
+
this.data = !this.model ?
|
|
7541
|
+
await this.getFromRequest(!!event, start, limit)
|
|
7542
|
+
: await this.getFromModel(!!event);
|
|
7543
|
+
this.refreshEventEmit();
|
|
7544
|
+
if (this.type === ListComponentsTypes.INFINITE) {
|
|
7545
|
+
if (this.page === this.pages) {
|
|
7546
|
+
if (event?.target)
|
|
7547
|
+
event.target.complete();
|
|
7548
|
+
this.loadMoreData = false;
|
|
7695
7549
|
}
|
|
7696
7550
|
else {
|
|
7697
|
-
|
|
7551
|
+
this.page += 1;
|
|
7552
|
+
this.refreshing = false;
|
|
7553
|
+
setTimeout(() => {
|
|
7554
|
+
if (event?.target && event?.type !== EventConstants.BACK_BUTTON_NAVIGATION)
|
|
7555
|
+
event.target.complete();
|
|
7556
|
+
}, 200);
|
|
7698
7557
|
}
|
|
7699
7558
|
}
|
|
7700
7559
|
else {
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
this.handleDelete(uid);
|
|
7705
|
-
this.refreshEventEmit();
|
|
7560
|
+
setTimeout(() => {
|
|
7561
|
+
this.refreshing = false;
|
|
7562
|
+
}, 200);
|
|
7706
7563
|
}
|
|
7707
7564
|
}
|
|
7708
7565
|
/**
|
|
7709
|
-
|
|
7710
|
-
|
|
7711
|
-
|
|
7712
|
-
|
|
7713
|
-
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7717
|
-
|
|
7718
|
-
|
|
7719
|
-
|
|
7720
|
-
|
|
7721
|
-
|
|
7722
|
-
|
|
7723
|
-
*/
|
|
7724
|
-
trackItemFn(index, item) {
|
|
7725
|
-
return `${item?.['uid'] || item?.[this.pk]}-${index}`;
|
|
7566
|
+
* @description Handles pagination events from the pagination component.
|
|
7567
|
+
* @summary Processes pagination events by updating the current page number and
|
|
7568
|
+
* refreshing the list data to display the selected page. This method is called
|
|
7569
|
+
* when a user interacts with the pagination controls to navigate between pages.
|
|
7570
|
+
*
|
|
7571
|
+
* @param {PaginationCustomEvent} event - The pagination event containing page information
|
|
7572
|
+
* @returns {void}
|
|
7573
|
+
*
|
|
7574
|
+
* @memberOf ListComponent
|
|
7575
|
+
*/
|
|
7576
|
+
handlePaginate(event) {
|
|
7577
|
+
const { page } = event.data;
|
|
7578
|
+
this.page = page;
|
|
7579
|
+
this.refresh(true);
|
|
7726
7580
|
}
|
|
7727
7581
|
/**
|
|
7728
|
-
* Handles
|
|
7582
|
+
* @description Handles pull-to-refresh events from the refresher component.
|
|
7583
|
+
* @summary Processes refresh events triggered by the user pulling down on the list
|
|
7584
|
+
* or by programmatic refresh requests. This method refreshes the list data and
|
|
7585
|
+
* completes the refresher animation when the data is loaded.
|
|
7729
7586
|
*
|
|
7730
|
-
* @param {
|
|
7731
|
-
* @returns {Promise<void>} A promise that resolves when the
|
|
7732
|
-
*/
|
|
7733
|
-
async handleCreate(uid) {
|
|
7734
|
-
const result = await this._repository?.read(uid);
|
|
7735
|
-
const item = this.mapResults([result])[0];
|
|
7736
|
-
this.items = this.data = [item, ...this.items || []];
|
|
7737
|
-
}
|
|
7738
|
-
/**
|
|
7739
|
-
* @description Handles the update event from the repository.
|
|
7740
|
-
* @summary Updates the list item with the specified ID based on the new data.
|
|
7587
|
+
* @param {InfiniteScrollCustomEvent | CustomEvent} [event] - The refresh event
|
|
7588
|
+
* @returns {Promise<void>} A promise that resolves when the refresh operation is complete
|
|
7741
7589
|
*
|
|
7742
|
-
* @param {string | number} uid - The ID of the item to update
|
|
7743
|
-
* @returns {Promise<void>}
|
|
7744
|
-
* @private
|
|
7745
7590
|
* @memberOf ListComponent
|
|
7746
7591
|
*/
|
|
7747
|
-
async
|
|
7748
|
-
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
7753
|
-
|
|
7754
|
-
break;
|
|
7755
|
-
}
|
|
7756
|
-
}
|
|
7757
|
-
setTimeout(() => {
|
|
7758
|
-
this.data = [...this.items];
|
|
7759
|
-
}, 0);
|
|
7592
|
+
async handleRefresh(event) {
|
|
7593
|
+
await this.refresh(event || true);
|
|
7594
|
+
if (event instanceof CustomEvent)
|
|
7595
|
+
setTimeout(() => {
|
|
7596
|
+
// Any calls to load data go here
|
|
7597
|
+
event.target.complete();
|
|
7598
|
+
}, 400);
|
|
7760
7599
|
}
|
|
7761
7600
|
/**
|
|
7762
|
-
* @description
|
|
7763
|
-
* @summary
|
|
7764
|
-
*
|
|
7601
|
+
* @description Filters data based on a search string.
|
|
7602
|
+
* @summary Processes the current data array to find items that match the provided
|
|
7603
|
+
* search string. This uses the arrayQueryByString utility to perform the filtering
|
|
7604
|
+
* across all properties of the items.
|
|
7765
7605
|
*
|
|
7766
|
-
* @param {
|
|
7767
|
-
* @param {string}
|
|
7768
|
-
* @returns {
|
|
7606
|
+
* @param {KeyValue[]} results - The array of items to search through
|
|
7607
|
+
* @param {string} search - The search string to filter by
|
|
7608
|
+
* @returns {KeyValue[]} A promise that resolves to the filtered array of items
|
|
7769
7609
|
*
|
|
7770
7610
|
* @memberOf ListComponent
|
|
7771
7611
|
*/
|
|
7772
|
-
|
|
7773
|
-
|
|
7774
|
-
pk = this.pk;
|
|
7775
|
-
this.items = this.data?.filter((item) => item['uid'] !== uid) || [];
|
|
7612
|
+
parseSearchResults(results, search) {
|
|
7613
|
+
return results.filter((item) => Object.values(item).some(value => value.toString().toLowerCase().includes(search?.toLowerCase())));
|
|
7776
7614
|
}
|
|
7777
7615
|
/**
|
|
7778
|
-
* @description
|
|
7779
|
-
* @summary
|
|
7780
|
-
*
|
|
7781
|
-
*
|
|
7616
|
+
* @description Fetches data from a request source.
|
|
7617
|
+
* @summary Retrieves data from the configured source function or URL, processes it,
|
|
7618
|
+
* and updates the component's data state. This method handles both initial data loading
|
|
7619
|
+
* and subsequent refresh operations when using an external data source rather than a model.
|
|
7782
7620
|
*
|
|
7783
|
-
* @param {
|
|
7784
|
-
* @
|
|
7621
|
+
* @param {boolean} force - Whether to force a refresh even if data already exists
|
|
7622
|
+
* @param {number} start - The starting index for pagination
|
|
7623
|
+
* @param {number} limit - The maximum number of items to retrieve
|
|
7624
|
+
* @returns {Promise<KeyValue[]>} A promise that resolves to the fetched data
|
|
7785
7625
|
*
|
|
7786
7626
|
* @memberOf ListComponent
|
|
7787
7627
|
*/
|
|
7788
|
-
|
|
7789
|
-
|
|
7628
|
+
async getFromRequest(force = false, start, limit) {
|
|
7629
|
+
let request = [];
|
|
7630
|
+
if (!this.data?.length || force || this.searchValue?.length || !!this.searchValue) {
|
|
7631
|
+
// (self.data as ListItem[]) = [];
|
|
7632
|
+
if (!this.searchValue?.length && !this.searchValue) {
|
|
7633
|
+
if (!this.source && !this.data?.length) {
|
|
7634
|
+
this.logger.info('No data and source passed to infinite list');
|
|
7635
|
+
return [];
|
|
7636
|
+
}
|
|
7637
|
+
if (this.source instanceof Function)
|
|
7638
|
+
request = await this.source();
|
|
7639
|
+
if (!Array.isArray(request))
|
|
7640
|
+
request = request?.['response']?.['data'] || request?.['results'] || [];
|
|
7641
|
+
this.data = [...await this.parseResult(request)];
|
|
7642
|
+
if (this.data?.length)
|
|
7643
|
+
this.items = this.type === ListComponentsTypes.INFINITE ?
|
|
7644
|
+
(this.items || []).concat([...this.data.slice(start, limit)]) : [...request.slice(start, limit)];
|
|
7645
|
+
}
|
|
7646
|
+
else {
|
|
7647
|
+
this.data = this.parseSearchResults(this.data, this.searchValue);
|
|
7648
|
+
this.items = this.data;
|
|
7649
|
+
}
|
|
7650
|
+
}
|
|
7651
|
+
if (this.loadMoreData && this.type === ListComponentsTypes.PAGINATED)
|
|
7652
|
+
this.getMoreData(this.data?.length || 0);
|
|
7653
|
+
return this.data || [];
|
|
7790
7654
|
}
|
|
7791
7655
|
/**
|
|
7792
|
-
* @description
|
|
7793
|
-
* @summary
|
|
7794
|
-
*
|
|
7795
|
-
* and
|
|
7796
|
-
*
|
|
7797
|
-
* @param {string | undefined} value - The search term or undefined to clear search
|
|
7798
|
-
* @returns {Promise<void>}
|
|
7656
|
+
* @description Fetches data from a model source.
|
|
7657
|
+
* @summary Retrieves data from the configured model using its pagination or find methods,
|
|
7658
|
+
* processes it, and updates the component's data state. This method handles both initial
|
|
7659
|
+
* data loading and subsequent refresh operations when using a model as the data source.
|
|
7799
7660
|
*
|
|
7800
|
-
* @
|
|
7801
|
-
*
|
|
7802
|
-
*
|
|
7803
|
-
*
|
|
7804
|
-
* B -->|No| D[Enable loadMoreData]
|
|
7805
|
-
* C --> E{Search value undefined?}
|
|
7806
|
-
* E -->|Yes| F[Enable loadMoreData]
|
|
7807
|
-
* E -->|No| G[Store search value]
|
|
7808
|
-
* D --> G
|
|
7809
|
-
* F --> H[Reset page to 1]
|
|
7810
|
-
* G --> I[Refresh data]
|
|
7811
|
-
* H --> I
|
|
7661
|
+
* @param {boolean} force - Whether to force a refresh even if data already exists
|
|
7662
|
+
* @param {number} start - The starting index for pagination
|
|
7663
|
+
* @param {number} limit - The maximum number of items to retrieve
|
|
7664
|
+
* @returns {Promise<KeyValue[]>} A promise that resolves to the fetched data
|
|
7812
7665
|
*
|
|
7813
7666
|
* @memberOf ListComponent
|
|
7814
7667
|
*/
|
|
7815
|
-
async
|
|
7816
|
-
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
|
|
7668
|
+
async getFromModel(force = false) {
|
|
7669
|
+
let data = [...this.data || []];
|
|
7670
|
+
let request = [];
|
|
7671
|
+
// getting model repository
|
|
7672
|
+
if (!this._repository)
|
|
7673
|
+
this._repository = this.repository;
|
|
7674
|
+
const repo = this._repository;
|
|
7675
|
+
if (!this.data?.length || force || this.searchValue?.length || !!this.searchValue) {
|
|
7676
|
+
try {
|
|
7677
|
+
if (!this.searchValue?.length && !this.searchValue) {
|
|
7678
|
+
this.data = [];
|
|
7679
|
+
// const rawQuery = this.parseQuery(self.model as Repository<Model>, start, limit);
|
|
7680
|
+
// request = this.parseResult(await (this.model as any)?.paginate(start, limit));
|
|
7681
|
+
if (!this.paginator) {
|
|
7682
|
+
this.paginator = await repo
|
|
7683
|
+
.select()
|
|
7684
|
+
.orderBy([this.pk, this.sortDirection])
|
|
7685
|
+
.paginate(this.limit);
|
|
7686
|
+
}
|
|
7687
|
+
request = await this.parseResult(this.paginator);
|
|
7688
|
+
}
|
|
7689
|
+
else {
|
|
7690
|
+
if (!this.indexes)
|
|
7691
|
+
this.indexes = (Object.values(this.mapper) || [this.pk]);
|
|
7692
|
+
const condition = this.parseConditions(this.searchValue);
|
|
7693
|
+
request = await this.parseResult(await repo.query(condition, (this.sortBy || this.pk), this.sortDirection));
|
|
7694
|
+
data = [];
|
|
7695
|
+
}
|
|
7696
|
+
data = this.type === ListComponentsTypes.INFINITE ? [...(data).concat(request)] : [...request];
|
|
7697
|
+
}
|
|
7698
|
+
catch (error) {
|
|
7699
|
+
this.logger.error(error?.message || `Unable to find ${this.model} on registry. Return empty array from component`);
|
|
7821
7700
|
}
|
|
7822
|
-
this.searchValue = value;
|
|
7823
|
-
await this.refresh(true);
|
|
7824
7701
|
}
|
|
7825
|
-
|
|
7826
|
-
this.
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
|
|
7702
|
+
if (data?.length) {
|
|
7703
|
+
if (this.searchValue) {
|
|
7704
|
+
this.items = [...data];
|
|
7705
|
+
if (this.items?.length <= this.limit)
|
|
7706
|
+
this.loadMoreData = false;
|
|
7707
|
+
}
|
|
7708
|
+
else {
|
|
7709
|
+
this.items = [...data];
|
|
7710
|
+
}
|
|
7831
7711
|
}
|
|
7712
|
+
if (this.type === ListComponentsTypes.PAGINATED && this.paginator)
|
|
7713
|
+
this.getMoreData(this.paginator.total);
|
|
7714
|
+
return data || [];
|
|
7832
7715
|
}
|
|
7833
7716
|
/**
|
|
7834
|
-
* @description
|
|
7835
|
-
* @summary
|
|
7836
|
-
*
|
|
7837
|
-
*
|
|
7717
|
+
* @description Converts search values or filter queries into database conditions.
|
|
7718
|
+
* @summary Transforms search input or complex filter queries into Condition objects
|
|
7719
|
+
* that can be used for database querying. Handles both simple string/number searches
|
|
7720
|
+
* across indexed fields and complex filter queries with multiple criteria.
|
|
7838
7721
|
*
|
|
7839
|
-
*
|
|
7840
|
-
*
|
|
7841
|
-
*
|
|
7842
|
-
|
|
7843
|
-
async handleFilter(value) {
|
|
7844
|
-
await this.handleSearch(value);
|
|
7845
|
-
}
|
|
7846
|
-
/**
|
|
7847
|
-
* @description Clears the current search and resets the list.
|
|
7848
|
-
* @summary Convenience method that clears the search by calling handleSearch
|
|
7849
|
-
* with undefined. This resets the list to show all data without filtering.
|
|
7722
|
+
* For simple searches (string/number):
|
|
7723
|
+
* - Creates conditions that search across all indexed fields
|
|
7724
|
+
* - Uses equality for numeric values and regex for string values
|
|
7725
|
+
* - Combines conditions with OR logic to search multiple fields
|
|
7850
7726
|
*
|
|
7851
|
-
*
|
|
7727
|
+
* For complex filter queries:
|
|
7728
|
+
* - Processes each filter item with its specific condition type
|
|
7729
|
+
* - Supports Equal, Not Equal, Contains, Not Contains, Greater Than, Less Than
|
|
7730
|
+
* - Updates sort configuration based on the filter query
|
|
7731
|
+
* - Combines multiple filter conditions with OR logic
|
|
7732
|
+
*
|
|
7733
|
+
* @param {string | number | IFilterQuery} value - The search value or filter query object
|
|
7734
|
+
* @returns {Condition<Model>} A Condition object for database querying
|
|
7852
7735
|
* @memberOf ListComponent
|
|
7853
7736
|
*/
|
|
7854
|
-
|
|
7855
|
-
|
|
7737
|
+
parseConditions(value) {
|
|
7738
|
+
let _condition;
|
|
7739
|
+
if (typeof value === Primitives.STRING || typeof value === Primitives.NUMBER) {
|
|
7740
|
+
_condition = Condition.attribute(this.pk).eq(!isNaN(value) ? Number(value) : value);
|
|
7741
|
+
for (const index of this.indexes) {
|
|
7742
|
+
if (index === this.pk)
|
|
7743
|
+
continue;
|
|
7744
|
+
let orCondition;
|
|
7745
|
+
if (!isNaN(value)) {
|
|
7746
|
+
orCondition = Condition.attribute(index).eq(Number(value));
|
|
7747
|
+
}
|
|
7748
|
+
else {
|
|
7749
|
+
orCondition = Condition.attribute(index).regexp(value);
|
|
7750
|
+
}
|
|
7751
|
+
_condition = _condition.or(orCondition);
|
|
7752
|
+
}
|
|
7753
|
+
}
|
|
7754
|
+
else {
|
|
7755
|
+
const { query, sort } = value;
|
|
7756
|
+
_condition = Condition.attribute(this.pk).dif('null');
|
|
7757
|
+
if (query?.length)
|
|
7758
|
+
_condition = undefined;
|
|
7759
|
+
(query || []).forEach((item) => {
|
|
7760
|
+
const { value, condition, index } = item;
|
|
7761
|
+
let val = value;
|
|
7762
|
+
if (index === this.pk || !isNaN(val))
|
|
7763
|
+
val = Number(val);
|
|
7764
|
+
let orCondition;
|
|
7765
|
+
switch (condition) {
|
|
7766
|
+
case "Equal":
|
|
7767
|
+
orCondition = Condition.attribute(index).eq(val);
|
|
7768
|
+
break;
|
|
7769
|
+
case "Not Equal":
|
|
7770
|
+
orCondition = Condition.attribute(index).dif(val);
|
|
7771
|
+
break;
|
|
7772
|
+
case "Not Contains":
|
|
7773
|
+
orCondition = !Condition.attribute(index).regexp(new RegExp(`^(?!.*${val}).*$`));
|
|
7774
|
+
break;
|
|
7775
|
+
case "Contains":
|
|
7776
|
+
orCondition = Condition.attribute(index).regexp(val);
|
|
7777
|
+
break;
|
|
7778
|
+
case "Greater Than":
|
|
7779
|
+
orCondition = Condition.attribute(index).gte(val);
|
|
7780
|
+
break;
|
|
7781
|
+
case "Less Than":
|
|
7782
|
+
orCondition = Condition.attribute(index).lte(val);
|
|
7783
|
+
break;
|
|
7784
|
+
}
|
|
7785
|
+
_condition = (!_condition ?
|
|
7786
|
+
orCondition : _condition.and(orCondition));
|
|
7787
|
+
});
|
|
7788
|
+
this.sortBy = sort?.value || this.pk;
|
|
7789
|
+
this.sortDirection = sort?.direction || this.sortDirection;
|
|
7790
|
+
}
|
|
7791
|
+
return _condition;
|
|
7856
7792
|
}
|
|
7857
7793
|
/**
|
|
7858
|
-
* @description
|
|
7859
|
-
* @summary
|
|
7860
|
-
*
|
|
7794
|
+
* @description Processes query results into a standardized format.
|
|
7795
|
+
* @summary Handles different result formats from various data sources, extracting
|
|
7796
|
+
* pagination information when available and applying any configured data mapping.
|
|
7797
|
+
* This ensures consistent data structure regardless of the source.
|
|
7861
7798
|
*
|
|
7862
|
-
* @
|
|
7863
|
-
* @
|
|
7799
|
+
* @protected
|
|
7800
|
+
* @param {KeyValue[] | Paginator} result - The raw query result
|
|
7801
|
+
* @returns {KeyValue[]} The processed array of items
|
|
7864
7802
|
*
|
|
7865
7803
|
* @memberOf ListComponent
|
|
7866
7804
|
*/
|
|
7867
|
-
|
|
7868
|
-
if (!
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
|
|
7875
|
-
|
|
7805
|
+
async parseResult(result) {
|
|
7806
|
+
if (!Array.isArray(result) && ('page' in result && 'total' in result)) {
|
|
7807
|
+
const paginator = result;
|
|
7808
|
+
try {
|
|
7809
|
+
result = await paginator.page(this.page);
|
|
7810
|
+
// TODO: Chage for result.total;
|
|
7811
|
+
this.getMoreData(paginator.total);
|
|
7812
|
+
}
|
|
7813
|
+
catch (error) {
|
|
7814
|
+
this.logger.info(error?.message || 'Unable to get page from paginator. Return empty array from component');
|
|
7815
|
+
result = [];
|
|
7816
|
+
}
|
|
7817
|
+
}
|
|
7818
|
+
else {
|
|
7819
|
+
this.getMoreData(result?.length || 0);
|
|
7820
|
+
}
|
|
7821
|
+
return (Object.keys(this.mapper || {}).length) ?
|
|
7822
|
+
this.mapResults(result) : result;
|
|
7876
7823
|
}
|
|
7877
7824
|
/**
|
|
7878
|
-
* @description
|
|
7879
|
-
* @summary
|
|
7880
|
-
*
|
|
7825
|
+
* @description Updates pagination state based on data length.
|
|
7826
|
+
* @summary Calculates whether more data is available and how many pages exist
|
|
7827
|
+
* based on the total number of items and the configured limit per page.
|
|
7828
|
+
* This information is used to control pagination UI and infinite scrolling behavior.
|
|
7881
7829
|
*
|
|
7882
|
-
* @
|
|
7883
|
-
* @param {ListItemCustomEvent | RendererCustomEvent} event - The click event
|
|
7830
|
+
* @param {number} length - The total number of items available
|
|
7884
7831
|
* @returns {void}
|
|
7885
7832
|
*
|
|
7886
7833
|
* @memberOf ListComponent
|
|
7887
7834
|
*/
|
|
7888
|
-
|
|
7889
|
-
this.clickEvent.emit(event);
|
|
7890
|
-
}
|
|
7891
|
-
/**
|
|
7892
|
-
* @description Refreshes the list data from the configured source.
|
|
7893
|
-
* @summary This method handles both initial data loading and subsequent refresh operations,
|
|
7894
|
-
* including pull-to-refresh and infinite scrolling. It manages the data fetching process,
|
|
7895
|
-
* updates the component's state, and handles pagination or infinite scrolling logic based
|
|
7896
|
-
* on the component's configuration.
|
|
7897
|
-
*
|
|
7898
|
-
* The method performs the following steps:
|
|
7899
|
-
* 1. Sets the refreshing flag to indicate a data fetch is in progress
|
|
7900
|
-
* 2. Calculates the appropriate start and limit values based on pagination settings
|
|
7901
|
-
* 3. Fetches data from the appropriate source (model or request)
|
|
7902
|
-
* 4. Updates the component's data and emits a refresh event
|
|
7903
|
-
* 5. Handles pagination or infinite scrolling state updates
|
|
7904
|
-
* 6. Completes any provided event (like InfiniteScrollCustomEvent)
|
|
7905
|
-
*
|
|
7906
|
-
* @param {InfiniteScrollCustomEvent | RefresherCustomEvent | boolean} event - The event that triggered the refresh,
|
|
7907
|
-
* or a boolean flag indicating if this is a forced refresh
|
|
7908
|
-
* @returns {Promise<void>} A promise that resolves when the refresh operation is complete
|
|
7909
|
-
*
|
|
7910
|
-
* @mermaid
|
|
7911
|
-
* sequenceDiagram
|
|
7912
|
-
* participant L as ListComponent
|
|
7913
|
-
* participant D as Data Source
|
|
7914
|
-
* participant E as Event System
|
|
7915
|
-
*
|
|
7916
|
-
* L->>L: refresh(event)
|
|
7917
|
-
* L->>L: Set refreshing flag
|
|
7918
|
-
* L->>L: Calculate start and limit
|
|
7919
|
-
* alt Using model
|
|
7920
|
-
* L->>D: getFromModel(force, start, limit)
|
|
7921
|
-
* D-->>L: Return data
|
|
7922
|
-
* else Using request
|
|
7923
|
-
* L->>D: getFromRequest(force, start, limit)
|
|
7924
|
-
* D-->>L: Return data
|
|
7925
|
-
* end
|
|
7926
|
-
* L->>E: refreshEventEmit()
|
|
7927
|
-
* alt Infinite scrolling mode
|
|
7928
|
-
* L->>L: Check if reached last page
|
|
7929
|
-
* alt Last page reached
|
|
7930
|
-
* L->>L: Complete scroll event
|
|
7931
|
-
* L->>L: Disable loadMoreData
|
|
7932
|
-
* else More pages available
|
|
7933
|
-
* L->>L: Increment page number
|
|
7934
|
-
* L->>L: Complete scroll event after delay
|
|
7935
|
-
* end
|
|
7936
|
-
* else Paginated mode
|
|
7937
|
-
* L->>L: Clear refreshing flag after delay
|
|
7938
|
-
* end
|
|
7939
|
-
*
|
|
7940
|
-
* @memberOf ListComponent
|
|
7941
|
-
*/
|
|
7942
|
-
async refresh(event = false) {
|
|
7943
|
-
// if(typeof force !== 'boolean' && force.type === EventConstants.BACK_BUTTON_NAVIGATION) {
|
|
7944
|
-
// const {refresh} = (force as CustomEvent).detail;
|
|
7945
|
-
// if(!refresh)
|
|
7946
|
-
// return false;
|
|
7947
|
-
// }
|
|
7948
|
-
this.refreshing = true;
|
|
7949
|
-
const start = this.page > 1 ? (this.page - 1) * this.limit : this.start;
|
|
7950
|
-
const limit = (this.page * (this.limit > 12 ? 12 : this.limit));
|
|
7951
|
-
this.data = !this.model ?
|
|
7952
|
-
await this.getFromRequest(!!event, start, limit)
|
|
7953
|
-
: await this.getFromModel(!!event);
|
|
7954
|
-
this.refreshEventEmit();
|
|
7835
|
+
getMoreData(length) {
|
|
7955
7836
|
if (this.type === ListComponentsTypes.INFINITE) {
|
|
7956
|
-
if (this.
|
|
7957
|
-
|
|
7958
|
-
|
|
7837
|
+
if (this.paginator)
|
|
7838
|
+
length = length * this.limit;
|
|
7839
|
+
if (length <= this.limit) {
|
|
7959
7840
|
this.loadMoreData = false;
|
|
7960
7841
|
}
|
|
7961
7842
|
else {
|
|
7962
|
-
this.
|
|
7963
|
-
this.
|
|
7964
|
-
|
|
7965
|
-
|
|
7966
|
-
|
|
7967
|
-
}, 200);
|
|
7843
|
+
this.pages = Math.floor(length / this.limit);
|
|
7844
|
+
if ((this.pages * this.limit) < length)
|
|
7845
|
+
this.pages += 1;
|
|
7846
|
+
if (this.pages === 1)
|
|
7847
|
+
this.loadMoreData = false;
|
|
7968
7848
|
}
|
|
7969
7849
|
}
|
|
7970
7850
|
else {
|
|
7971
|
-
|
|
7972
|
-
|
|
7973
|
-
|
|
7851
|
+
this.pages = length;
|
|
7852
|
+
if (this.pages === 1)
|
|
7853
|
+
this.loadMoreData = false;
|
|
7974
7854
|
}
|
|
7975
7855
|
}
|
|
7976
7856
|
/**
|
|
7977
|
-
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
7981
|
-
*
|
|
7982
|
-
* @param {PaginationCustomEvent} event - The pagination event containing page information
|
|
7983
|
-
* @returns {void}
|
|
7984
|
-
*
|
|
7985
|
-
* @memberOf ListComponent
|
|
7986
|
-
*/
|
|
7987
|
-
handlePaginate(event) {
|
|
7988
|
-
const { page } = event.data;
|
|
7989
|
-
this.page = page;
|
|
7990
|
-
this.refresh(true);
|
|
7991
|
-
}
|
|
7992
|
-
/**
|
|
7993
|
-
* @description Handles pull-to-refresh events from the refresher component.
|
|
7994
|
-
* @summary Processes refresh events triggered by the user pulling down on the list
|
|
7995
|
-
* or by programmatic refresh requests. This method refreshes the list data and
|
|
7996
|
-
* completes the refresher animation when the data is loaded.
|
|
7857
|
+
* @description Maps a single item using the configured mapper.
|
|
7858
|
+
* @summary Transforms a data item according to the mapping configuration,
|
|
7859
|
+
* extracting nested properties and formatting values as needed. This allows
|
|
7860
|
+
* the component to display data in a format different from how it's stored.
|
|
7997
7861
|
*
|
|
7998
|
-
* @
|
|
7999
|
-
* @
|
|
7862
|
+
* @protected
|
|
7863
|
+
* @param {KeyValue} item - The item to map
|
|
7864
|
+
* @param {KeyValue} mapper - The mapping configuration
|
|
7865
|
+
* @param {KeyValue} [props] - Additional properties to include
|
|
7866
|
+
* @returns {KeyValue} The mapped item
|
|
8000
7867
|
*
|
|
8001
7868
|
* @memberOf ListComponent
|
|
8002
7869
|
*/
|
|
8003
|
-
|
|
8004
|
-
|
|
8005
|
-
|
|
8006
|
-
|
|
8007
|
-
|
|
8008
|
-
|
|
8009
|
-
|
|
7870
|
+
itemMapper(item, mapper, props) {
|
|
7871
|
+
return Object.entries(mapper).reduce((accum, [key, value]) => {
|
|
7872
|
+
const arrayValue = value.split('.');
|
|
7873
|
+
if (!value) {
|
|
7874
|
+
accum[key] = value;
|
|
7875
|
+
}
|
|
7876
|
+
else {
|
|
7877
|
+
if (arrayValue.length === 1) {
|
|
7878
|
+
value = item?.[value] ? item[value] : value !== key ? value : "";
|
|
7879
|
+
if (isValidDate(value))
|
|
7880
|
+
value = `${formatDate(value)}`;
|
|
7881
|
+
accum[key] = value;
|
|
7882
|
+
}
|
|
7883
|
+
else {
|
|
7884
|
+
let val;
|
|
7885
|
+
for (const _value of arrayValue)
|
|
7886
|
+
val = !val
|
|
7887
|
+
? item[_value]
|
|
7888
|
+
: (typeof val === 'string' ? JSON.parse(val) : val)[_value];
|
|
7889
|
+
if (isValidDate(new Date(val)))
|
|
7890
|
+
val = `${formatDate(val)}`;
|
|
7891
|
+
accum[key] = val === null || val === undefined ? value : val;
|
|
7892
|
+
}
|
|
7893
|
+
}
|
|
7894
|
+
return Object.assign({}, props || {}, accum);
|
|
7895
|
+
}, {});
|
|
8010
7896
|
}
|
|
8011
7897
|
/**
|
|
8012
|
-
* @description
|
|
8013
|
-
* @summary
|
|
8014
|
-
*
|
|
8015
|
-
*
|
|
7898
|
+
* @description Maps all result items using the configured mapper.
|
|
7899
|
+
* @summary Applies the itemMapper to each item in the result set, adding
|
|
7900
|
+
* common properties like operations and route information. This transforms
|
|
7901
|
+
* the raw data into the format expected by the list item components.
|
|
8016
7902
|
*
|
|
8017
|
-
* @param {KeyValue[]}
|
|
8018
|
-
* @
|
|
8019
|
-
* @returns {KeyValue[]} A promise that resolves to the filtered array of items
|
|
7903
|
+
* @param {KeyValue[]} data - The array of items to map
|
|
7904
|
+
* @returns {KeyValue[]} The array of mapped items
|
|
8020
7905
|
*
|
|
8021
7906
|
* @memberOf ListComponent
|
|
8022
7907
|
*/
|
|
8023
|
-
|
|
8024
|
-
|
|
7908
|
+
mapResults(data) {
|
|
7909
|
+
if (!data || !data.length)
|
|
7910
|
+
return [];
|
|
7911
|
+
// passing uid as prop to mapper
|
|
7912
|
+
this.mapper = { ...this.mapper, ...{ uid: this.pk } };
|
|
7913
|
+
const props = Object.assign({
|
|
7914
|
+
operations: this.operations,
|
|
7915
|
+
route: this.route,
|
|
7916
|
+
...Object.keys(this.item).reduce((acc, key) => {
|
|
7917
|
+
acc[key] = this.item[key];
|
|
7918
|
+
return acc;
|
|
7919
|
+
}, {}),
|
|
7920
|
+
// ... (!this.item.render ? {} : Object.keys(this.item).reduce((acc: KeyValue, key: string) => {
|
|
7921
|
+
// acc[key] = this.item[key as keyof IListItemProp];
|
|
7922
|
+
// return acc;
|
|
7923
|
+
// }, {}))
|
|
7924
|
+
});
|
|
7925
|
+
return data.reduce((accum, curr) => {
|
|
7926
|
+
accum.push({ ...this.itemMapper(curr, this.mapper, props), ...{ pk: this.pk } });
|
|
7927
|
+
return accum;
|
|
7928
|
+
}, []);
|
|
8025
7929
|
}
|
|
7930
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
7931
|
+
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" }] }); }
|
|
7932
|
+
};
|
|
7933
|
+
ListComponent = __decorate([
|
|
7934
|
+
Dynamic(),
|
|
7935
|
+
__metadata("design:paramtypes", [])
|
|
7936
|
+
], ListComponent);
|
|
7937
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ListComponent, decorators: [{
|
|
7938
|
+
type: Component,
|
|
7939
|
+
args: [{ selector: 'ngx-decaf-list', standalone: true, imports: [
|
|
7940
|
+
TranslatePipe,
|
|
7941
|
+
IonRefresher,
|
|
7942
|
+
PaginationComponent,
|
|
7943
|
+
IonList,
|
|
7944
|
+
IonItem,
|
|
7945
|
+
IonThumbnail,
|
|
7946
|
+
IonSkeletonText,
|
|
7947
|
+
IonLabel,
|
|
7948
|
+
IonText,
|
|
7949
|
+
IonRefresherContent,
|
|
7950
|
+
IonInfiniteScroll,
|
|
7951
|
+
IonInfiniteScrollContent,
|
|
7952
|
+
IonThumbnail,
|
|
7953
|
+
IonSkeletonText,
|
|
7954
|
+
SearchbarComponent,
|
|
7955
|
+
EmptyStateComponent,
|
|
7956
|
+
FilterComponent,
|
|
7957
|
+
ComponentRendererComponent
|
|
7958
|
+
], 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"] }]
|
|
7959
|
+
}], ctorParameters: () => [], propDecorators: { type: [{
|
|
7960
|
+
type: Input
|
|
7961
|
+
}], translatable: [{
|
|
7962
|
+
type: Input
|
|
7963
|
+
}], showSearchbar: [{
|
|
7964
|
+
type: Input
|
|
7965
|
+
}], data: [{
|
|
7966
|
+
type: Input
|
|
7967
|
+
}], source: [{
|
|
7968
|
+
type: Input
|
|
7969
|
+
}], start: [{
|
|
7970
|
+
type: Input
|
|
7971
|
+
}], limit: [{
|
|
7972
|
+
type: Input
|
|
7973
|
+
}], loadMoreData: [{
|
|
7974
|
+
type: Input
|
|
7975
|
+
}], lines: [{
|
|
7976
|
+
type: Input
|
|
7977
|
+
}], inset: [{
|
|
7978
|
+
type: Input
|
|
7979
|
+
}], scrollThreshold: [{
|
|
7980
|
+
type: Input
|
|
7981
|
+
}], scrollPosition: [{
|
|
7982
|
+
type: Input
|
|
7983
|
+
}], loadingText: [{
|
|
7984
|
+
type: Input
|
|
7985
|
+
}], showRefresher: [{
|
|
7986
|
+
type: Input
|
|
7987
|
+
}], loadingSpinner: [{
|
|
7988
|
+
type: Input
|
|
7989
|
+
}], enableFilter: [{
|
|
7990
|
+
type: Input
|
|
7991
|
+
}], sortDirection: [{
|
|
7992
|
+
type: Input
|
|
7993
|
+
}], sortBy: [{
|
|
7994
|
+
type: Input
|
|
7995
|
+
}], disableSort: [{
|
|
7996
|
+
type: Input
|
|
7997
|
+
}], emptyIcon: [{
|
|
7998
|
+
type: Input
|
|
7999
|
+
}], empty: [{
|
|
8000
|
+
type: Input
|
|
8001
|
+
}], refreshEvent: [{
|
|
8002
|
+
type: Output
|
|
8003
|
+
}], clickEvent: [{
|
|
8004
|
+
type: Output
|
|
8005
|
+
}], handleClick: [{
|
|
8006
|
+
type: HostListener,
|
|
8007
|
+
args: ['window:ListItemClickEvent', ['$event']]
|
|
8008
|
+
}], handleSearch: [{
|
|
8009
|
+
type: HostListener,
|
|
8010
|
+
args: ['window:searchbarEvent', ['$event']]
|
|
8011
|
+
}], refresh: [{
|
|
8012
|
+
type: HostListener,
|
|
8013
|
+
args: ['window:BackButtonNavigationEndEvent', ['$event']]
|
|
8014
|
+
}] } });
|
|
8015
|
+
|
|
8016
|
+
/**
|
|
8017
|
+
* @description A component for displaying a list item with various customization options.
|
|
8018
|
+
* @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.
|
|
8019
|
+
*
|
|
8020
|
+
* @class
|
|
8021
|
+
* @extends NgxBaseComponent
|
|
8022
|
+
*
|
|
8023
|
+
* @param {string} [lines='none'] - Determines the line style of the item. Can be 'inset', 'inseet', or 'none'.
|
|
8024
|
+
* @param {Record<string, any>} item - The data item to be displayed in the list item.
|
|
8025
|
+
* @param {string} icon - The name of the icon to be displayed.
|
|
8026
|
+
* @param {'start' | 'end'} [iconSlot='start'] - The position of the icon within the item.
|
|
8027
|
+
* @param {StringOrBoolean} [button=true] - Determines if the item should behave as a button.
|
|
8028
|
+
* @param {string} [title] - The main title of the list item.
|
|
8029
|
+
* @param {string} [description] - A description for the list item.
|
|
8030
|
+
* @param {string} [info] - Additional information for the list item.
|
|
8031
|
+
* @param {string} [subinfo] - Sub-information for the list item.
|
|
8032
|
+
*
|
|
8033
|
+
* @example
|
|
8034
|
+
* <ngx-decaf-list-item
|
|
8035
|
+
* [item]="dataItem"
|
|
8036
|
+
* icon="star"
|
|
8037
|
+
* title="Item Title"
|
|
8038
|
+
* description="Item Description"
|
|
8039
|
+
* (clickEvent)="handleItemClick($event)">
|
|
8040
|
+
* </ngx-decaf-list-item>
|
|
8041
|
+
*
|
|
8042
|
+
* @mermaid
|
|
8043
|
+
* sequenceDiagram
|
|
8044
|
+
* participant C as Component
|
|
8045
|
+
* participant V as View
|
|
8046
|
+
* participant U as User
|
|
8047
|
+
* C->>V: Initialize component
|
|
8048
|
+
* V->>U: Display list item
|
|
8049
|
+
* U->>V: Click on item or action
|
|
8050
|
+
* V->>C: Trigger handleAction()
|
|
8051
|
+
* C->>C: Process action
|
|
8052
|
+
* C->>V: Update view or navigate
|
|
8053
|
+
*/
|
|
8054
|
+
let ListItemComponent = class ListItemComponent extends NgxBaseComponent {
|
|
8026
8055
|
/**
|
|
8027
|
-
* @description
|
|
8028
|
-
* @summary
|
|
8029
|
-
*
|
|
8030
|
-
*
|
|
8031
|
-
*
|
|
8032
|
-
* @param {boolean} force - Whether to force a refresh even if data already exists
|
|
8033
|
-
* @param {number} start - The starting index for pagination
|
|
8034
|
-
* @param {number} limit - The maximum number of items to retrieve
|
|
8035
|
-
* @returns {Promise<KeyValue[]>} A promise that resolves to the fetched data
|
|
8056
|
+
* @description Creates an instance of ListItemComponent.
|
|
8057
|
+
* @summary Initializes a new ListItemComponent by calling the parent class constructor
|
|
8058
|
+
* with the component name for logging and identification purposes. Also registers
|
|
8059
|
+
* all available Ionic icons to ensure they can be displayed in the component.
|
|
8036
8060
|
*
|
|
8037
|
-
* @memberOf
|
|
8061
|
+
* @memberOf ListItemComponent
|
|
8038
8062
|
*/
|
|
8039
|
-
|
|
8040
|
-
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
|
|
8058
|
-
|
|
8059
|
-
|
|
8060
|
-
|
|
8061
|
-
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8063
|
+
constructor() {
|
|
8064
|
+
super("ListItemComponent");
|
|
8065
|
+
/**
|
|
8066
|
+
* @description Controls the display of lines around the list item.
|
|
8067
|
+
* @summary Determines how lines are displayed around the list item borders.
|
|
8068
|
+
* 'inset' shows lines with padding, 'full' shows full-width lines, and 'none'
|
|
8069
|
+
* removes all lines. This affects the visual separation between list items.
|
|
8070
|
+
*
|
|
8071
|
+
* @type {'inset' | 'full' | 'none'}
|
|
8072
|
+
* @default 'inset'
|
|
8073
|
+
* @memberOf ListItemComponent
|
|
8074
|
+
*/
|
|
8075
|
+
this.lines = 'full';
|
|
8076
|
+
/**
|
|
8077
|
+
* @description Position of the icon within the list item.
|
|
8078
|
+
* @summary Determines whether the icon appears at the start (left in LTR languages)
|
|
8079
|
+
* or end (right in LTR languages) of the list item. This affects the overall
|
|
8080
|
+
* layout and visual hierarchy of the item content.
|
|
8081
|
+
*
|
|
8082
|
+
* @type {'start' | 'end'}
|
|
8083
|
+
* @default 'start'
|
|
8084
|
+
* @memberOf ListItemComponent
|
|
8085
|
+
*/
|
|
8086
|
+
this.iconSlot = 'start';
|
|
8087
|
+
/**
|
|
8088
|
+
* @description Controls whether the list item behaves as a clickable button.
|
|
8089
|
+
* @summary When set to true, the list item will have button-like behavior including
|
|
8090
|
+
* hover effects, click handling, and appropriate accessibility attributes.
|
|
8091
|
+
* When false, the item is displayed as static content without interactive behavior.
|
|
8092
|
+
*
|
|
8093
|
+
* @type {StringOrBoolean}
|
|
8094
|
+
* @default true
|
|
8095
|
+
* @memberOf ListItemComponent
|
|
8096
|
+
*/
|
|
8097
|
+
this.button = true;
|
|
8098
|
+
/**
|
|
8099
|
+
* @description Event emitter for list item click interactions.
|
|
8100
|
+
* @summary Emits custom events when the list item is clicked or when actions
|
|
8101
|
+
* are performed on it. The emitted event contains information about the action,
|
|
8102
|
+
* the item data, and other relevant context for parent components to handle.
|
|
8103
|
+
*
|
|
8104
|
+
* @type {EventEmitter<ListItemCustomEvent>}
|
|
8105
|
+
* @memberOf ListItemComponent
|
|
8106
|
+
*/
|
|
8107
|
+
this.clickEvent = new EventEmitter();
|
|
8108
|
+
/**
|
|
8109
|
+
* @description Flag indicating whether slide items are currently enabled.
|
|
8110
|
+
* @summary Controls the visibility of slide actions based on screen size and
|
|
8111
|
+
* available operations. When true, users can swipe on the item to reveal
|
|
8112
|
+
* action buttons for operations like edit and delete.
|
|
8113
|
+
*
|
|
8114
|
+
* @type {boolean}
|
|
8115
|
+
* @default false
|
|
8116
|
+
* @memberOf ListItemComponent
|
|
8117
|
+
*/
|
|
8118
|
+
this.showSlideItems = false;
|
|
8119
|
+
/**
|
|
8120
|
+
* @description Flag indicating whether the action menu popover is currently open.
|
|
8121
|
+
* @summary Tracks the state of the action menu to prevent multiple instances
|
|
8122
|
+
* from being opened simultaneously and to ensure proper cleanup when actions
|
|
8123
|
+
* are performed. Used for managing the popover lifecycle.
|
|
8124
|
+
*
|
|
8125
|
+
* @type {boolean}
|
|
8126
|
+
* @default false
|
|
8127
|
+
* @memberOf ListItemComponent
|
|
8128
|
+
*/
|
|
8129
|
+
this.actionMenuOpen = false;
|
|
8130
|
+
/**
|
|
8131
|
+
* @description Angular NavController service for handling navigation.
|
|
8132
|
+
* @summary Injected service that provides methods for programmatic navigation
|
|
8133
|
+
* within the Ionic application. Used for navigating to different routes when
|
|
8134
|
+
* list item actions are performed or when the item itself is clicked.
|
|
8135
|
+
*
|
|
8136
|
+
* @private
|
|
8137
|
+
* @type {NavController}
|
|
8138
|
+
* @memberOf ListItemComponent
|
|
8139
|
+
*/
|
|
8140
|
+
this.navController = inject(NavController);
|
|
8141
|
+
addIcons(allIcons);
|
|
8142
|
+
}
|
|
8143
|
+
/**
|
|
8144
|
+
* @description Initializes the component after Angular first displays the data-bound properties.
|
|
8145
|
+
* @summary Sets up the component by determining slide item visibility, processing boolean inputs,
|
|
8146
|
+
* building CSS class names based on properties, and capturing the current window width.
|
|
8147
|
+
* This method prepares the component for user interaction by ensuring all properties are
|
|
8148
|
+
* properly initialized and responsive behavior is configured.
|
|
8071
8149
|
*
|
|
8072
|
-
* @
|
|
8073
|
-
*
|
|
8074
|
-
*
|
|
8075
|
-
*
|
|
8150
|
+
* @mermaid
|
|
8151
|
+
* sequenceDiagram
|
|
8152
|
+
* participant A as Angular Lifecycle
|
|
8153
|
+
* participant L as ListItemComponent
|
|
8154
|
+
* participant W as Window
|
|
8076
8155
|
*
|
|
8077
|
-
*
|
|
8156
|
+
* A->>L: ngOnInit()
|
|
8157
|
+
* L->>L: enableSlideItems()
|
|
8158
|
+
* L->>L: Process button boolean
|
|
8159
|
+
* L->>L: Build className with flex classes
|
|
8160
|
+
* alt operations exist
|
|
8161
|
+
* L->>L: Add 'action' class
|
|
8162
|
+
* end
|
|
8163
|
+
* L->>W: getWindowWidth()
|
|
8164
|
+
* W-->>L: Return current width
|
|
8165
|
+
* L->>L: Store windowWidth
|
|
8166
|
+
*
|
|
8167
|
+
* @return {Promise<void>}
|
|
8168
|
+
* @memberOf ListItemComponent
|
|
8078
8169
|
*/
|
|
8079
|
-
async
|
|
8080
|
-
|
|
8081
|
-
|
|
8082
|
-
|
|
8083
|
-
if (
|
|
8084
|
-
this.
|
|
8085
|
-
|
|
8086
|
-
if (!this.data?.length || force || this.searchValue?.length || !!this.searchValue) {
|
|
8087
|
-
try {
|
|
8088
|
-
if (!this.searchValue?.length && !this.searchValue) {
|
|
8089
|
-
this.data = [];
|
|
8090
|
-
// const rawQuery = this.parseQuery(self.model as Repository<Model>, start, limit);
|
|
8091
|
-
// request = this.parseResult(await (this.model as any)?.paginate(start, limit));
|
|
8092
|
-
if (!this.paginator) {
|
|
8093
|
-
this.paginator = await repo
|
|
8094
|
-
.select()
|
|
8095
|
-
.orderBy([this.pk, this.sortDirection])
|
|
8096
|
-
.paginate(this.limit);
|
|
8097
|
-
}
|
|
8098
|
-
request = await this.parseResult(this.paginator);
|
|
8099
|
-
}
|
|
8100
|
-
else {
|
|
8101
|
-
if (!this.indexes)
|
|
8102
|
-
this.indexes = (Object.values(this.mapper) || [this.pk]);
|
|
8103
|
-
const condition = this.parseConditions(this.searchValue);
|
|
8104
|
-
request = await this.parseResult(await repo.query(condition, (this.sortBy || this.pk), this.sortDirection));
|
|
8105
|
-
data = [];
|
|
8106
|
-
}
|
|
8107
|
-
data = this.type === ListComponentsTypes.INFINITE ? [...(data).concat(request)] : [...request];
|
|
8108
|
-
}
|
|
8109
|
-
catch (error) {
|
|
8110
|
-
this.logger.error(error?.message || `Unable to find ${this.model} on registry. Return empty array from component`);
|
|
8111
|
-
}
|
|
8112
|
-
}
|
|
8113
|
-
if (data?.length) {
|
|
8114
|
-
if (this.searchValue) {
|
|
8115
|
-
this.items = [...data];
|
|
8116
|
-
if (this.items?.length <= this.limit)
|
|
8117
|
-
this.loadMoreData = false;
|
|
8118
|
-
}
|
|
8119
|
-
else {
|
|
8120
|
-
this.items = [...data];
|
|
8121
|
-
}
|
|
8122
|
-
}
|
|
8123
|
-
if (this.type === ListComponentsTypes.PAGINATED && this.paginator)
|
|
8124
|
-
this.getMoreData(this.paginator.total);
|
|
8125
|
-
return data || [];
|
|
8170
|
+
async ngOnInit() {
|
|
8171
|
+
this.showSlideItems = this.enableSlideItems();
|
|
8172
|
+
this.button = stringToBoolean(this.button);
|
|
8173
|
+
this.className = `${this.className} dcf-flex dcf-flex-middle grid-item`;
|
|
8174
|
+
if (this.operations?.length)
|
|
8175
|
+
this.className += ` action`;
|
|
8176
|
+
this.windowWidth = getWindowWidth();
|
|
8126
8177
|
}
|
|
8127
8178
|
/**
|
|
8128
|
-
* @description
|
|
8129
|
-
* @summary
|
|
8130
|
-
*
|
|
8131
|
-
*
|
|
8179
|
+
* @description Handles user interactions and actions performed on the list item.
|
|
8180
|
+
* @summary This method is the central action handler for list item interactions. It manages
|
|
8181
|
+
* event propagation, dismisses open action menus, removes focus traps, and either emits
|
|
8182
|
+
* events for parent components to handle or performs navigation based on the component's
|
|
8183
|
+
* route configuration. This method supports both event-driven and navigation-driven architectures.
|
|
8132
8184
|
*
|
|
8133
|
-
*
|
|
8134
|
-
* -
|
|
8135
|
-
*
|
|
8136
|
-
*
|
|
8185
|
+
* @param {CrudOperations} action - The type of CRUD operation being performed
|
|
8186
|
+
* @param {Event} event - The browser event that triggered the action
|
|
8187
|
+
* @param {HTMLElement} [target] - Optional target element for the event
|
|
8188
|
+
* @return {Promise<boolean|void>} A promise that resolves to navigation success or void for events
|
|
8137
8189
|
*
|
|
8138
|
-
*
|
|
8139
|
-
*
|
|
8140
|
-
*
|
|
8141
|
-
*
|
|
8142
|
-
*
|
|
8190
|
+
* @mermaid
|
|
8191
|
+
* sequenceDiagram
|
|
8192
|
+
* participant U as User
|
|
8193
|
+
* participant L as ListItemComponent
|
|
8194
|
+
* participant P as Parent Component
|
|
8195
|
+
* participant N as NavController
|
|
8196
|
+
* participant E as Event System
|
|
8143
8197
|
*
|
|
8144
|
-
*
|
|
8145
|
-
*
|
|
8146
|
-
*
|
|
8198
|
+
* U->>L: Perform action (click/swipe)
|
|
8199
|
+
* L->>L: stopImmediatePropagation()
|
|
8200
|
+
* alt actionMenuOpen
|
|
8201
|
+
* L->>L: Dismiss action menu
|
|
8202
|
+
* end
|
|
8203
|
+
* L->>L: removeFocusTrap()
|
|
8204
|
+
* alt No route configured
|
|
8205
|
+
* L->>E: windowEventEmitter()
|
|
8206
|
+
* L->>P: clickEvent.emit()
|
|
8207
|
+
* else Route configured
|
|
8208
|
+
* L->>N: redirect(action, uid)
|
|
8209
|
+
* N-->>L: Return navigation result
|
|
8210
|
+
* end
|
|
8211
|
+
*
|
|
8212
|
+
* @memberOf ListItemComponent
|
|
8147
8213
|
*/
|
|
8148
|
-
|
|
8149
|
-
|
|
8150
|
-
if (
|
|
8151
|
-
|
|
8152
|
-
|
|
8153
|
-
|
|
8154
|
-
|
|
8155
|
-
|
|
8156
|
-
|
|
8157
|
-
|
|
8158
|
-
}
|
|
8159
|
-
else {
|
|
8160
|
-
orCondition = Condition.attribute(index).regexp(value);
|
|
8161
|
-
}
|
|
8162
|
-
_condition = _condition.or(orCondition);
|
|
8163
|
-
}
|
|
8164
|
-
}
|
|
8165
|
-
else {
|
|
8166
|
-
const { query, sort } = value;
|
|
8167
|
-
_condition = Condition.attribute(this.pk).dif('null');
|
|
8168
|
-
if (query?.length)
|
|
8169
|
-
_condition = undefined;
|
|
8170
|
-
(query || []).forEach((item) => {
|
|
8171
|
-
const { value, condition, index } = item;
|
|
8172
|
-
let val = value;
|
|
8173
|
-
if (index === this.pk || !isNaN(val))
|
|
8174
|
-
val = Number(val);
|
|
8175
|
-
let orCondition;
|
|
8176
|
-
switch (condition) {
|
|
8177
|
-
case "Equal":
|
|
8178
|
-
orCondition = Condition.attribute(index).eq(val);
|
|
8179
|
-
break;
|
|
8180
|
-
case "Not Equal":
|
|
8181
|
-
orCondition = Condition.attribute(index).dif(val);
|
|
8182
|
-
break;
|
|
8183
|
-
case "Not Contains":
|
|
8184
|
-
orCondition = !Condition.attribute(index).regexp(new RegExp(`^(?!.*${val}).*$`));
|
|
8185
|
-
break;
|
|
8186
|
-
case "Contains":
|
|
8187
|
-
orCondition = Condition.attribute(index).regexp(val);
|
|
8188
|
-
break;
|
|
8189
|
-
case "Greater Than":
|
|
8190
|
-
orCondition = Condition.attribute(index).gte(val);
|
|
8191
|
-
break;
|
|
8192
|
-
case "Less Than":
|
|
8193
|
-
orCondition = Condition.attribute(index).lte(val);
|
|
8194
|
-
break;
|
|
8195
|
-
}
|
|
8196
|
-
_condition = (!_condition ?
|
|
8197
|
-
orCondition : _condition.and(orCondition));
|
|
8198
|
-
});
|
|
8199
|
-
this.sortBy = sort?.value || this.pk;
|
|
8200
|
-
this.sortDirection = sort?.direction || this.sortDirection;
|
|
8214
|
+
async handleAction(action, event, target) {
|
|
8215
|
+
event.stopImmediatePropagation();
|
|
8216
|
+
if (this.actionMenuOpen)
|
|
8217
|
+
await this.actionMenuComponent.dismiss();
|
|
8218
|
+
// forcing trap focus
|
|
8219
|
+
removeFocusTrap();
|
|
8220
|
+
if (!this.route) {
|
|
8221
|
+
const event = { target: target, action, pk: this.pk, data: this.uid, name: EventConstants.CLICK, component: this.componentName };
|
|
8222
|
+
windowEventEmitter(`ListItem${EventConstants.CLICK}`, event);
|
|
8223
|
+
return this.clickEvent.emit(event);
|
|
8201
8224
|
}
|
|
8202
|
-
return
|
|
8225
|
+
return await this.redirect(action, (typeof this.uid === 'number' ? `${this.uid}` : this.uid));
|
|
8203
8226
|
}
|
|
8204
8227
|
/**
|
|
8205
|
-
* @description
|
|
8206
|
-
* @summary
|
|
8207
|
-
*
|
|
8208
|
-
*
|
|
8228
|
+
* @description Responsive handler that enables or disables slide items based on screen size and operations.
|
|
8229
|
+
* @summary This method is automatically called when the window is resized and also during component
|
|
8230
|
+
* initialization. It determines whether slide actions should be available based on the current
|
|
8231
|
+
* window width and the presence of UPDATE or DELETE operations. Slide items are typically hidden
|
|
8232
|
+
* on larger screens where there's space for dedicated action buttons.
|
|
8209
8233
|
*
|
|
8210
|
-
* @
|
|
8211
|
-
* @param {KeyValue[] | Paginator} result - The raw query result
|
|
8212
|
-
* @returns {KeyValue[]} The processed array of items
|
|
8234
|
+
* @return {boolean} True if slide items should be shown, false otherwise
|
|
8213
8235
|
*
|
|
8214
|
-
* @
|
|
8236
|
+
* @mermaid
|
|
8237
|
+
* sequenceDiagram
|
|
8238
|
+
* participant W as Window
|
|
8239
|
+
* participant L as ListItemComponent
|
|
8240
|
+
* participant U as UI
|
|
8241
|
+
*
|
|
8242
|
+
* W->>L: resize event
|
|
8243
|
+
* L->>W: getWindowWidth()
|
|
8244
|
+
* W-->>L: Return current width
|
|
8245
|
+
* L->>L: Store windowWidth
|
|
8246
|
+
* alt No operations OR width > 639px
|
|
8247
|
+
* L->>U: showSlideItems = false
|
|
8248
|
+
* else Operations include UPDATE/DELETE
|
|
8249
|
+
* L->>U: showSlideItems = true
|
|
8250
|
+
* end
|
|
8251
|
+
* L-->>U: Return showSlideItems value
|
|
8252
|
+
*
|
|
8253
|
+
* @memberOf ListItemComponent
|
|
8215
8254
|
*/
|
|
8216
|
-
|
|
8217
|
-
|
|
8218
|
-
|
|
8219
|
-
|
|
8220
|
-
|
|
8221
|
-
|
|
8222
|
-
this.getMoreData(paginator.total);
|
|
8223
|
-
}
|
|
8224
|
-
catch (error) {
|
|
8225
|
-
this.logger.info(error?.message || 'Unable to get page from paginator. Return empty array from component');
|
|
8226
|
-
result = [];
|
|
8227
|
-
}
|
|
8228
|
-
}
|
|
8229
|
-
else {
|
|
8230
|
-
this.getMoreData(result?.length || 0);
|
|
8231
|
-
}
|
|
8232
|
-
return (Object.keys(this.mapper || {}).length) ?
|
|
8233
|
-
this.mapResults(result) : result;
|
|
8255
|
+
enableSlideItems() {
|
|
8256
|
+
this.windowWidth = getWindowWidth();
|
|
8257
|
+
if (!this.operations?.length || this.windowWidth > 639)
|
|
8258
|
+
return this.showSlideItems = false;
|
|
8259
|
+
this.showSlideItems = this.operations.includes(OperationKeys.UPDATE) || this.operations.includes(OperationKeys.DELETE);
|
|
8260
|
+
return this.showSlideItems;
|
|
8234
8261
|
}
|
|
8235
8262
|
/**
|
|
8236
|
-
* @description
|
|
8237
|
-
* @summary
|
|
8238
|
-
*
|
|
8239
|
-
*
|
|
8263
|
+
* @description Animates and removes an element from the DOM.
|
|
8264
|
+
* @summary This method applies CSS animation classes to create a smooth fade-out effect
|
|
8265
|
+
* before removing the element from the DOM. The animation enhances user experience by
|
|
8266
|
+
* providing visual feedback when items are deleted or removed from lists. The timing
|
|
8267
|
+
* is coordinated with the CSS animation duration to ensure the element is removed
|
|
8268
|
+
* after the animation completes.
|
|
8240
8269
|
*
|
|
8241
|
-
* @param {
|
|
8242
|
-
* @
|
|
8270
|
+
* @param {HTMLElement} element - The DOM element to animate and remove
|
|
8271
|
+
* @return {void}
|
|
8243
8272
|
*
|
|
8244
|
-
* @
|
|
8273
|
+
* @mermaid
|
|
8274
|
+
* sequenceDiagram
|
|
8275
|
+
* participant L as ListItemComponent
|
|
8276
|
+
* participant E as HTMLElement
|
|
8277
|
+
* participant D as DOM
|
|
8278
|
+
*
|
|
8279
|
+
* L->>E: Add animation classes
|
|
8280
|
+
* Note over E: uk-animation-fade, uk-animation-medium, uk-animation-reverse
|
|
8281
|
+
* E->>E: Start fade animation
|
|
8282
|
+
* L->>L: setTimeout(600ms)
|
|
8283
|
+
* Note over L: Wait for animation to complete
|
|
8284
|
+
* L->>D: element.remove()
|
|
8285
|
+
* D->>D: Remove element from DOM
|
|
8286
|
+
*
|
|
8287
|
+
* @memberOf ListItemComponent
|
|
8245
8288
|
*/
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
length = length * this.limit;
|
|
8250
|
-
if (length <= this.limit) {
|
|
8251
|
-
this.loadMoreData = false;
|
|
8252
|
-
}
|
|
8253
|
-
else {
|
|
8254
|
-
this.pages = Math.floor(length / this.limit);
|
|
8255
|
-
if ((this.pages * this.limit) < length)
|
|
8256
|
-
this.pages += 1;
|
|
8257
|
-
if (this.pages === 1)
|
|
8258
|
-
this.loadMoreData = false;
|
|
8259
|
-
}
|
|
8260
|
-
}
|
|
8261
|
-
else {
|
|
8262
|
-
this.pages = length;
|
|
8263
|
-
if (this.pages === 1)
|
|
8264
|
-
this.loadMoreData = false;
|
|
8265
|
-
}
|
|
8289
|
+
removeElement(element) {
|
|
8290
|
+
element.classList.add('uk-animation-fade', 'uk-animation-medium', 'uk-animation-reverse');
|
|
8291
|
+
setTimeout(() => { element.remove(); }, 600);
|
|
8266
8292
|
}
|
|
8267
8293
|
/**
|
|
8268
|
-
* @description
|
|
8269
|
-
* @summary
|
|
8270
|
-
*
|
|
8271
|
-
*
|
|
8294
|
+
* @description Navigates to a new route based on the specified action and item ID.
|
|
8295
|
+
* @summary This method constructs a navigation URL using the component's route configuration,
|
|
8296
|
+
* the specified action, and an item identifier. It uses Ionic's NavController to perform
|
|
8297
|
+
* forward navigation with appropriate animations. This method is typically used for
|
|
8298
|
+
* CRUD operations where each action (create, read, update, delete) has its own route.
|
|
8272
8299
|
*
|
|
8273
|
-
* @
|
|
8274
|
-
* @param {
|
|
8275
|
-
* @
|
|
8276
|
-
* @param {KeyValue} [props] - Additional properties to include
|
|
8277
|
-
* @returns {KeyValue} The mapped item
|
|
8300
|
+
* @param {string} action - The action to be performed (e.g., 'edit', 'view', 'delete')
|
|
8301
|
+
* @param {string} [id] - The unique identifier of the item to be acted upon
|
|
8302
|
+
* @return {Promise<boolean>} A promise that resolves to true if navigation was successful
|
|
8278
8303
|
*
|
|
8279
|
-
* @
|
|
8304
|
+
* @mermaid
|
|
8305
|
+
* sequenceDiagram
|
|
8306
|
+
* participant L as ListItemComponent
|
|
8307
|
+
* participant N as NavController
|
|
8308
|
+
* participant R as Router
|
|
8309
|
+
*
|
|
8310
|
+
* L->>L: redirect(action, id)
|
|
8311
|
+
* L->>L: Construct URL: /{route}/{action}/{id}
|
|
8312
|
+
* L->>N: navigateForward(url)
|
|
8313
|
+
* N->>R: Navigate to constructed URL
|
|
8314
|
+
* R-->>N: Return navigation result
|
|
8315
|
+
* N-->>L: Return boolean success
|
|
8316
|
+
*
|
|
8317
|
+
* @memberOf ListItemComponent
|
|
8280
8318
|
*/
|
|
8281
|
-
|
|
8282
|
-
return
|
|
8283
|
-
const arrayValue = value.split('.');
|
|
8284
|
-
if (!value) {
|
|
8285
|
-
accum[key] = value;
|
|
8286
|
-
}
|
|
8287
|
-
else {
|
|
8288
|
-
if (arrayValue.length === 1) {
|
|
8289
|
-
value = item?.[value] ? item[value] : value !== key ? value : "";
|
|
8290
|
-
if (isValidDate(value))
|
|
8291
|
-
value = `${formatDate(value)}`;
|
|
8292
|
-
accum[key] = value;
|
|
8293
|
-
}
|
|
8294
|
-
else {
|
|
8295
|
-
let val;
|
|
8296
|
-
for (const _value of arrayValue)
|
|
8297
|
-
val = !val
|
|
8298
|
-
? item[_value]
|
|
8299
|
-
: (typeof val === 'string' ? JSON.parse(val) : val)[_value];
|
|
8300
|
-
if (isValidDate(new Date(val)))
|
|
8301
|
-
val = `${formatDate(val)}`;
|
|
8302
|
-
accum[key] = val === null || val === undefined ? value : val;
|
|
8303
|
-
}
|
|
8304
|
-
}
|
|
8305
|
-
return Object.assign({}, props || {}, accum);
|
|
8306
|
-
}, {});
|
|
8319
|
+
async redirect(action, id) {
|
|
8320
|
+
return await this.navController.navigateForward(`/${this.route}/${action}/${id || this.uid}`);
|
|
8307
8321
|
}
|
|
8308
8322
|
/**
|
|
8309
|
-
* @description
|
|
8310
|
-
* @summary
|
|
8311
|
-
*
|
|
8312
|
-
*
|
|
8323
|
+
* @description Presents the actions menu popover for the list item.
|
|
8324
|
+
* @summary This method handles the display of a contextual action menu when triggered by user
|
|
8325
|
+
* interaction (typically a long press or right-click). It stops event propagation to prevent
|
|
8326
|
+
* unwanted side effects, removes any existing focus traps for accessibility, configures the
|
|
8327
|
+
* popover with the triggering event, and opens the action menu. The menu typically contains
|
|
8328
|
+
* available CRUD operations for the item.
|
|
8313
8329
|
*
|
|
8314
|
-
* @param {
|
|
8315
|
-
* @
|
|
8330
|
+
* @param {Event} event - The event that triggered the action menu request
|
|
8331
|
+
* @return {void}
|
|
8316
8332
|
*
|
|
8317
|
-
* @
|
|
8333
|
+
* @mermaid
|
|
8334
|
+
* sequenceDiagram
|
|
8335
|
+
* participant U as User
|
|
8336
|
+
* participant L as ListItemComponent
|
|
8337
|
+
* participant P as Popover
|
|
8338
|
+
* participant A as Accessibility
|
|
8339
|
+
*
|
|
8340
|
+
* U->>L: Trigger action menu (long press/right-click)
|
|
8341
|
+
* L->>L: stopImmediatePropagation()
|
|
8342
|
+
* L->>A: removeFocusTrap()
|
|
8343
|
+
* L->>P: Set event reference
|
|
8344
|
+
* L->>L: actionMenuOpen = true
|
|
8345
|
+
* L->>P: Display popover with actions
|
|
8346
|
+
*
|
|
8347
|
+
* @memberOf ListItemComponent
|
|
8318
8348
|
*/
|
|
8319
|
-
|
|
8320
|
-
|
|
8321
|
-
|
|
8322
|
-
|
|
8323
|
-
this.
|
|
8324
|
-
|
|
8325
|
-
operations: this.operations,
|
|
8326
|
-
route: this.route,
|
|
8327
|
-
...Object.keys(this.item).reduce((acc, key) => {
|
|
8328
|
-
acc[key] = this.item[key];
|
|
8329
|
-
return acc;
|
|
8330
|
-
}, {}),
|
|
8331
|
-
// ... (!this.item.render ? {} : Object.keys(this.item).reduce((acc: KeyValue, key: string) => {
|
|
8332
|
-
// acc[key] = this.item[key as keyof IListItemProp];
|
|
8333
|
-
// return acc;
|
|
8334
|
-
// }, {}))
|
|
8335
|
-
});
|
|
8336
|
-
return data.reduce((accum, curr) => {
|
|
8337
|
-
accum.push({ ...this.itemMapper(curr, this.mapper, props), ...{ pk: this.pk } });
|
|
8338
|
-
return accum;
|
|
8339
|
-
}, []);
|
|
8349
|
+
presentActionsMenu(event) {
|
|
8350
|
+
event.stopImmediatePropagation();
|
|
8351
|
+
// forcing trap focus
|
|
8352
|
+
removeFocusTrap();
|
|
8353
|
+
this.actionMenuComponent.event = event;
|
|
8354
|
+
this.actionMenuOpen = true;
|
|
8340
8355
|
}
|
|
8341
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8342
|
-
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"] }] }); }
|
|
8356
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ListItemComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8357
|
+
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" }] }); }
|
|
8343
8358
|
};
|
|
8344
|
-
|
|
8359
|
+
ListItemComponent = __decorate([
|
|
8345
8360
|
Dynamic(),
|
|
8346
8361
|
__metadata("design:paramtypes", [])
|
|
8347
|
-
],
|
|
8348
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8362
|
+
], ListItemComponent);
|
|
8363
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ListItemComponent, decorators: [{
|
|
8349
8364
|
type: Component,
|
|
8350
|
-
args: [{ selector: 'ngx-decaf-list', standalone: true, imports: [
|
|
8365
|
+
args: [{ selector: 'ngx-decaf-list-item', standalone: true, imports: [
|
|
8351
8366
|
TranslatePipe,
|
|
8352
|
-
IonRefresher,
|
|
8353
|
-
IonLoading,
|
|
8354
|
-
PaginationComponent,
|
|
8355
8367
|
IonList,
|
|
8368
|
+
IonListHeader,
|
|
8356
8369
|
IonItem,
|
|
8357
|
-
|
|
8358
|
-
|
|
8370
|
+
IonItemSliding,
|
|
8371
|
+
IonItemOptions,
|
|
8372
|
+
IonItemOption,
|
|
8373
|
+
IonIcon,
|
|
8359
8374
|
IonLabel,
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
|
|
8363
|
-
IonInfiniteScrollContent,
|
|
8364
|
-
|
|
8365
|
-
|
|
8366
|
-
|
|
8367
|
-
EmptyStateComponent,
|
|
8368
|
-
ListItemComponent,
|
|
8369
|
-
FilterComponent,
|
|
8370
|
-
ComponentRendererComponent
|
|
8371
|
-
], 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"] }]
|
|
8372
|
-
}], ctorParameters: () => [], propDecorators: { type: [{
|
|
8373
|
-
type: Input
|
|
8374
|
-
}], translatable: [{
|
|
8375
|
-
type: Input
|
|
8376
|
-
}], showSearchbar: [{
|
|
8377
|
-
type: Input
|
|
8378
|
-
}], data: [{
|
|
8379
|
-
type: Input
|
|
8380
|
-
}], source: [{
|
|
8381
|
-
type: Input
|
|
8382
|
-
}], start: [{
|
|
8383
|
-
type: Input
|
|
8384
|
-
}], limit: [{
|
|
8385
|
-
type: Input
|
|
8386
|
-
}], loadMoreData: [{
|
|
8387
|
-
type: Input
|
|
8375
|
+
IonButton,
|
|
8376
|
+
IonContent,
|
|
8377
|
+
IonPopover
|
|
8378
|
+
], 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"] }]
|
|
8379
|
+
}], ctorParameters: () => [], propDecorators: { actionMenuComponent: [{
|
|
8380
|
+
type: ViewChild,
|
|
8381
|
+
args: ['actionMenuComponent']
|
|
8388
8382
|
}], lines: [{
|
|
8389
8383
|
type: Input
|
|
8390
|
-
}],
|
|
8391
|
-
type: Input
|
|
8392
|
-
}], scrollThreshold: [{
|
|
8393
|
-
type: Input
|
|
8394
|
-
}], scrollPosition: [{
|
|
8395
|
-
type: Input
|
|
8396
|
-
}], loadingText: [{
|
|
8397
|
-
type: Input
|
|
8398
|
-
}], showRefresher: [{
|
|
8384
|
+
}], item: [{
|
|
8399
8385
|
type: Input
|
|
8400
|
-
}],
|
|
8386
|
+
}], icon: [{
|
|
8401
8387
|
type: Input
|
|
8402
|
-
}],
|
|
8388
|
+
}], iconSlot: [{
|
|
8403
8389
|
type: Input
|
|
8404
|
-
}],
|
|
8390
|
+
}], button: [{
|
|
8405
8391
|
type: Input
|
|
8406
|
-
}],
|
|
8392
|
+
}], title: [{
|
|
8407
8393
|
type: Input
|
|
8408
|
-
}],
|
|
8394
|
+
}], description: [{
|
|
8409
8395
|
type: Input
|
|
8410
|
-
}],
|
|
8396
|
+
}], info: [{
|
|
8411
8397
|
type: Input
|
|
8412
|
-
}],
|
|
8398
|
+
}], subinfo: [{
|
|
8413
8399
|
type: Input
|
|
8414
|
-
}], refreshEvent: [{
|
|
8415
|
-
type: Output
|
|
8416
8400
|
}], clickEvent: [{
|
|
8417
8401
|
type: Output
|
|
8418
|
-
}],
|
|
8419
|
-
type: HostListener,
|
|
8420
|
-
args: ['window:ListItemClickEvent', ['$event']]
|
|
8421
|
-
}], handleSearch: [{
|
|
8422
|
-
type: HostListener,
|
|
8423
|
-
args: ['window:searchbarEvent', ['$event']]
|
|
8424
|
-
}], refresh: [{
|
|
8402
|
+
}], enableSlideItems: [{
|
|
8425
8403
|
type: HostListener,
|
|
8426
|
-
args: ['window:
|
|
8404
|
+
args: ['window:resize', ['$event']]
|
|
8427
8405
|
}] } });
|
|
8428
8406
|
|
|
8429
8407
|
let SteppedFormComponent = class SteppedFormComponent {
|
|
@@ -8446,6 +8424,17 @@ let SteppedFormComponent = class SteppedFormComponent {
|
|
|
8446
8424
|
* @memberOf SteppedFormComponent
|
|
8447
8425
|
*/
|
|
8448
8426
|
this.pages = 1;
|
|
8427
|
+
/**
|
|
8428
|
+
* List of titles and descriptions for each page of the stepped form.
|
|
8429
|
+
* Each object in the array represents a page, containing a title and a description.
|
|
8430
|
+
*
|
|
8431
|
+
* @example
|
|
8432
|
+
* pageTitles = [
|
|
8433
|
+
* { title: 'Personal Information', description: 'Fill in your personal details.' },
|
|
8434
|
+
* { title: 'Address', description: 'Provide your residential address.' }
|
|
8435
|
+
* ];
|
|
8436
|
+
*/
|
|
8437
|
+
this.pageTitles = [];
|
|
8449
8438
|
/**
|
|
8450
8439
|
* @description The CRUD operation type for this form.
|
|
8451
8440
|
* @summary Defines the type of operation being performed (CREATE, READ, UPDATE, DELETE).
|
|
@@ -8534,7 +8523,6 @@ let SteppedFormComponent = class SteppedFormComponent {
|
|
|
8534
8523
|
*
|
|
8535
8524
|
* A->>S: ngOnInit()
|
|
8536
8525
|
* S->>S: Set activePage = startPage
|
|
8537
|
-
* S->>S: Process children into pagesArray
|
|
8538
8526
|
* S->>S: Calculate total pages
|
|
8539
8527
|
* S->>S: Assign page props to children
|
|
8540
8528
|
* S->>S: getCurrentFormGroup(activePage)
|
|
@@ -8547,14 +8535,9 @@ let SteppedFormComponent = class SteppedFormComponent {
|
|
|
8547
8535
|
if (!this.locale)
|
|
8548
8536
|
this.locale = getLocaleContext("SteppedFormComponent");
|
|
8549
8537
|
this.activePage = this.startPage;
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
acc[page] = [];
|
|
8554
|
-
acc[page].push({ index: page });
|
|
8555
|
-
return acc;
|
|
8556
|
-
}, []).filter(Boolean);
|
|
8557
|
-
this.pages = this.pagesArray.length;
|
|
8538
|
+
if (!this.pageTitles.length)
|
|
8539
|
+
this.pageTitles = Array.from({ length: this.pages }, () => ({ title: '', description: '' }));
|
|
8540
|
+
this.pages = this.pageTitles.length;
|
|
8558
8541
|
this.children = [...this.children.map((c) => {
|
|
8559
8542
|
if (!c.props)
|
|
8560
8543
|
c.props = {};
|
|
@@ -8563,6 +8546,7 @@ let SteppedFormComponent = class SteppedFormComponent {
|
|
|
8563
8546
|
c.props['page'] = page > this.pages ? this.pages : page;
|
|
8564
8547
|
return c;
|
|
8565
8548
|
})];
|
|
8549
|
+
console.log(this.pageTitles);
|
|
8566
8550
|
this.getCurrentFormGroup(this.activePage);
|
|
8567
8551
|
}
|
|
8568
8552
|
/**
|
|
@@ -8676,19 +8660,16 @@ let SteppedFormComponent = class SteppedFormComponent {
|
|
|
8676
8660
|
getCurrentFormGroup(page) {
|
|
8677
8661
|
this.activeFormGroup = this.formGroup.at(page - 1);
|
|
8678
8662
|
this.activeChildren = undefined;
|
|
8679
|
-
this.timerSubscription = timer(10).subscribe(() =>
|
|
8680
|
-
this.activeChildren = this.children.filter(c => c.props?.['page'] === page);
|
|
8681
|
-
console.log(this.activeChildren);
|
|
8682
|
-
});
|
|
8663
|
+
this.timerSubscription = timer(10).subscribe(() => this.activeChildren = this.children.filter(c => c.props?.['page'] === page));
|
|
8683
8664
|
}
|
|
8684
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8685
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "
|
|
8665
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SteppedFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
8666
|
+
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", pageTitles: "pageTitles", 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 class=\"dcf-grid dcf-grid-collapse skip\">\n @for(page of pageTitles; track $index;) {\n <div class=\"dcf-flex dcf-flex-middle\">\n <div class=\"dcf-step\" [class.dcf-active]=\"activePage === $index + 1\" [class.dcf-passed]=\"($index + 1) < activePage\">{{ $index + 1 }}</div>\n @if((page?.title || page?.description)) {\n <div class=\"dcf-information dcf-visible@s\">\n @if(page?.title) {\n <div class=\"dcf-title\">{{ page?.title | translate }}</div>\n }\n @if(page?.description) {\n <div class=\"dcf-description\">{{ page?.description | translate }}</div>\n }\n <div class=\"dcf-separator\"></div>\n </div>\n }\n @if($index < pageTitles.length - 1) {\n <div class=\"dcf-arrow-container\">\n <svg width=\"8\" height=\"12\" viewBox=\"0 0 8 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.5 1L6.5 6L1.5 11\" />\n </svg>\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n @if(pageTitles[activePage - 1]?.title || pageTitles[activePage - 1]?.description) {\n <div class=\"dcf-current-step\">\n <div>\n @if(pageTitles[activePage - 1]?.title) {\n <div class=\"dcf-title\">{{ pageTitles[activePage - 1]?.title | translate }}</div>\n }\n @if(pageTitles[activePage - 1]?.description) {\n <div class=\"dcf-description\">{{ pageTitles[activePage - 1]?.description | translate }}</div>\n }\n </div>\n </div>\n }\n\n\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 color=\"light\" (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=\"solid\" (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;align-items:center;margin-bottom:2rem;overflow-x:auto;flex-wrap:nowrap}.dcf-page-steps .dcf-grid{display:flex!important;flex-wrap:nowrap!important;align-items:center}.dcf-step{height:38px;min-width:38px;width:38px;background:var(--dcf-color-gray-2);margin:0;display:flex;color:var(--dcf-color-gray-7);justify-content:center;align-items:center;font-size:1rem;font-weight:600;border-radius:var(--dcf-border-radius)}.dcf-step.dcf-active{color:var(--dcf-color-light);background:var(--ion-color-primary);box-shadow:0 2px 6px #144c714d}.dcf-step.dcf-passed{color:var(--dcf-color-primary-shade);background:var(--dcf-color-gray-3)}.dcf-information{padding-left:.5rem}.dcf-title{font-size:.875rem;font-weight:600;margin:0;color:var(--dcf-color-gray-7)}.dcf-description{font-size:.8rem;font-weight:500;margin:0;margin-top:.25rem;color:var(--dcf-color-gray-4)}.dcf-arrow-container{display:flex;align-items:center;justify-content:center;padding:0 .5rem;height:38px}.dcf-arrow-container{display:flex;align-items:center;justify-content:center;padding:0 1rem;height:40px}.dcf-arrow-container svg{width:1rem;height:1rem;stroke:var(--dcf-color-gray-8);stroke-opacity:.7;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}ion-button[color=light]{--background: var(--dcf-color-gray-7) !important}.dcf-current-step{margin-top:-.5rem!important;margin-bottom:1.75rem!important;display:flex;align-items:center;justify-content:center}@media (min-width: 639px){.dcf-current-step{display:none}}\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: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "globals", "children", "model", "parent"], outputs: ["listenEvent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
8686
8667
|
};
|
|
8687
8668
|
SteppedFormComponent = __decorate([
|
|
8688
8669
|
Dynamic(),
|
|
8689
8670
|
__metadata("design:paramtypes", [])
|
|
8690
8671
|
], SteppedFormComponent);
|
|
8691
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8672
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: SteppedFormComponent, decorators: [{
|
|
8692
8673
|
type: Component,
|
|
8693
8674
|
args: [{ selector: 'ngx-decaf-stepped-form', imports: [
|
|
8694
8675
|
TranslatePipe,
|
|
@@ -8696,14 +8677,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
8696
8677
|
IonSkeletonText,
|
|
8697
8678
|
IonText,
|
|
8698
8679
|
IonButton,
|
|
8699
|
-
IonIcon,
|
|
8700
|
-
ModelRendererComponent,
|
|
8701
8680
|
ComponentRendererComponent
|
|
8702
|
-
], standalone: true, template: "<form class=\"dcf-steped-form\" novalidate>\n <div class=\"dcf-page-steps\">\n <div>\n
|
|
8681
|
+
], standalone: true, template: "<form class=\"dcf-steped-form\" novalidate>\n <div class=\"dcf-page-steps\">\n <div class=\"dcf-grid dcf-grid-collapse skip\">\n @for(page of pageTitles; track $index;) {\n <div class=\"dcf-flex dcf-flex-middle\">\n <div class=\"dcf-step\" [class.dcf-active]=\"activePage === $index + 1\" [class.dcf-passed]=\"($index + 1) < activePage\">{{ $index + 1 }}</div>\n @if((page?.title || page?.description)) {\n <div class=\"dcf-information dcf-visible@s\">\n @if(page?.title) {\n <div class=\"dcf-title\">{{ page?.title | translate }}</div>\n }\n @if(page?.description) {\n <div class=\"dcf-description\">{{ page?.description | translate }}</div>\n }\n <div class=\"dcf-separator\"></div>\n </div>\n }\n @if($index < pageTitles.length - 1) {\n <div class=\"dcf-arrow-container\">\n <svg width=\"8\" height=\"12\" viewBox=\"0 0 8 12\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M1.5 1L6.5 6L1.5 11\" />\n </svg>\n </div>\n }\n </div>\n }\n </div>\n </div>\n\n @if(pageTitles[activePage - 1]?.title || pageTitles[activePage - 1]?.description) {\n <div class=\"dcf-current-step\">\n <div>\n @if(pageTitles[activePage - 1]?.title) {\n <div class=\"dcf-title\">{{ pageTitles[activePage - 1]?.title | translate }}</div>\n }\n @if(pageTitles[activePage - 1]?.description) {\n <div class=\"dcf-description\">{{ pageTitles[activePage - 1]?.description | translate }}</div>\n }\n </div>\n </div>\n }\n\n\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 color=\"light\" (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=\"solid\" (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;align-items:center;margin-bottom:2rem;overflow-x:auto;flex-wrap:nowrap}.dcf-page-steps .dcf-grid{display:flex!important;flex-wrap:nowrap!important;align-items:center}.dcf-step{height:38px;min-width:38px;width:38px;background:var(--dcf-color-gray-2);margin:0;display:flex;color:var(--dcf-color-gray-7);justify-content:center;align-items:center;font-size:1rem;font-weight:600;border-radius:var(--dcf-border-radius)}.dcf-step.dcf-active{color:var(--dcf-color-light);background:var(--ion-color-primary);box-shadow:0 2px 6px #144c714d}.dcf-step.dcf-passed{color:var(--dcf-color-primary-shade);background:var(--dcf-color-gray-3)}.dcf-information{padding-left:.5rem}.dcf-title{font-size:.875rem;font-weight:600;margin:0;color:var(--dcf-color-gray-7)}.dcf-description{font-size:.8rem;font-weight:500;margin:0;margin-top:.25rem;color:var(--dcf-color-gray-4)}.dcf-arrow-container{display:flex;align-items:center;justify-content:center;padding:0 .5rem;height:38px}.dcf-arrow-container{display:flex;align-items:center;justify-content:center;padding:0 1rem;height:40px}.dcf-arrow-container svg{width:1rem;height:1rem;stroke:var(--dcf-color-gray-8);stroke-opacity:.7;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}ion-button[color=light]{--background: var(--dcf-color-gray-7) !important}.dcf-current-step{margin-top:-.5rem!important;margin-bottom:1.75rem!important;display:flex;align-items:center;justify-content:center}@media (min-width: 639px){.dcf-current-step{display:none}}\n"] }]
|
|
8703
8682
|
}], ctorParameters: () => [], propDecorators: { locale: [{
|
|
8704
8683
|
type: Input
|
|
8705
8684
|
}], pages: [{
|
|
8706
8685
|
type: Input
|
|
8686
|
+
}], pageTitles: [{
|
|
8687
|
+
type: Input
|
|
8707
8688
|
}], operation: [{
|
|
8708
8689
|
type: Input
|
|
8709
8690
|
}], startPage: [{
|
|
@@ -8732,10 +8713,10 @@ class CollapsableDirective {
|
|
|
8732
8713
|
}
|
|
8733
8714
|
}
|
|
8734
8715
|
}
|
|
8735
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8736
|
-
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "
|
|
8716
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CollapsableDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
8717
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.2", type: CollapsableDirective, isStandalone: true, selector: "[decafCollapsable]", ngImport: i0 }); }
|
|
8737
8718
|
}
|
|
8738
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8719
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: CollapsableDirective, decorators: [{
|
|
8739
8720
|
type: Directive,
|
|
8740
8721
|
args: [{
|
|
8741
8722
|
selector: '[decafCollapsable]',
|
|
@@ -8761,8 +8742,8 @@ const Components = [
|
|
|
8761
8742
|
SteppedFormComponent
|
|
8762
8743
|
];
|
|
8763
8744
|
class ForAngularComponentsModule {
|
|
8764
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "
|
|
8765
|
-
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "
|
|
8745
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ForAngularComponentsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
|
|
8746
|
+
static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "20.3.2", ngImport: i0, type: ForAngularComponentsModule, imports: [ModelRendererComponent,
|
|
8766
8747
|
ComponentRendererComponent,
|
|
8767
8748
|
CrudFieldComponent,
|
|
8768
8749
|
CrudFormComponent,
|
|
@@ -8789,7 +8770,7 @@ class ForAngularComponentsModule {
|
|
|
8789
8770
|
LayoutComponent,
|
|
8790
8771
|
FilterComponent,
|
|
8791
8772
|
SteppedFormComponent, CollapsableDirective] }); }
|
|
8792
|
-
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "
|
|
8773
|
+
static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ForAngularComponentsModule, imports: [CrudFieldComponent,
|
|
8793
8774
|
CrudFormComponent,
|
|
8794
8775
|
EmptyStateComponent,
|
|
8795
8776
|
ListComponent,
|
|
@@ -8801,7 +8782,7 @@ class ForAngularComponentsModule {
|
|
|
8801
8782
|
FilterComponent,
|
|
8802
8783
|
SteppedFormComponent] }); }
|
|
8803
8784
|
}
|
|
8804
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
8785
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.2", ngImport: i0, type: ForAngularComponentsModule, decorators: [{
|
|
8805
8786
|
type: NgModule,
|
|
8806
8787
|
args: [{
|
|
8807
8788
|
imports: [...Components, ...Directives],
|
|
@@ -8825,5 +8806,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
8825
8806
|
* Generated bundle index. Do not edit.
|
|
8826
8807
|
*/
|
|
8827
8808
|
|
|
8828
|
-
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,
|
|
8809
|
+
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 };
|
|
8829
8810
|
//# sourceMappingURL=decaf-ts-for-angular.mjs.map
|