@decaf-ts/for-angular 0.1.17 → 0.1.20
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 +473 -141
- package/fesm2022/decaf-ts-for-angular.mjs.map +1 -1
- package/index.d.ts +511 -189
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { parseValueByType, HTML5InputTypes, UIKeys, HTML5CheckTypes, escapeHtml, parseToNumber, RenderingEngine, DecafTranslateService, DecafComponent, ComponentEventNames, UIValidator, RenderingError, UIMediaBreakPoints, LayoutGridGaps, ElementSizes, DecafEventHandler } from '@decaf-ts/ui-decorators';
|
|
2
2
|
import * as i0 from '@angular/core';
|
|
3
|
-
import { InjectionToken, isDevMode, provideEnvironmentInitializer, reflectComponentType, Injector, createEnvironmentInjector, runInInjectionContext, createComponent, inject,
|
|
3
|
+
import { InjectionToken, isDevMode, provideEnvironmentInitializer, reflectComponentType, Injector, createEnvironmentInjector, runInInjectionContext, createComponent, inject, NgZone, Injectable, Input, Directive, signal, ChangeDetectorRef, EnvironmentInjector, Renderer2, EventEmitter, ElementRef, Output, ViewChild, Inject, ViewContainerRef, TemplateRef, Component, ViewEncapsulation, HostListener, Pipe, NgModule } from '@angular/core';
|
|
4
4
|
import * as i1$1 from '@angular/common';
|
|
5
5
|
import { Location, NgComponentOutlet, CommonModule } from '@angular/common';
|
|
6
6
|
import { ValidationKeys, DEFAULT_PATTERNS, VALIDATION_PARENT_KEY, Primitives, Model, Validation, ComparisonValidationKeys, PathProxyEngine, ModelKeys, isValidDate as isValidDate$1, parseDate, sf as sf$1, ReservedModels } from '@decaf-ts/decorator-validation';
|
|
@@ -842,6 +842,10 @@ function getMenuIcon(label, menu) {
|
|
|
842
842
|
const item = menu.find((m) => m.label?.toLowerCase() === label.toLowerCase());
|
|
843
843
|
return item?.icon || '';
|
|
844
844
|
}
|
|
845
|
+
function dateFromString(value) {
|
|
846
|
+
const dateArray = value.includes('T') ? value.split('T') : value.split(' ');
|
|
847
|
+
return new Date(dateArray.length === 1 ? `${value}T00:00:00` : value);
|
|
848
|
+
}
|
|
845
849
|
|
|
846
850
|
function getDbAdapterFlavour() {
|
|
847
851
|
return (getOnWindow(DB_ADAPTER_FLAVOUR_TOKEN) || '');
|
|
@@ -1612,11 +1616,7 @@ class NgxFormService {
|
|
|
1612
1616
|
const { name, childOf } = componentProps;
|
|
1613
1617
|
if (isMultiple)
|
|
1614
1618
|
componentProps['pk'] = componentProps['pk'] || parentProps?.['pk'] || '';
|
|
1615
|
-
const fullPath = childOf
|
|
1616
|
-
? isMultiple
|
|
1617
|
-
? `${childOf}.${index}.${name}`
|
|
1618
|
-
: `${childOf}.${name}`
|
|
1619
|
-
: name;
|
|
1619
|
+
const fullPath = childOf ? (isMultiple ? `${childOf}.${index}.${name}` : `${childOf}.${name}`) : name;
|
|
1620
1620
|
const [parentGroup, controlName] = this.resolveParentGroup(formGroup, fullPath, componentProps, parentProps);
|
|
1621
1621
|
if (!parentGroup.get(controlName)) {
|
|
1622
1622
|
const control = NgxFormService.fromProps(componentProps, componentProps.updateMode || 'change');
|
|
@@ -1793,9 +1793,7 @@ class NgxFormService {
|
|
|
1793
1793
|
* @static
|
|
1794
1794
|
*/
|
|
1795
1795
|
static addControlFromProps(id, props, parentProps) {
|
|
1796
|
-
const componentPages = (typeof props?.pages === Primitives.NUMBER
|
|
1797
|
-
? props?.pages
|
|
1798
|
-
: props?.pages?.length);
|
|
1796
|
+
const componentPages = (typeof props?.pages === Primitives.NUMBER ? props?.pages : props?.pages?.length);
|
|
1799
1797
|
const parentPages = (typeof parentProps?.pages === Primitives.NUMBER
|
|
1800
1798
|
? parentProps?.pages
|
|
1801
1799
|
: parentProps?.pages?.length);
|
|
@@ -1806,9 +1804,7 @@ class NgxFormService {
|
|
|
1806
1804
|
const parentChildOf = parentProps?.childOf || '';
|
|
1807
1805
|
const index = props.page || parentProps?.page;
|
|
1808
1806
|
// dont check page in nested childs with same childOf
|
|
1809
|
-
if ((!(typeof index === 'number') || index === 0) &&
|
|
1810
|
-
childOf.length &&
|
|
1811
|
-
childOf !== parentChildOf)
|
|
1807
|
+
if ((!(typeof index === 'number') || index === 0) && childOf.length && childOf !== parentChildOf)
|
|
1812
1808
|
throw Error(`Property 'page' is required and greather than 0 on ${props.name}`);
|
|
1813
1809
|
// if(index > formLength) {
|
|
1814
1810
|
// if((form as KeyValue)?.['lastIndex'] && index === (form as KeyValue)['lastIndex']['page']) {
|
|
@@ -1875,18 +1871,19 @@ class NgxFormService {
|
|
|
1875
1871
|
const parentProps = NgxFormService.getPropsFromControl(formGroup);
|
|
1876
1872
|
for (const key in formGroup.controls) {
|
|
1877
1873
|
const control = formGroup.controls[key];
|
|
1874
|
+
const props = NgxFormService.getPropsFromControl(control);
|
|
1878
1875
|
if (!(control instanceof FormControl)) {
|
|
1879
1876
|
if (control.disabled) {
|
|
1880
|
-
if (control instanceof FormGroup)
|
|
1877
|
+
if (control instanceof FormGroup) {
|
|
1878
|
+
const hasValue = this.controlHasValue(control);
|
|
1879
|
+
if (!hasValue) {
|
|
1880
|
+
continue;
|
|
1881
|
+
}
|
|
1881
1882
|
data[key] = NgxFormService.getFormData(control);
|
|
1883
|
+
continue;
|
|
1884
|
+
}
|
|
1882
1885
|
if (control instanceof FormArray) {
|
|
1883
|
-
const value = control
|
|
1884
|
-
.map((c) => {
|
|
1885
|
-
if (Object.values(c.value).some((p) => p !== undefined && String(p).trim() !== ''))
|
|
1886
|
-
return c.value;
|
|
1887
|
-
return undefined;
|
|
1888
|
-
})
|
|
1889
|
-
.filter((v) => v !== undefined);
|
|
1886
|
+
const value = this.getFormArrayControlsValue(control);
|
|
1890
1887
|
if (Array.isArray(value)) {
|
|
1891
1888
|
if (value.length > 0) {
|
|
1892
1889
|
data[key] = value.reduce((acc, curr, i) => {
|
|
@@ -1902,9 +1899,9 @@ class NgxFormService {
|
|
|
1902
1899
|
}
|
|
1903
1900
|
const value = control.value;
|
|
1904
1901
|
const isValid = control.valid;
|
|
1905
|
-
if (parentProps
|
|
1902
|
+
if (parentProps?.multiple) {
|
|
1906
1903
|
if (isValid) {
|
|
1907
|
-
data[key] = value;
|
|
1904
|
+
data[key] = Array.isArray(value) ? value : [value];
|
|
1908
1905
|
}
|
|
1909
1906
|
else {
|
|
1910
1907
|
this.reset(control);
|
|
@@ -1914,7 +1911,6 @@ class NgxFormService {
|
|
|
1914
1911
|
data[key] = NgxFormService.getFormData(control);
|
|
1915
1912
|
continue;
|
|
1916
1913
|
}
|
|
1917
|
-
const props = NgxFormService.getPropsFromControl(control);
|
|
1918
1914
|
// const { readonly } = (props as IFormComponentProperties) || false; TODO: dont send readonly fields?
|
|
1919
1915
|
let value = control.value;
|
|
1920
1916
|
if (!HTML5CheckTypes.includes(props['type'])) {
|
|
@@ -1924,7 +1920,7 @@ class NgxFormService {
|
|
|
1924
1920
|
break;
|
|
1925
1921
|
case HTML5InputTypes.DATE:
|
|
1926
1922
|
case HTML5InputTypes.DATETIME_LOCAL:
|
|
1927
|
-
value = typeof value === Primitives.STRING ?
|
|
1923
|
+
value = typeof value === Primitives.STRING ? dateFromString(value) : value;
|
|
1928
1924
|
break;
|
|
1929
1925
|
default:
|
|
1930
1926
|
value = !isNaN(value) ? value : escapeHtml(value)?.trim();
|
|
@@ -1932,14 +1928,23 @@ class NgxFormService {
|
|
|
1932
1928
|
}
|
|
1933
1929
|
else {
|
|
1934
1930
|
if (props['type'] === HTML5InputTypes.CHECKBOX)
|
|
1935
|
-
value =
|
|
1936
|
-
Array.isArray(value) || typeof value === Primitives.STRING ? value : (value ?? false);
|
|
1931
|
+
value = Array.isArray(value) || typeof value === Primitives.STRING ? value : (value ?? false);
|
|
1937
1932
|
}
|
|
1938
1933
|
data[key] = value;
|
|
1939
1934
|
}
|
|
1940
1935
|
NgxFormService.enableAllGroupControls(formGroup);
|
|
1941
1936
|
return data;
|
|
1942
1937
|
}
|
|
1938
|
+
static getFormArrayControlsValue(formArray) {
|
|
1939
|
+
return formArray.controls
|
|
1940
|
+
.map((c) => {
|
|
1941
|
+
return this.controlHasValue(c) ? c.value : undefined;
|
|
1942
|
+
})
|
|
1943
|
+
.filter((v) => v !== undefined);
|
|
1944
|
+
}
|
|
1945
|
+
static controlHasValue(control) {
|
|
1946
|
+
return Object.values(control.value).some((p) => p !== undefined && String(p).trim() !== '');
|
|
1947
|
+
}
|
|
1943
1948
|
/**
|
|
1944
1949
|
* @description Validates fields in a form control or form group.
|
|
1945
1950
|
* @summary Recursively validates all fields in a form control or form group, marking them as touched and dirty.
|
|
@@ -3227,26 +3232,6 @@ function provideDecafI18nConfig(config = { fallbackLang: 'en', lang: 'en' }, res
|
|
|
3227
3232
|
provideDecafI18nLoader(resources, versionedSuffix),
|
|
3228
3233
|
];
|
|
3229
3234
|
}
|
|
3230
|
-
class DecafTranslatePipe {
|
|
3231
|
-
constructor() {
|
|
3232
|
-
this.translate = inject(TranslateService);
|
|
3233
|
-
}
|
|
3234
|
-
transform(value, ...args) {
|
|
3235
|
-
if (I18nLoader.enabled && value) {
|
|
3236
|
-
return this.translate.instant(value, ...args);
|
|
3237
|
-
}
|
|
3238
|
-
return `<div class="dcf-translation-key">${sf(value, args)}</div>`;
|
|
3239
|
-
}
|
|
3240
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DecafTranslatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
3241
|
-
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.17", ngImport: i0, type: DecafTranslatePipe, isStandalone: true, name: "translate", pure: false }); }
|
|
3242
|
-
}
|
|
3243
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DecafTranslatePipe, decorators: [{
|
|
3244
|
-
type: Pipe,
|
|
3245
|
-
args: [{
|
|
3246
|
-
name: 'translate',
|
|
3247
|
-
pure: false,
|
|
3248
|
-
}]
|
|
3249
|
-
}] });
|
|
3250
3235
|
|
|
3251
3236
|
/**
|
|
3252
3237
|
* @module NgxMediaService
|
|
@@ -3650,8 +3635,11 @@ class NgxTranslateService extends DecafTranslateService {
|
|
|
3650
3635
|
instant(key, interpolateParams) {
|
|
3651
3636
|
return this.translateService.instant(key, interpolateParams);
|
|
3652
3637
|
}
|
|
3653
|
-
translate(key, params) {
|
|
3654
|
-
|
|
3638
|
+
async translate(key, params) {
|
|
3639
|
+
if (typeof params === Primitives.STRING) {
|
|
3640
|
+
params = { '0': params };
|
|
3641
|
+
}
|
|
3642
|
+
return firstValueFrom(this.translateService.instant(key, params));
|
|
3655
3643
|
}
|
|
3656
3644
|
async get(key, params) {
|
|
3657
3645
|
if (key) {
|
|
@@ -3909,10 +3897,11 @@ class NgxRepositoryDirective extends DecafComponent {
|
|
|
3909
3897
|
const handler = this.handlers?.[hook] || undefined;
|
|
3910
3898
|
const model = this.buildTransactionModel(data || {}, repository, operation);
|
|
3911
3899
|
if (handler && typeof handler === 'function') {
|
|
3912
|
-
const result =
|
|
3900
|
+
const result = await handler.bind(this)(model, repository, this.modelId);
|
|
3913
3901
|
if (result === false) {
|
|
3914
3902
|
return undefined;
|
|
3915
3903
|
}
|
|
3904
|
+
return result;
|
|
3916
3905
|
}
|
|
3917
3906
|
return model;
|
|
3918
3907
|
}
|
|
@@ -3926,7 +3915,7 @@ class NgxRepositoryDirective extends DecafComponent {
|
|
|
3926
3915
|
const hook = `after${operation.charAt(0).toUpperCase() + operation.slice(1)}`;
|
|
3927
3916
|
const handler = this.handlers?.[hook] || undefined;
|
|
3928
3917
|
if (handler && typeof handler === 'function') {
|
|
3929
|
-
const result =
|
|
3918
|
+
const result = await handler.bind(this)(model, repository, this.modelId);
|
|
3930
3919
|
if (result === false) {
|
|
3931
3920
|
return undefined;
|
|
3932
3921
|
}
|
|
@@ -5378,7 +5367,7 @@ class NgxModelPageDirective extends NgxPageDirective {
|
|
|
5378
5367
|
}
|
|
5379
5368
|
if (handler && role) {
|
|
5380
5369
|
this.handlers = handlers || {};
|
|
5381
|
-
return await handler.bind(this)(event, data || {}, role);
|
|
5370
|
+
return await handler.bind(this)(event, data || {}, this, role);
|
|
5382
5371
|
}
|
|
5383
5372
|
switch (name) {
|
|
5384
5373
|
case ComponentEventNames.Submit:
|
|
@@ -6515,12 +6504,70 @@ function Dynamic() {
|
|
|
6515
6504
|
// };
|
|
6516
6505
|
// }
|
|
6517
6506
|
|
|
6507
|
+
/**
|
|
6508
|
+
* @module lib/directives/NgxSvgDirective
|
|
6509
|
+
* @description Standalone directive that inlines SVG assets into the host element.
|
|
6510
|
+
* @summary Provides {@link NgxSvgDirective}, a lightweight Angular directive that resolves
|
|
6511
|
+
* an SVG file path from either its input binding or the host element's `src` attribute and
|
|
6512
|
+
* delegates the HTTP fetch and DOM injection to {@link NgxMediaService}.
|
|
6513
|
+
* @link {@link NgxSvgDirective}
|
|
6514
|
+
*/
|
|
6515
|
+
/**
|
|
6516
|
+
* @description Angular directive that fetches an SVG file and inlines it into the host element.
|
|
6517
|
+
* @summary Standalone directive bound to the `[ngx-decaf-svg]` attribute selector. On
|
|
6518
|
+
* initialisation it resolves the SVG asset path from the `[ngx-decaf-svg]` input binding or,
|
|
6519
|
+
* as a fallback, the host element's native `src` attribute. Once a non-empty path is determined
|
|
6520
|
+
* it calls {@link NgxMediaService.loadSvgObserver}, which performs the HTTP request via
|
|
6521
|
+
* {@link HttpClient} and injects the SVG markup directly into the host element's DOM, enabling
|
|
6522
|
+
* full CSS styling of the inlined SVG.
|
|
6523
|
+
* @class NgxSvgDirective
|
|
6524
|
+
* @implements {OnInit}
|
|
6525
|
+
* @example
|
|
6526
|
+
* ```html
|
|
6527
|
+
* <!-- Via directive binding -->
|
|
6528
|
+
* <div [ngx-decaf-svg]="'/assets/icons/logo.svg'"></div>
|
|
6529
|
+
*
|
|
6530
|
+
* <!-- Fallback to src attribute -->
|
|
6531
|
+
* <img ngx-decaf-svg src="/assets/icons/arrow.svg" />
|
|
6532
|
+
* ```
|
|
6533
|
+
*/
|
|
6518
6534
|
class NgxSvgDirective {
|
|
6519
6535
|
constructor() {
|
|
6536
|
+
/**
|
|
6537
|
+
* @description Service responsible for fetching and inlining the SVG markup.
|
|
6538
|
+
* @summary Injected {@link NgxMediaService} instance used by `ngOnInit` to perform the
|
|
6539
|
+
* HTTP request and inject the resulting SVG markup into the host element's DOM.
|
|
6540
|
+
* @type {NgxMediaService}
|
|
6541
|
+
* @memberOf module:lib/directives/NgxSvgDirective
|
|
6542
|
+
*/
|
|
6520
6543
|
this.mediaService = inject(NgxMediaService);
|
|
6544
|
+
/**
|
|
6545
|
+
* @description Reference to the host DOM element into which the SVG will be injected.
|
|
6546
|
+
* @summary Obtained via Angular's `inject(ElementRef)`. Provides access to the native
|
|
6547
|
+
* element forwarded to {@link NgxMediaService.loadSvgObserver} as the injection target,
|
|
6548
|
+
* and used as a fallback source for the `src` attribute when `path` is not set.
|
|
6549
|
+
* @type {ElementRef}
|
|
6550
|
+
* @memberOf module:lib/directives/NgxSvgDirective
|
|
6551
|
+
*/
|
|
6521
6552
|
this.element = inject(ElementRef);
|
|
6553
|
+
/**
|
|
6554
|
+
* @description HTTP client instance forwarded to the media service for the SVG fetch.
|
|
6555
|
+
* @summary Injected {@link HttpClient} passed directly to
|
|
6556
|
+
* {@link NgxMediaService.loadSvgObserver} so the service can issue the GET request for
|
|
6557
|
+
* the SVG file without managing its own HTTP dependency.
|
|
6558
|
+
* @type {HttpClient}
|
|
6559
|
+
* @memberOf module:lib/directives/NgxSvgDirective
|
|
6560
|
+
*/
|
|
6522
6561
|
this.http = inject(HttpClient);
|
|
6523
6562
|
}
|
|
6563
|
+
/**
|
|
6564
|
+
* @description Resolves the SVG path and triggers the inline load.
|
|
6565
|
+
* @summary Trims `path` and, when empty, falls back to the host element's `src` attribute.
|
|
6566
|
+
* When a valid path is found, delegates to {@link NgxMediaService.loadSvgObserver} to
|
|
6567
|
+
* fetch the file and inject the SVG markup into the host element.
|
|
6568
|
+
* @returns {void}
|
|
6569
|
+
* @memberOf module:lib/directives/NgxSvgDirective
|
|
6570
|
+
*/
|
|
6524
6571
|
ngOnInit() {
|
|
6525
6572
|
this.path = this.path?.trim() || this.element?.nativeElement?.getAttribute('src')?.trim() || '';
|
|
6526
6573
|
if (this.path) {
|
|
@@ -6534,7 +6581,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
6534
6581
|
type: Directive,
|
|
6535
6582
|
args: [{
|
|
6536
6583
|
selector: '[ngx-decaf-svg]',
|
|
6537
|
-
standalone: true
|
|
6584
|
+
standalone: true,
|
|
6538
6585
|
}]
|
|
6539
6586
|
}], propDecorators: { path: [{
|
|
6540
6587
|
type: Input,
|
|
@@ -6543,7 +6590,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
6543
6590
|
|
|
6544
6591
|
let IconComponent = class IconComponent {
|
|
6545
6592
|
constructor() {
|
|
6546
|
-
this.color =
|
|
6593
|
+
this.color = 'dark';
|
|
6547
6594
|
this.slot = 'icon-only';
|
|
6548
6595
|
this.button = false;
|
|
6549
6596
|
this.buttonFill = 'clear';
|
|
@@ -6568,7 +6615,7 @@ let IconComponent = class IconComponent {
|
|
|
6568
6615
|
this.type = 'icon';
|
|
6569
6616
|
this.name = `ti-${this.name.replace(/ti-/g, '')}`;
|
|
6570
6617
|
}
|
|
6571
|
-
this.mediaService.isDarkMode().subscribe(isDark => {
|
|
6618
|
+
this.mediaService.isDarkMode().subscribe((isDark) => {
|
|
6572
6619
|
this.isDarkMode = isDark;
|
|
6573
6620
|
});
|
|
6574
6621
|
this.initialized = true;
|
|
@@ -9704,7 +9751,7 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
|
|
|
9704
9751
|
return this.mapper;
|
|
9705
9752
|
}
|
|
9706
9753
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: FieldsetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
9707
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: FieldsetComponent, isStandalone: true, selector: "ngx-decaf-fieldset", inputs: { formControl: "formControl", customTypes: "customTypes", title: "title", description: "description", multiple: "multiple", value: "value", borders: "borders", max: "max", required: "required", ordenable: "ordenable", editable: "editable" }, usesInheritance: true, ngImport: i0, template: "@if (['create', 'update'].includes(operation) || !multiple) {\n <div\n [attr.role]=\"['create', 'update'].includes(operation) ? 'group' : 'region'\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.dcf-empty]=\"!items?.length\"\n [class.dcf-open]=\"isOpen\"\n #component\n >\n <div class=\"dcf-width-1-1\">\n <div>\n <div\n class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\"\n >\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create'].includes(operation) && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button\n fill=\"clear\"\n size=\"small\"\n (click)=\"handleClear($event)\"\n [class.dcf-invisible]=\"!isOpen\"\n [attr.aria-label]=\"\n (items?.length\n ? locale + '.clear_items'\n : locale + '.hidden_form'\n ) | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n [name]=\"'ti-' + (items?.length ? 'trash' : 'eye-off')\"\n />\n </ion-button>\n </div>\n }\n </div>\n </div>\n <div\n class=\"dcf-fieldset-content\"\n [class.dcf-empty]=\"!items?.length && !isOpen\"\n slot=\"content\"\n >\n @if (activePage) {\n <div\n class=\"dcf-animation dcf-animation-slide-top-small dcf-animation-fast\"\n [class.dcf-disabled]=\"!activePage\"\n >\n <ngx-decaf-layout\n [isModalChild]=\"isModalChild\"\n [className]=\"''\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [pk]=\"pk\"\n [modelId]=\"modelId\"\n [operation]=\"operation\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group\n [formGroup]=\"formGroup.parent\"\n [disabled]=\"updatingItem\"\n (ionItemReorder)=\"handleReorderItems($any($event))\"\n #accordionComponent\n >\n @for (\n item of items;\n track trackItemFn(item.index, item.title)\n ) {\n <ion-item\n [class.not-unique]=\"\n isUniqueError && item.title === isUniqueError\n \"\n [class.updating]=\"\n updatingItem?.['index'] === item.index - 1\n \"\n lines=\"full\"\n [button]=\"false\"\n [title]=\"item?.[pk] ?? pk + ': ' + item[pk]\"\n >\n @if (ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon\n aria-hidden=\"true\"\n name=\"swap-vertical-outline\"\n ></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon\n aria-hidden=\"true\"\n class=\"dcf-reorder-disabled\"\n size=\"small\"\n name=\"swap-vertical-outline\"\n disabled\n ></ion-icon>\n </div>\n }\n }\n\n <ion-label\n [color]=\"\n item.title === isUniqueError &&\n !updatingItem?.[pk] === item.title\n ? 'danger'\n : ''\n \"\n >\n {{ item.index }}.{{ item.title }}\n <!-- @if (ordenable) {\n {{ item.index }}.{{ item.title }}\n } @else {\n @if (item[pk]) {\n {{ pk }}: {{ item[pk] }} -\n }\n {{ item.title }}\n } -->\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">\n {{ item.description }}\n </ion-text>\n }\n </ion-label>\n @if (item.info?.length || item.subinfo?.length) {\n <ion-note slot=\"end\">\n @if (item.info?.length) {\n {{ item.info }}\n <br />\n }\n @if (item.subinfo) {\n {{ item.subinfo }}\n }\n </ion-note>\n }\n <div slot=\"end\">\n @if (editable) {\n @if (\n !updatingItem || updatingItem?.[pk] !== item.title\n ) {\n <ion-button\n fill=\"clear\"\n size=\"small\"\n (click)=\"handleUpdateItem($index)\"\n [attr.aria-label]=\"\n locale + '.edit_item' | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n size=\"small\"\n name=\"ti-cash-edit\"\n [color]=\"!isDarkMode ? 'dark' : 'light'\"\n ></ngx-decaf-icon>\n </ion-button>\n }\n }\n @if (!updatingItem) {\n <ion-button\n fill=\"clear\"\n size=\"small\"\n color=\"danger\"\n (click)=\"handleRemoveItem($index)\"\n [attr.aria-label]=\"\n locale + '.remove_item' | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n size=\"small\"\n name=\"ti-row-remove\"\n [color]=\"!isDarkMode ? 'dark' : 'light'\"\n />\n </ion-button>\n }\n </div>\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (isUniqueError) {\n <div\n class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\"\n >\n <div class=\"dcf-grid dcf-grid-collapse dcf-width-1-1\">\n <div\n class=\"dcf-auto\"\n [attr.style]=\"'max-width: 50px'\"\n >\n <ion-icon\n aria-hidden=\"true\"\n name=\"alert-circle-outline\"\n ></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text\n color=\"danger\"\n class=\"dcf-text-small\"\n >\n {{\n locale + '.not_unique'\n | translate: { value: isUniqueError }\n }}\n </ion-text>\n </div>\n </div>\n </div>\n }\n\n @if (max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text\n class=\"dcf-text-small\"\n [color]=\"\n items.length !== max\n ? !isDarkMode\n ? 'medium'\n : ''\n : 'primary'\n \"\n >\n {{\n locale +\n (items.length !== max ? '.max_items' : '.max_items_reached')\n | translate: { '0': max }\n }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\">\n @if (updatingItem) {\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n color=\"danger\"\n (click)=\"handleCancelUpdateItem()\"\n [attr.aria-label]=\"locale + '.cancel_update' | translate\"\n >\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n (click)=\"handleCreateItem()\"\n [attr.aria-label]=\"locale + '.update_item' | translate\"\n >\n <ion-icon\n aria-hidden=\"true\"\n name=\"refresh-outline\"\n slot=\"start\"\n ></ion-icon>\n {{ locale + '.update_item' | translate }}\n </ion-button>\n </div>\n } @else {\n @if (items.length < max || !max) {\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n class=\"dcf-button-add\"\n [color]=\"isDarkMode ? 'light' : 'dark'\"\n (click)=\"handleCreateItem()\"\n [attr.aria-label]=\"locale + '.create_item' | translate\"\n >\n <!-- <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon> -->\n <ngx-decaf-icon\n slot=\"icon-only\"\n name=\"ti-code-plus\"\n slot=\"start\"\n />\n {{\n locale +\n (required\n ? items.length\n ? '.add'\n : '.add_first'\n : items.length\n ? '.add'\n : isOpen\n ? '.add_first'\n : '.show_form') | translate\n }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n </div>\n </div>\n} @else {\n @if (refreshing) {\n <div class=\"dcf-loading-container\">\n <ion-spinner\n name=\"crescent\"\n color=\"primary\"\n ></ion-spinner>\n </div>\n } @else {\n <legend>{{ (title ? title : name) | translate }}</legend>\n @if (!items.length) {\n <div class=\"dcf-padding-xsmall\">\n <ion-text>{{ locale + '.empty' | translate }}</ion-text>\n </div>\n } @else {\n @for (item of items; track trackItemFn($index, item)) {\n <div\n class=\"dcf-fieldset-read-item\"\n [class.dcf-accordion]=\"multiple\"\n >\n <div>\n <ngx-decaf-layout\n [isModalChild]=\"isModalChild\"\n [className]=\"operation\"\n [accordion]=\"multiple\"\n [operation]=\"operation\"\n [pk]=\"pk\"\n [model]=\"model\"\n [modelId]=\"modelId\"\n [flexMode]=\"item?.props?.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'collapse'\"\n [children]=\"item || []\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"item?.props?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n />\n </div>\n </div>\n }\n }\n }\n}\n", styles: ["fieldset{margin:0;padding:0;min-inline-size:auto}.dcf-loading-container{height:50%;display:flex;justify-content:center;align-items:center}.dcf-loading-container ion-spinner{width:30px;height:30px}.dcf-fieldset-read-item{border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);padding:var(--dcf-padding-small) var(--dcf-padding-xsmall);padding-bottom:0;margin-bottom:var(--dcf-margin-small)!important}.dcf-fieldset-read-item.dcf-accordion{margin-top:.5rem}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3);padding:var(--dcf-padding-small)}.dcf-fieldset-component.create ::ng-deep .dcf-item-readonly{display:none!important}.dcf-fieldset-component.dcf-open.dcf-empty .dcf-button-add{margin-top:1rem!important;margin-bottom:.15rem!important}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:var(--dcf-padding-xsmall) .25rem}.dcf-fieldset-component:not(.dcf-blank):not(.read):not(.delete){padding:var(--dcf-padding)}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-max-message-container{padding:0 .125rem;margin-bottom:var(--dcf-margin-xsmall)}legend,.dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-content{margin-top:.25rem}.dcf-fieldset-content:not(.dcf-empty){padding:var(--dcf-padding-small) .25rem!important;margin-top:var(--dcf-margin-xsmall)}.dcf-fields-list{margin-top:var(--dcf-margin-small);padding-bottom:var(--dcf-padding)!important;max-height:200px}.dcf-fields-list ion-item{--min-height: 30px;--padding-top: 0rem;--padding-bottom: 0rem;--padding-start: .75rem;--padding-end: .5rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: transparent;--background: rgba(var(--dcf-color-primary-rgb), .025) !important;border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);box-sizing:border-box}.dcf-fields-list ion-item:not(:last-child){margin-bottom:var(--dcf-margin-small)}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);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:.925rem;color:var(--ion-color-gray-6)}\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: 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: "component", type: LayoutComponent, selector: "ngx-decaf-layout", inputs: ["gap", "grid", "flexMode", "rowCard", "maxColsLength", "accordion"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IconComponent, selector: "ngx-decaf-icon", inputs: ["name", "color", "slot", "button", "buttonFill", "buttonShape", "width", "size", "inline"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
9754
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: FieldsetComponent, isStandalone: true, selector: "ngx-decaf-fieldset", inputs: { formControl: "formControl", customTypes: "customTypes", title: "title", description: "description", multiple: "multiple", value: "value", borders: "borders", max: "max", required: "required", ordenable: "ordenable", editable: "editable" }, usesInheritance: true, ngImport: i0, template: "@if (['create', 'update'].includes(operation) || !multiple) {\n <div\n [attr.role]=\"['create', 'update'].includes(operation) ? 'group' : 'region'\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.dcf-empty]=\"!items?.length\"\n [class.dcf-open]=\"isOpen\"\n #component\n >\n <div class=\"dcf-width-1-1\">\n <div>\n <div\n class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\"\n >\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create'].includes(operation) && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button\n fill=\"clear\"\n size=\"small\"\n (click)=\"handleClear($event)\"\n [class.dcf-invisible]=\"!isOpen\"\n [attr.aria-label]=\"\n (items?.length\n ? locale + '.clear_items'\n : locale + '.hidden_form'\n ) | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n [name]=\"'ti-' + (items?.length ? 'trash' : 'eye-off')\"\n />\n </ion-button>\n </div>\n }\n </div>\n </div>\n <div\n class=\"dcf-fieldset-content\"\n [class.dcf-empty]=\"!items?.length && !isOpen\"\n slot=\"content\"\n >\n @if (activePage) {\n <div\n class=\"dcf-animation dcf-animation-slide-top-small dcf-animation-fast\"\n [class.dcf-disabled]=\"!activePage\"\n >\n <ngx-decaf-layout\n [isModalChild]=\"isModalChild\"\n [className]=\"''\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [pk]=\"pk\"\n [modelId]=\"modelId\"\n [operation]=\"operation\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group\n [formGroup]=\"formGroup.parent\"\n [disabled]=\"updatingItem\"\n (ionItemReorder)=\"handleReorderItems($any($event))\"\n #accordionComponent\n >\n @for (\n item of items;\n track trackItemFn(item.index, item.title)\n ) {\n <ion-item\n [class.not-unique]=\"\n isUniqueError && item.title === isUniqueError\n \"\n [class.updating]=\"\n updatingItem?.['index'] === item.index - 1\n \"\n lines=\"full\"\n [button]=\"false\"\n [title]=\"item?.[pk] ?? pk + ': ' + item[pk]\"\n >\n @if (ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon\n aria-hidden=\"true\"\n name=\"swap-vertical-outline\"\n ></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon\n aria-hidden=\"true\"\n class=\"dcf-reorder-disabled\"\n size=\"small\"\n name=\"swap-vertical-outline\"\n disabled\n ></ion-icon>\n </div>\n }\n }\n\n <ion-label\n [color]=\"\n item.title === isUniqueError &&\n !updatingItem?.[pk] === item.title\n ? 'danger'\n : ''\n \"\n >\n {{ item.index }}.{{ item.title }}\n <!-- @if (ordenable) {\n {{ item.index }}.{{ item.title }}\n } @else {\n @if (item[pk]) {\n {{ pk }}: {{ item[pk] }} -\n }\n {{ item.title }}\n } -->\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">\n {{ item.description }}\n </ion-text>\n }\n </ion-label>\n @if (item.info?.length || item.subinfo?.length) {\n <ion-note slot=\"end\">\n @if (item.info?.length) {\n {{ item.info }}\n <br />\n }\n @if (item.subinfo) {\n {{ item.subinfo }}\n }\n </ion-note>\n }\n <div slot=\"end\">\n @if (editable) {\n @if (\n !updatingItem || updatingItem?.[pk] !== item.title\n ) {\n <ion-button\n fill=\"clear\"\n size=\"small\"\n (click)=\"handleUpdateItem($index)\"\n [attr.aria-label]=\"\n locale + '.edit_item' | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n size=\"small\"\n name=\"ti-cash-edit\"\n [color]=\"!isDarkMode ? 'dark' : 'light'\"\n ></ngx-decaf-icon>\n </ion-button>\n }\n }\n @if (!updatingItem) {\n <ion-button\n fill=\"clear\"\n size=\"small\"\n color=\"danger\"\n (click)=\"handleRemoveItem($index)\"\n [attr.aria-label]=\"\n locale + '.remove_item' | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n size=\"small\"\n name=\"ti-row-remove\"\n [color]=\"!isDarkMode ? 'dark' : 'light'\"\n />\n </ion-button>\n }\n </div>\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (isUniqueError) {\n <div\n class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\"\n >\n <div class=\"dcf-grid dcf-grid-collapse dcf-width-1-1\">\n <div\n class=\"dcf-auto\"\n [attr.style]=\"'max-width: 50px'\"\n >\n <ion-icon\n aria-hidden=\"true\"\n name=\"alert-circle-outline\"\n ></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text\n color=\"danger\"\n class=\"dcf-text-small\"\n >\n {{\n locale + '.not_unique'\n | translate: { value: isUniqueError }\n }}\n </ion-text>\n </div>\n </div>\n </div>\n }\n\n @if (max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text\n class=\"dcf-text-small\"\n [color]=\"\n items.length !== max\n ? !isDarkMode\n ? 'medium'\n : ''\n : 'primary'\n \"\n >\n {{\n locale +\n (items.length !== max ? '.max_items' : '.max_items_reached')\n | translate: { '0': max }\n }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\">\n @if (updatingItem) {\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n color=\"danger\"\n (click)=\"handleCancelUpdateItem()\"\n [attr.aria-label]=\"locale + '.cancel_update' | translate\"\n >\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n (click)=\"handleCreateItem()\"\n [attr.aria-label]=\"locale + '.update_item' | translate\"\n >\n <ion-icon\n aria-hidden=\"true\"\n name=\"refresh-outline\"\n slot=\"start\"\n ></ion-icon>\n {{ locale + '.update_item' | translate }}\n </ion-button>\n </div>\n } @else {\n @if (items.length < max || !max) {\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n class=\"dcf-button-add\"\n [color]=\"isDarkMode ? 'light' : 'dark'\"\n (click)=\"handleCreateItem()\"\n [attr.aria-label]=\"locale + '.create_item' | translate\"\n >\n <!-- <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon> -->\n <ngx-decaf-icon\n slot=\"icon-only\"\n name=\"ti-code-plus\"\n slot=\"start\"\n />\n {{\n locale +\n (required\n ? items.length\n ? '.add'\n : '.add_first'\n : items.length\n ? '.add'\n : isOpen\n ? '.add_first'\n : '.show_form') | translate\n }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n </div>\n </div>\n} @else {\n @if (refreshing) {\n <div class=\"dcf-loading-container\">\n <ion-spinner\n name=\"crescent\"\n color=\"primary\"\n ></ion-spinner>\n </div>\n } @else {\n <legend>{{ (title ? title : name) | translate }}</legend>\n @if (!items.length) {\n <div class=\"dcf-padding-xsmall\">\n <ion-text>{{ locale + '.empty' | translate }}</ion-text>\n </div>\n } @else {\n @for (item of items; track trackItemFn($index, item)) {\n <div\n class=\"dcf-fieldset-read-item\"\n [class.dcf-accordion]=\"multiple\"\n >\n <div>\n <ngx-decaf-layout\n [isModalChild]=\"isModalChild\"\n [className]=\"operation\"\n [accordion]=\"multiple\"\n [operation]=\"operation\"\n [pk]=\"pk\"\n [model]=\"model\"\n [modelId]=\"modelId\"\n [flexMode]=\"item?.props?.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'collapse'\"\n [children]=\"item || []\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"item?.props?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n />\n </div>\n </div>\n }\n }\n }\n}\n", styles: ["fieldset{margin:0;padding:0;min-inline-size:auto}.dcf-loading-container{height:50%;display:flex;justify-content:center;align-items:center}.dcf-loading-container ion-spinner{width:30px;height:30px}.dcf-fieldset-read-item{border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);padding:var(--dcf-padding-small) var(--dcf-padding-xsmall);padding-bottom:0;margin-bottom:var(--dcf-margin-small)!important}.dcf-fieldset-read-item.dcf-accordion{margin-top:.5rem}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3);padding:var(--dcf-padding-small)}.dcf-fieldset-component.create ::ng-deep .dcf-item-readonly{display:none!important}.dcf-fieldset-component.dcf-open.dcf-empty .dcf-button-add{margin-top:1rem!important;margin-bottom:.15rem!important}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:var(--dcf-padding-xsmall) .25rem}.dcf-fieldset-component:not(.dcf-blank):not(.read):not(.delete){padding:var(--dcf-padding)}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-max-message-container{padding:0 .125rem;margin-bottom:var(--dcf-margin-xsmall)}legend,.dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-content{margin-top:.25rem}.dcf-fieldset-content:not(.dcf-empty){padding:var(--dcf-padding-small) .25rem!important;margin-top:var(--dcf-margin-xsmall)}.dcf-fieldset-content:not(.dcf-empty) ::ng-deep .dcf-layout-container{min-height:80px}.dcf-fields-list{margin-top:var(--dcf-margin-small);padding-bottom:var(--dcf-padding)!important;max-height:200px}.dcf-fields-list ion-item{--min-height: 30px;--padding-top: 0rem;--padding-bottom: 0rem;--padding-start: .75rem;--padding-end: .5rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: transparent;--background: rgba(var(--dcf-color-primary-rgb), .025) !important;border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);box-sizing:border-box}.dcf-fields-list ion-item:not(:last-child){margin-bottom:var(--dcf-margin-small)}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);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:.925rem;color:var(--ion-color-gray-6)}\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: 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: "component", type: LayoutComponent, selector: "ngx-decaf-layout", inputs: ["gap", "grid", "flexMode", "rowCard", "maxColsLength", "accordion"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: IconComponent, selector: "ngx-decaf-icon", inputs: ["name", "color", "slot", "button", "buttonFill", "buttonShape", "width", "size", "inline"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
9708
9755
|
};
|
|
9709
9756
|
FieldsetComponent = __decorate([
|
|
9710
9757
|
Dynamic(),
|
|
@@ -9726,7 +9773,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
9726
9773
|
LayoutComponent,
|
|
9727
9774
|
IonSpinner,
|
|
9728
9775
|
IconComponent,
|
|
9729
|
-
], template: "@if (['create', 'update'].includes(operation) || !multiple) {\n <div\n [attr.role]=\"['create', 'update'].includes(operation) ? 'group' : 'region'\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.dcf-empty]=\"!items?.length\"\n [class.dcf-open]=\"isOpen\"\n #component\n >\n <div class=\"dcf-width-1-1\">\n <div>\n <div\n class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\"\n >\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create'].includes(operation) && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button\n fill=\"clear\"\n size=\"small\"\n (click)=\"handleClear($event)\"\n [class.dcf-invisible]=\"!isOpen\"\n [attr.aria-label]=\"\n (items?.length\n ? locale + '.clear_items'\n : locale + '.hidden_form'\n ) | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n [name]=\"'ti-' + (items?.length ? 'trash' : 'eye-off')\"\n />\n </ion-button>\n </div>\n }\n </div>\n </div>\n <div\n class=\"dcf-fieldset-content\"\n [class.dcf-empty]=\"!items?.length && !isOpen\"\n slot=\"content\"\n >\n @if (activePage) {\n <div\n class=\"dcf-animation dcf-animation-slide-top-small dcf-animation-fast\"\n [class.dcf-disabled]=\"!activePage\"\n >\n <ngx-decaf-layout\n [isModalChild]=\"isModalChild\"\n [className]=\"''\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [pk]=\"pk\"\n [modelId]=\"modelId\"\n [operation]=\"operation\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group\n [formGroup]=\"formGroup.parent\"\n [disabled]=\"updatingItem\"\n (ionItemReorder)=\"handleReorderItems($any($event))\"\n #accordionComponent\n >\n @for (\n item of items;\n track trackItemFn(item.index, item.title)\n ) {\n <ion-item\n [class.not-unique]=\"\n isUniqueError && item.title === isUniqueError\n \"\n [class.updating]=\"\n updatingItem?.['index'] === item.index - 1\n \"\n lines=\"full\"\n [button]=\"false\"\n [title]=\"item?.[pk] ?? pk + ': ' + item[pk]\"\n >\n @if (ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon\n aria-hidden=\"true\"\n name=\"swap-vertical-outline\"\n ></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon\n aria-hidden=\"true\"\n class=\"dcf-reorder-disabled\"\n size=\"small\"\n name=\"swap-vertical-outline\"\n disabled\n ></ion-icon>\n </div>\n }\n }\n\n <ion-label\n [color]=\"\n item.title === isUniqueError &&\n !updatingItem?.[pk] === item.title\n ? 'danger'\n : ''\n \"\n >\n {{ item.index }}.{{ item.title }}\n <!-- @if (ordenable) {\n {{ item.index }}.{{ item.title }}\n } @else {\n @if (item[pk]) {\n {{ pk }}: {{ item[pk] }} -\n }\n {{ item.title }}\n } -->\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">\n {{ item.description }}\n </ion-text>\n }\n </ion-label>\n @if (item.info?.length || item.subinfo?.length) {\n <ion-note slot=\"end\">\n @if (item.info?.length) {\n {{ item.info }}\n <br />\n }\n @if (item.subinfo) {\n {{ item.subinfo }}\n }\n </ion-note>\n }\n <div slot=\"end\">\n @if (editable) {\n @if (\n !updatingItem || updatingItem?.[pk] !== item.title\n ) {\n <ion-button\n fill=\"clear\"\n size=\"small\"\n (click)=\"handleUpdateItem($index)\"\n [attr.aria-label]=\"\n locale + '.edit_item' | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n size=\"small\"\n name=\"ti-cash-edit\"\n [color]=\"!isDarkMode ? 'dark' : 'light'\"\n ></ngx-decaf-icon>\n </ion-button>\n }\n }\n @if (!updatingItem) {\n <ion-button\n fill=\"clear\"\n size=\"small\"\n color=\"danger\"\n (click)=\"handleRemoveItem($index)\"\n [attr.aria-label]=\"\n locale + '.remove_item' | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n size=\"small\"\n name=\"ti-row-remove\"\n [color]=\"!isDarkMode ? 'dark' : 'light'\"\n />\n </ion-button>\n }\n </div>\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (isUniqueError) {\n <div\n class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\"\n >\n <div class=\"dcf-grid dcf-grid-collapse dcf-width-1-1\">\n <div\n class=\"dcf-auto\"\n [attr.style]=\"'max-width: 50px'\"\n >\n <ion-icon\n aria-hidden=\"true\"\n name=\"alert-circle-outline\"\n ></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text\n color=\"danger\"\n class=\"dcf-text-small\"\n >\n {{\n locale + '.not_unique'\n | translate: { value: isUniqueError }\n }}\n </ion-text>\n </div>\n </div>\n </div>\n }\n\n @if (max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text\n class=\"dcf-text-small\"\n [color]=\"\n items.length !== max\n ? !isDarkMode\n ? 'medium'\n : ''\n : 'primary'\n \"\n >\n {{\n locale +\n (items.length !== max ? '.max_items' : '.max_items_reached')\n | translate: { '0': max }\n }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\">\n @if (updatingItem) {\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n color=\"danger\"\n (click)=\"handleCancelUpdateItem()\"\n [attr.aria-label]=\"locale + '.cancel_update' | translate\"\n >\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n (click)=\"handleCreateItem()\"\n [attr.aria-label]=\"locale + '.update_item' | translate\"\n >\n <ion-icon\n aria-hidden=\"true\"\n name=\"refresh-outline\"\n slot=\"start\"\n ></ion-icon>\n {{ locale + '.update_item' | translate }}\n </ion-button>\n </div>\n } @else {\n @if (items.length < max || !max) {\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n class=\"dcf-button-add\"\n [color]=\"isDarkMode ? 'light' : 'dark'\"\n (click)=\"handleCreateItem()\"\n [attr.aria-label]=\"locale + '.create_item' | translate\"\n >\n <!-- <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon> -->\n <ngx-decaf-icon\n slot=\"icon-only\"\n name=\"ti-code-plus\"\n slot=\"start\"\n />\n {{\n locale +\n (required\n ? items.length\n ? '.add'\n : '.add_first'\n : items.length\n ? '.add'\n : isOpen\n ? '.add_first'\n : '.show_form') | translate\n }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n </div>\n </div>\n} @else {\n @if (refreshing) {\n <div class=\"dcf-loading-container\">\n <ion-spinner\n name=\"crescent\"\n color=\"primary\"\n ></ion-spinner>\n </div>\n } @else {\n <legend>{{ (title ? title : name) | translate }}</legend>\n @if (!items.length) {\n <div class=\"dcf-padding-xsmall\">\n <ion-text>{{ locale + '.empty' | translate }}</ion-text>\n </div>\n } @else {\n @for (item of items; track trackItemFn($index, item)) {\n <div\n class=\"dcf-fieldset-read-item\"\n [class.dcf-accordion]=\"multiple\"\n >\n <div>\n <ngx-decaf-layout\n [isModalChild]=\"isModalChild\"\n [className]=\"operation\"\n [accordion]=\"multiple\"\n [operation]=\"operation\"\n [pk]=\"pk\"\n [model]=\"model\"\n [modelId]=\"modelId\"\n [flexMode]=\"item?.props?.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'collapse'\"\n [children]=\"item || []\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"item?.props?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n />\n </div>\n </div>\n }\n }\n }\n}\n", styles: ["fieldset{margin:0;padding:0;min-inline-size:auto}.dcf-loading-container{height:50%;display:flex;justify-content:center;align-items:center}.dcf-loading-container ion-spinner{width:30px;height:30px}.dcf-fieldset-read-item{border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);padding:var(--dcf-padding-small) var(--dcf-padding-xsmall);padding-bottom:0;margin-bottom:var(--dcf-margin-small)!important}.dcf-fieldset-read-item.dcf-accordion{margin-top:.5rem}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3);padding:var(--dcf-padding-small)}.dcf-fieldset-component.create ::ng-deep .dcf-item-readonly{display:none!important}.dcf-fieldset-component.dcf-open.dcf-empty .dcf-button-add{margin-top:1rem!important;margin-bottom:.15rem!important}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:var(--dcf-padding-xsmall) .25rem}.dcf-fieldset-component:not(.dcf-blank):not(.read):not(.delete){padding:var(--dcf-padding)}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-max-message-container{padding:0 .125rem;margin-bottom:var(--dcf-margin-xsmall)}legend,.dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-content{margin-top:.25rem}.dcf-fieldset-content:not(.dcf-empty){padding:var(--dcf-padding-small) .25rem!important;margin-top:var(--dcf-margin-xsmall)}.dcf-fields-list{margin-top:var(--dcf-margin-small);padding-bottom:var(--dcf-padding)!important;max-height:200px}.dcf-fields-list ion-item{--min-height: 30px;--padding-top: 0rem;--padding-bottom: 0rem;--padding-start: .75rem;--padding-end: .5rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: transparent;--background: rgba(var(--dcf-color-primary-rgb), .025) !important;border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);box-sizing:border-box}.dcf-fields-list ion-item:not(:last-child){margin-bottom:var(--dcf-margin-small)}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);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:.925rem;color:var(--ion-color-gray-6)}\n"] }]
|
|
9776
|
+
], template: "@if (['create', 'update'].includes(operation) || !multiple) {\n <div\n [attr.role]=\"['create', 'update'].includes(operation) ? 'group' : 'region'\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.dcf-empty]=\"!items?.length\"\n [class.dcf-open]=\"isOpen\"\n #component\n >\n <div class=\"dcf-width-1-1\">\n <div>\n <div\n class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\"\n >\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create'].includes(operation) && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button\n fill=\"clear\"\n size=\"small\"\n (click)=\"handleClear($event)\"\n [class.dcf-invisible]=\"!isOpen\"\n [attr.aria-label]=\"\n (items?.length\n ? locale + '.clear_items'\n : locale + '.hidden_form'\n ) | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n [name]=\"'ti-' + (items?.length ? 'trash' : 'eye-off')\"\n />\n </ion-button>\n </div>\n }\n </div>\n </div>\n <div\n class=\"dcf-fieldset-content\"\n [class.dcf-empty]=\"!items?.length && !isOpen\"\n slot=\"content\"\n >\n @if (activePage) {\n <div\n class=\"dcf-animation dcf-animation-slide-top-small dcf-animation-fast\"\n [class.dcf-disabled]=\"!activePage\"\n >\n <ngx-decaf-layout\n [isModalChild]=\"isModalChild\"\n [className]=\"''\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [pk]=\"pk\"\n [modelId]=\"modelId\"\n [operation]=\"operation\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group\n [formGroup]=\"formGroup.parent\"\n [disabled]=\"updatingItem\"\n (ionItemReorder)=\"handleReorderItems($any($event))\"\n #accordionComponent\n >\n @for (\n item of items;\n track trackItemFn(item.index, item.title)\n ) {\n <ion-item\n [class.not-unique]=\"\n isUniqueError && item.title === isUniqueError\n \"\n [class.updating]=\"\n updatingItem?.['index'] === item.index - 1\n \"\n lines=\"full\"\n [button]=\"false\"\n [title]=\"item?.[pk] ?? pk + ': ' + item[pk]\"\n >\n @if (ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon\n aria-hidden=\"true\"\n name=\"swap-vertical-outline\"\n ></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon\n aria-hidden=\"true\"\n class=\"dcf-reorder-disabled\"\n size=\"small\"\n name=\"swap-vertical-outline\"\n disabled\n ></ion-icon>\n </div>\n }\n }\n\n <ion-label\n [color]=\"\n item.title === isUniqueError &&\n !updatingItem?.[pk] === item.title\n ? 'danger'\n : ''\n \"\n >\n {{ item.index }}.{{ item.title }}\n <!-- @if (ordenable) {\n {{ item.index }}.{{ item.title }}\n } @else {\n @if (item[pk]) {\n {{ pk }}: {{ item[pk] }} -\n }\n {{ item.title }}\n } -->\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">\n {{ item.description }}\n </ion-text>\n }\n </ion-label>\n @if (item.info?.length || item.subinfo?.length) {\n <ion-note slot=\"end\">\n @if (item.info?.length) {\n {{ item.info }}\n <br />\n }\n @if (item.subinfo) {\n {{ item.subinfo }}\n }\n </ion-note>\n }\n <div slot=\"end\">\n @if (editable) {\n @if (\n !updatingItem || updatingItem?.[pk] !== item.title\n ) {\n <ion-button\n fill=\"clear\"\n size=\"small\"\n (click)=\"handleUpdateItem($index)\"\n [attr.aria-label]=\"\n locale + '.edit_item' | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n size=\"small\"\n name=\"ti-cash-edit\"\n [color]=\"!isDarkMode ? 'dark' : 'light'\"\n ></ngx-decaf-icon>\n </ion-button>\n }\n }\n @if (!updatingItem) {\n <ion-button\n fill=\"clear\"\n size=\"small\"\n color=\"danger\"\n (click)=\"handleRemoveItem($index)\"\n [attr.aria-label]=\"\n locale + '.remove_item' | translate\n \"\n >\n <ngx-decaf-icon\n slot=\"icon-only\"\n size=\"small\"\n name=\"ti-row-remove\"\n [color]=\"!isDarkMode ? 'dark' : 'light'\"\n />\n </ion-button>\n }\n </div>\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (isUniqueError) {\n <div\n class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\"\n >\n <div class=\"dcf-grid dcf-grid-collapse dcf-width-1-1\">\n <div\n class=\"dcf-auto\"\n [attr.style]=\"'max-width: 50px'\"\n >\n <ion-icon\n aria-hidden=\"true\"\n name=\"alert-circle-outline\"\n ></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text\n color=\"danger\"\n class=\"dcf-text-small\"\n >\n {{\n locale + '.not_unique'\n | translate: { value: isUniqueError }\n }}\n </ion-text>\n </div>\n </div>\n </div>\n }\n\n @if (max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text\n class=\"dcf-text-small\"\n [color]=\"\n items.length !== max\n ? !isDarkMode\n ? 'medium'\n : ''\n : 'primary'\n \"\n >\n {{\n locale +\n (items.length !== max ? '.max_items' : '.max_items_reached')\n | translate: { '0': max }\n }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\">\n @if (updatingItem) {\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n color=\"danger\"\n (click)=\"handleCancelUpdateItem()\"\n [attr.aria-label]=\"locale + '.cancel_update' | translate\"\n >\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n (click)=\"handleCreateItem()\"\n [attr.aria-label]=\"locale + '.update_item' | translate\"\n >\n <ion-icon\n aria-hidden=\"true\"\n name=\"refresh-outline\"\n slot=\"start\"\n ></ion-icon>\n {{ locale + '.update_item' | translate }}\n </ion-button>\n </div>\n } @else {\n @if (items.length < max || !max) {\n <div>\n <ion-button\n size=\"small\"\n fill=\"clear\"\n class=\"dcf-button-add\"\n [color]=\"isDarkMode ? 'light' : 'dark'\"\n (click)=\"handleCreateItem()\"\n [attr.aria-label]=\"locale + '.create_item' | translate\"\n >\n <!-- <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon> -->\n <ngx-decaf-icon\n slot=\"icon-only\"\n name=\"ti-code-plus\"\n slot=\"start\"\n />\n {{\n locale +\n (required\n ? items.length\n ? '.add'\n : '.add_first'\n : items.length\n ? '.add'\n : isOpen\n ? '.add_first'\n : '.show_form') | translate\n }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n </div>\n </div>\n} @else {\n @if (refreshing) {\n <div class=\"dcf-loading-container\">\n <ion-spinner\n name=\"crescent\"\n color=\"primary\"\n ></ion-spinner>\n </div>\n } @else {\n <legend>{{ (title ? title : name) | translate }}</legend>\n @if (!items.length) {\n <div class=\"dcf-padding-xsmall\">\n <ion-text>{{ locale + '.empty' | translate }}</ion-text>\n </div>\n } @else {\n @for (item of items; track trackItemFn($index, item)) {\n <div\n class=\"dcf-fieldset-read-item\"\n [class.dcf-accordion]=\"multiple\"\n >\n <div>\n <ngx-decaf-layout\n [isModalChild]=\"isModalChild\"\n [className]=\"operation\"\n [accordion]=\"multiple\"\n [operation]=\"operation\"\n [pk]=\"pk\"\n [model]=\"model\"\n [modelId]=\"modelId\"\n [flexMode]=\"item?.props?.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'collapse'\"\n [children]=\"item || []\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"item?.props?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n />\n </div>\n </div>\n }\n }\n }\n}\n", styles: ["fieldset{margin:0;padding:0;min-inline-size:auto}.dcf-loading-container{height:50%;display:flex;justify-content:center;align-items:center}.dcf-loading-container ion-spinner{width:30px;height:30px}.dcf-fieldset-read-item{border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);padding:var(--dcf-padding-small) var(--dcf-padding-xsmall);padding-bottom:0;margin-bottom:var(--dcf-margin-small)!important}.dcf-fieldset-read-item.dcf-accordion{margin-top:.5rem}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3);padding:var(--dcf-padding-small)}.dcf-fieldset-component.create ::ng-deep .dcf-item-readonly{display:none!important}.dcf-fieldset-component.dcf-open.dcf-empty .dcf-button-add{margin-top:1rem!important;margin-bottom:.15rem!important}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:var(--dcf-padding-xsmall) .25rem}.dcf-fieldset-component:not(.dcf-blank):not(.read):not(.delete){padding:var(--dcf-padding)}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-max-message-container{padding:0 .125rem;margin-bottom:var(--dcf-margin-xsmall)}legend,.dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-content{margin-top:.25rem}.dcf-fieldset-content:not(.dcf-empty){padding:var(--dcf-padding-small) .25rem!important;margin-top:var(--dcf-margin-xsmall)}.dcf-fieldset-content:not(.dcf-empty) ::ng-deep .dcf-layout-container{min-height:80px}.dcf-fields-list{margin-top:var(--dcf-margin-small);padding-bottom:var(--dcf-padding)!important;max-height:200px}.dcf-fields-list ion-item{--min-height: 30px;--padding-top: 0rem;--padding-bottom: 0rem;--padding-start: .75rem;--padding-end: .5rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: transparent;--background: rgba(var(--dcf-color-primary-rgb), .025) !important;border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);box-sizing:border-box}.dcf-fields-list ion-item:not(:last-child){margin-bottom:var(--dcf-margin-small)}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);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:.925rem;color:var(--ion-color-gray-6)}\n"] }]
|
|
9730
9777
|
}], ctorParameters: () => [], propDecorators: { formControl: [{
|
|
9731
9778
|
type: Input
|
|
9732
9779
|
}], customTypes: [{
|
|
@@ -13985,6 +14032,189 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
13985
14032
|
type: Input
|
|
13986
14033
|
}] } });
|
|
13987
14034
|
|
|
14035
|
+
class DecafTruncatePipe {
|
|
14036
|
+
transform(value, limit = 30, trail = '...') {
|
|
14037
|
+
if (!value) {
|
|
14038
|
+
return '';
|
|
14039
|
+
}
|
|
14040
|
+
const sanitized = this.sanitize(value);
|
|
14041
|
+
return sanitized.length > limit ? `${sanitized.substring(0, limit)}${trail}` : sanitized;
|
|
14042
|
+
}
|
|
14043
|
+
sanitize(value) {
|
|
14044
|
+
return value.replace(/<[^>]+>/g, '').trim();
|
|
14045
|
+
}
|
|
14046
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DecafTruncatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
14047
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.17", ngImport: i0, type: DecafTruncatePipe, isStandalone: true, name: "truncate" }); }
|
|
14048
|
+
}
|
|
14049
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DecafTruncatePipe, decorators: [{
|
|
14050
|
+
type: Pipe,
|
|
14051
|
+
args: [{
|
|
14052
|
+
name: 'truncate',
|
|
14053
|
+
// pure: true,
|
|
14054
|
+
standalone: true,
|
|
14055
|
+
}]
|
|
14056
|
+
}] });
|
|
14057
|
+
|
|
14058
|
+
/**
|
|
14059
|
+
* @module DecafTooltipDirective
|
|
14060
|
+
* @description Provides a tooltip directive for the decaf-ts for-angular library.
|
|
14061
|
+
* @summary This module defines the {@link DecafTooltipDirective}, a standalone Angular directive
|
|
14062
|
+
* that dynamically appends a tooltip element to any host element it decorates. It also supports
|
|
14063
|
+
* optional text truncation using the {@link DecafTruncatePipe}.
|
|
14064
|
+
*/
|
|
14065
|
+
/**
|
|
14066
|
+
* @description Angular directive that appends a tooltip `<span>` to the host element and
|
|
14067
|
+
* optionally truncates its visible text content.
|
|
14068
|
+
* @summary The `DecafTooltipDirective` is a standalone Angular directive bound to the
|
|
14069
|
+
* `[ngx-decaf-tooltip]` attribute selector. It processes the {@link TooltipConfig} provided
|
|
14070
|
+
* via the `options` input, sanitizes the text, and appends a `.dcf-tooltip` `<span>` containing
|
|
14071
|
+
* the sanitized full text to the host element. The directive also applies the `dcf-tooltip-parent`
|
|
14072
|
+
* CSS class to the host for tooltip positioning. When truncation is enabled, the host element's
|
|
14073
|
+
* inner content is replaced with the truncated text before the tooltip span is added.
|
|
14074
|
+
* @example
|
|
14075
|
+
* ```html
|
|
14076
|
+
* <!-- Basic tooltip -->
|
|
14077
|
+
* <span [ngx-decaf-tooltip]="{ text: 'Full description here' }">Hover me</span>
|
|
14078
|
+
*
|
|
14079
|
+
* <!-- Truncated visible text with tooltip showing the full content -->
|
|
14080
|
+
* <span [ngx-decaf-tooltip]="{ text: veryLongLabel, truncate: true, limit: 20, trail: '…' }">
|
|
14081
|
+
* {{ veryLongLabel }}
|
|
14082
|
+
* </span>
|
|
14083
|
+
* ```
|
|
14084
|
+
* @class DecafTooltipDirective
|
|
14085
|
+
*/
|
|
14086
|
+
/**
|
|
14087
|
+
* @description Angular lifecycle hook invoked whenever one or more input properties change.
|
|
14088
|
+
* @summary Processes the {@link ITooltipConfig} options, sanitizes the text, and updates the
|
|
14089
|
+
* host element's content and tooltip span accordingly. Applies the `dcf-tooltip-parent` CSS class
|
|
14090
|
+
* to the host for styling.
|
|
14091
|
+
* @return {void}
|
|
14092
|
+
*/
|
|
14093
|
+
class DecafTooltipDirective {
|
|
14094
|
+
constructor() {
|
|
14095
|
+
/**
|
|
14096
|
+
* @description Reference to the host DOM element into which the SVG will be injected.
|
|
14097
|
+
* @summary Obtained via Angular's `inject(ElementRef)`. Provides access to the native
|
|
14098
|
+
* element forwarded to {@link NgxMediaService.loadSvgObserver} as the injection target,
|
|
14099
|
+
* and used as a fallback source for the `src` attribute when `path` is not set.
|
|
14100
|
+
* @type {ElementRef}
|
|
14101
|
+
* @memberOf module:lib/directives/NgxSvgDirective
|
|
14102
|
+
*/
|
|
14103
|
+
this.element = inject(ElementRef);
|
|
14104
|
+
this.renderer = inject(Renderer2);
|
|
14105
|
+
this.truncatePipe = inject(DecafTruncatePipe);
|
|
14106
|
+
}
|
|
14107
|
+
/**
|
|
14108
|
+
* @description Angular lifecycle hook invoked whenever one or more input properties change.
|
|
14109
|
+
* @summary Processes the {@link TooltipConfig} options, sanitizes the text, and updates the
|
|
14110
|
+
* host element's content and tooltip span accordingly. Applies the `dcf-tooltip-parent` CSS class
|
|
14111
|
+
* to the host for styling.
|
|
14112
|
+
* @return {void}
|
|
14113
|
+
*/
|
|
14114
|
+
ngOnChanges() {
|
|
14115
|
+
const options = {
|
|
14116
|
+
truncate: false,
|
|
14117
|
+
limit: 30,
|
|
14118
|
+
...this.options,
|
|
14119
|
+
};
|
|
14120
|
+
if (options?.text && options?.text.trim().length) {
|
|
14121
|
+
const value = options.text.replace(/<[^>]+>/g, '').trim();
|
|
14122
|
+
const text = !options.truncate
|
|
14123
|
+
? value
|
|
14124
|
+
: this.truncatePipe.transform(value, options.limit, options.trail || '...');
|
|
14125
|
+
const element = this.element?.nativeElement ? this.element?.nativeElement : this.element;
|
|
14126
|
+
if (options.truncate) {
|
|
14127
|
+
this.renderer.setProperty(element, 'innerHTML', '');
|
|
14128
|
+
const textNode = this.renderer.createText(text);
|
|
14129
|
+
this.renderer.appendChild(element, textNode);
|
|
14130
|
+
}
|
|
14131
|
+
// creating tooltip element
|
|
14132
|
+
const tooltip = this.renderer.createElement('span');
|
|
14133
|
+
this.renderer.addClass(tooltip, 'dcf-tooltip');
|
|
14134
|
+
this.renderer.appendChild(tooltip, this.renderer.createText(this.truncatePipe.sanitize(value)));
|
|
14135
|
+
this.renderer.appendChild(element, tooltip);
|
|
14136
|
+
this.renderer.addClass(element, 'dcf-tooltip-parent');
|
|
14137
|
+
}
|
|
14138
|
+
}
|
|
14139
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DecafTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
|
|
14140
|
+
static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.17", type: DecafTooltipDirective, isStandalone: true, selector: "[ngx-decaf-tooltip]", inputs: { options: ["ngx-decaf-tooltip", "options"] }, providers: [DecafTruncatePipe], usesOnChanges: true, ngImport: i0 }); }
|
|
14141
|
+
}
|
|
14142
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DecafTooltipDirective, decorators: [{
|
|
14143
|
+
type: Directive,
|
|
14144
|
+
args: [{
|
|
14145
|
+
selector: '[ngx-decaf-tooltip]',
|
|
14146
|
+
providers: [DecafTruncatePipe],
|
|
14147
|
+
standalone: true,
|
|
14148
|
+
}]
|
|
14149
|
+
}], propDecorators: { options: [{
|
|
14150
|
+
type: Input,
|
|
14151
|
+
args: ['ngx-decaf-tooltip']
|
|
14152
|
+
}] } });
|
|
14153
|
+
|
|
14154
|
+
/**
|
|
14155
|
+
* @description Abstract base class for dynamic Angular modules
|
|
14156
|
+
* @summary The DynamicModule serves as a base class for Angular modules that need to be
|
|
14157
|
+
* dynamically loaded or configured at runtime. It provides a common type for the rendering
|
|
14158
|
+
* engine to identify and work with dynamic modules.
|
|
14159
|
+
* @class DynamicModule
|
|
14160
|
+
* @example
|
|
14161
|
+
* ```typescript
|
|
14162
|
+
* @NgModule({
|
|
14163
|
+
* declarations: [MyComponent],
|
|
14164
|
+
* imports: [CommonModule]
|
|
14165
|
+
* })
|
|
14166
|
+
* export class MyDynamicModule extends DynamicModule {}
|
|
14167
|
+
* ```
|
|
14168
|
+
*/
|
|
14169
|
+
class DynamicModule {
|
|
14170
|
+
}
|
|
14171
|
+
|
|
14172
|
+
class NgxEventHandler extends DecafEventHandler {
|
|
14173
|
+
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
14174
|
+
constructor() {
|
|
14175
|
+
super();
|
|
14176
|
+
this._data = null;
|
|
14177
|
+
}
|
|
14178
|
+
async handle(event, data, instance, ...args) {
|
|
14179
|
+
this.log.for(this.handle).info(`Handle called with args: ${event}, ${data}, ${instance}, ${args}`);
|
|
14180
|
+
}
|
|
14181
|
+
from(...args) {
|
|
14182
|
+
this.log.for(this.process).info(`Process called with args: ${args}`);
|
|
14183
|
+
return this;
|
|
14184
|
+
}
|
|
14185
|
+
async process(...args) {
|
|
14186
|
+
this.log.for(this.process).info(`Process called with args: ${args}`);
|
|
14187
|
+
}
|
|
14188
|
+
async delete(...args) {
|
|
14189
|
+
this.log.for(this.delete).info(`Delete called with args: ${args}`);
|
|
14190
|
+
}
|
|
14191
|
+
async batchOperation(...args) {
|
|
14192
|
+
this.log.for(this.batchOperation).info(`batchOperation called with args: ${args}`);
|
|
14193
|
+
}
|
|
14194
|
+
async beforeCreate(...args) {
|
|
14195
|
+
this.log.for(this.beforeCreate).info(`beforeCreate called with args: ${args}`);
|
|
14196
|
+
}
|
|
14197
|
+
async beforeUpdate(...args) {
|
|
14198
|
+
this.log.for(this.beforeUpdate).info(`beforeUpdate called with args: ${args}`);
|
|
14199
|
+
}
|
|
14200
|
+
async afterCreate(...args) {
|
|
14201
|
+
this.log.for(this.afterCreate).info(`afterCreate called with args: ${args}`);
|
|
14202
|
+
}
|
|
14203
|
+
async afterUpdate(...args) {
|
|
14204
|
+
this.log.for(this.afterUpdate).info(`afterUpdate called with args: ${args}`);
|
|
14205
|
+
}
|
|
14206
|
+
}
|
|
14207
|
+
|
|
14208
|
+
/**
|
|
14209
|
+
* @module engine
|
|
14210
|
+
* @description Angular rendering engine for Decaf applications
|
|
14211
|
+
* @summary The engine module provides core functionality for rendering Angular components
|
|
14212
|
+
* in Decaf applications. It includes constants, decorators, rendering engines, and utility types
|
|
14213
|
+
* that enable dynamic component creation, property mapping, and component lifecycle management.
|
|
14214
|
+
* Key exports include {@link NgxRenderingEngine}, {@link DynamicModule}, and various decorators
|
|
14215
|
+
* for component configuration.
|
|
14216
|
+
*/
|
|
14217
|
+
|
|
13988
14218
|
/**
|
|
13989
14219
|
* @description Service for handling routing operations in the application.
|
|
13990
14220
|
* @summary The RouterService provides a unified interface for navigation and route management,
|
|
@@ -14339,10 +14569,51 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14339
14569
|
let TableComponent = class TableComponent extends ListComponent {
|
|
14340
14570
|
constructor() {
|
|
14341
14571
|
super(...arguments);
|
|
14572
|
+
/**
|
|
14573
|
+
* @description Maximum character count before cell content is truncated. `-1` disables truncation.
|
|
14574
|
+
* @type {number}
|
|
14575
|
+
* @default -1
|
|
14576
|
+
*/
|
|
14577
|
+
this.maxContentLength = -1;
|
|
14578
|
+
/**
|
|
14579
|
+
* @description Column keys whose values are never truncated regardless of `maxContentLength`.
|
|
14580
|
+
* @type {string[]}
|
|
14581
|
+
* @default ['userId']
|
|
14582
|
+
*/
|
|
14583
|
+
this.preserve = ['userId'];
|
|
14584
|
+
/**
|
|
14585
|
+
* @description Column header label array, mirrors `cols` after `getOperations()` resolves.
|
|
14586
|
+
* @type {string[]}
|
|
14587
|
+
*/
|
|
14342
14588
|
this.headers = [];
|
|
14589
|
+
/**
|
|
14590
|
+
* @description When `true`, row-level action buttons are rendered if the user has the required permissions.
|
|
14591
|
+
* @type {boolean}
|
|
14592
|
+
* @default true
|
|
14593
|
+
*/
|
|
14343
14594
|
this.allowOperations = true;
|
|
14595
|
+
/**
|
|
14596
|
+
* @description Injected {@link NgxRouterService} used to read URL query parameters for pre-populating the search state.
|
|
14597
|
+
* @type {NgxRouterService}
|
|
14598
|
+
*/
|
|
14344
14599
|
this.routerService = inject(NgxRouterService);
|
|
14345
14600
|
}
|
|
14601
|
+
/**
|
|
14602
|
+
* @description Resolves and sorts the visible column keys from the current mapper metadata.
|
|
14603
|
+
* @summary Reads `this._mapper` to obtain all columns that carry a `sequence` property,
|
|
14604
|
+
* then sorts them so that columns anchored to `UIKeys.FIRST` appear first, numerically
|
|
14605
|
+
* sequenced columns are ordered by their value, and `UIKeys.LAST` anchored columns appear
|
|
14606
|
+
* last. Returns the final sorted array of column key strings.
|
|
14607
|
+
* @return {string[]} Sorted array of column keys derived from the mapper.
|
|
14608
|
+
* @mermaid
|
|
14609
|
+
* sequenceDiagram
|
|
14610
|
+
* participant TC as TableComponent
|
|
14611
|
+
* participant M as _mapper
|
|
14612
|
+
* TC->>M: Object.entries(_mapper)
|
|
14613
|
+
* M-->>TC: [key, value][] entries
|
|
14614
|
+
* TC->>TC: sort by sequence weight (FIRST=0, number=1, LAST=100)
|
|
14615
|
+
* TC-->>TC: return sorted keys[]
|
|
14616
|
+
*/
|
|
14346
14617
|
get _cols() {
|
|
14347
14618
|
this.mapper = this._mapper;
|
|
14348
14619
|
return Object.entries(this.mapper)
|
|
@@ -14362,9 +14633,20 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
14362
14633
|
})
|
|
14363
14634
|
.map(([key]) => key);
|
|
14364
14635
|
}
|
|
14636
|
+
/**
|
|
14637
|
+
* @description Returns the column header labels derived directly from the resolved `cols` array.
|
|
14638
|
+
* @return {string[]} Shallow copy of `cols` used as table header labels.
|
|
14639
|
+
*/
|
|
14365
14640
|
get _headers() {
|
|
14366
14641
|
return this.cols.map((col) => col);
|
|
14367
14642
|
}
|
|
14643
|
+
/**
|
|
14644
|
+
* @description Filters the raw mapper to only the entries that declare a `sequence` property.
|
|
14645
|
+
* @summary Iterates over `this.mapper`, retains only keys whose value is a plain object
|
|
14646
|
+
* containing a `sequence` field, and returns the resulting subset as a {@link KeyValue} map
|
|
14647
|
+
* used by `_cols` for ordered column resolution.
|
|
14648
|
+
* @return {KeyValue} Filtered mapper containing only sequenced column definitions.
|
|
14649
|
+
*/
|
|
14368
14650
|
get _mapper() {
|
|
14369
14651
|
return Object.keys(this.mapper).reduce((accum, curr) => {
|
|
14370
14652
|
const mapper = this.mapper[curr];
|
|
@@ -14373,8 +14655,13 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
14373
14655
|
return accum;
|
|
14374
14656
|
}, {});
|
|
14375
14657
|
}
|
|
14658
|
+
/**
|
|
14659
|
+
* @description Angular lifecycle hook that initializes the table and loads its first page of data.
|
|
14660
|
+
* @summary Sets up the table by resolving columns, headers, and filter options. It also reads URL query parameters
|
|
14661
|
+
* to pre-populate the search state and triggers the initial data refresh.
|
|
14662
|
+
* @return {Promise<void>}
|
|
14663
|
+
*/
|
|
14376
14664
|
async ngOnInit() {
|
|
14377
|
-
// this.parseProps(this);
|
|
14378
14665
|
await super.initialize();
|
|
14379
14666
|
this.type = ListComponentsTypes.PAGINATED;
|
|
14380
14667
|
this.empty = Object.assign({}, DefaultListEmptyOptions, this.empty);
|
|
@@ -14383,7 +14670,6 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
14383
14670
|
.subscribe(([model, action, uid, data]) => this.handleObserveEvent(model, action, uid, data));
|
|
14384
14671
|
this.cols = this._cols;
|
|
14385
14672
|
this.getOperations();
|
|
14386
|
-
this.searchValue = undefined;
|
|
14387
14673
|
const filter = this.routerService.getQueryParamValue('filter');
|
|
14388
14674
|
if (filter) {
|
|
14389
14675
|
const value = this.routerService.getQueryParamValue('value');
|
|
@@ -14406,6 +14692,11 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
14406
14692
|
}
|
|
14407
14693
|
await this.refresh();
|
|
14408
14694
|
}
|
|
14695
|
+
/**
|
|
14696
|
+
* @description Determines which row-level CRUD operations are permitted and finalizes the column list.
|
|
14697
|
+
* @summary Checks user permissions for `UPDATE` and `DELETE` operations. Updates the `cols` and `headers` arrays accordingly.
|
|
14698
|
+
* @return {void}
|
|
14699
|
+
*/
|
|
14409
14700
|
getOperations() {
|
|
14410
14701
|
if (this.allowOperations) {
|
|
14411
14702
|
this.allowOperations = this.isAllowed(OperationKeys.UPDATE) || this.isAllowed(OperationKeys.DELETE);
|
|
@@ -14418,25 +14709,45 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
14418
14709
|
}
|
|
14419
14710
|
this.headers = this._headers;
|
|
14420
14711
|
}
|
|
14712
|
+
/**
|
|
14713
|
+
* @description Populates `filterOptions` from a function call or a decorator-bound repository.
|
|
14714
|
+
* @summary Resolves filter options dynamically based on the provided `filterModel`. Supports both
|
|
14715
|
+
* async functions and repository-based data sources.
|
|
14716
|
+
* @return {Promise<void>}
|
|
14717
|
+
*/
|
|
14421
14718
|
async getFilterOptions() {
|
|
14422
|
-
const
|
|
14423
|
-
|
|
14424
|
-
const { repository, pk } = repo;
|
|
14425
|
-
if (!this.filterBy)
|
|
14719
|
+
const getFilterOptionsMapper = (pk) => {
|
|
14720
|
+
if (!this.filterBy) {
|
|
14426
14721
|
this.filterBy = pk;
|
|
14722
|
+
}
|
|
14427
14723
|
if (!this.filterOptionsMapper) {
|
|
14428
|
-
this.filterOptionsMapper =
|
|
14429
|
-
|
|
14430
|
-
|
|
14431
|
-
|
|
14432
|
-
|
|
14433
|
-
|
|
14434
|
-
|
|
14435
|
-
|
|
14436
|
-
|
|
14724
|
+
this.filterOptionsMapper = (item) => ({
|
|
14725
|
+
text: `${item[pk]}`,
|
|
14726
|
+
value: `${item[pk]}`,
|
|
14727
|
+
});
|
|
14728
|
+
}
|
|
14729
|
+
};
|
|
14730
|
+
if (typeof this.filterModel === 'function') {
|
|
14731
|
+
this.filterOptions = await this.filterModel();
|
|
14732
|
+
}
|
|
14733
|
+
else {
|
|
14734
|
+
const repo = getModelAndRepository(this.filterModel);
|
|
14735
|
+
if (repo) {
|
|
14736
|
+
const { repository, pk } = repo;
|
|
14737
|
+
getFilterOptionsMapper(pk);
|
|
14738
|
+
const query = await repository.select().execute();
|
|
14437
14739
|
this.filterOptions = query.map((item) => this.filterOptionsMapper(item));
|
|
14740
|
+
}
|
|
14438
14741
|
}
|
|
14439
14742
|
}
|
|
14743
|
+
/**
|
|
14744
|
+
* @description Maps a single raw data row to the cell-structured format expected by the table template.
|
|
14745
|
+
* @summary Applies transformations and event bindings to each row of data, preparing it for rendering.
|
|
14746
|
+
* @param {KeyValue} item - Raw data object representing a single table row.
|
|
14747
|
+
* @param {KeyValue} mapper - Column mapper definitions.
|
|
14748
|
+
* @param {KeyValue} [props={}] - Additional rendering props.
|
|
14749
|
+
* @return {Promise<KeyValue>} Mapped row object.
|
|
14750
|
+
*/
|
|
14440
14751
|
async itemMapper(item, mapper, props = {}) {
|
|
14441
14752
|
this.model = item;
|
|
14442
14753
|
const mapped = super.itemMapper(item, this.cols.filter((c) => c !== 'actions'), props);
|
|
@@ -14501,12 +14812,27 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
14501
14812
|
}
|
|
14502
14813
|
return mapped;
|
|
14503
14814
|
}
|
|
14815
|
+
/**
|
|
14816
|
+
* @description Maps an array of raw data objects to the cell-structured rows used by the template.
|
|
14817
|
+
* @summary Resolves all rows concurrently via `Promise.all`, delegating each item to `itemMapper`.
|
|
14818
|
+
* @param {KeyValue[]} data - Raw row objects returned by the data source.
|
|
14819
|
+
* @return {Promise<KeyValue[]>} Array of structured row objects.
|
|
14820
|
+
*/
|
|
14504
14821
|
async mapResults(data) {
|
|
14505
14822
|
this._data = [...data];
|
|
14506
14823
|
if (!data || !data.length)
|
|
14507
14824
|
return [];
|
|
14508
14825
|
return await Promise.all(data.map(async (curr) => await this.itemMapper(curr, this.mapper, { uid: curr[this.pk] })));
|
|
14509
14826
|
}
|
|
14827
|
+
/**
|
|
14828
|
+
* @description Handles a CRUD action triggered by a row action button.
|
|
14829
|
+
* @summary Invokes a custom handler or navigates to the appropriate route for the given action.
|
|
14830
|
+
* @param {IBaseCustomEvent} event - The originating event.
|
|
14831
|
+
* @param {UIFunctionLike | undefined} handler - Optional custom handler.
|
|
14832
|
+
* @param {string} uid - Primary key value of the target row.
|
|
14833
|
+
* @param {CrudOperations} action - The CRUD operation type.
|
|
14834
|
+
* @return {Promise<void>}
|
|
14835
|
+
*/
|
|
14510
14836
|
async handleAction(event, handler, uid, action) {
|
|
14511
14837
|
if (handler) {
|
|
14512
14838
|
const handlerFn = await handler(this, event, uid);
|
|
@@ -14514,6 +14840,14 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
14514
14840
|
}
|
|
14515
14841
|
await this.handleRedirect(event, uid, action);
|
|
14516
14842
|
}
|
|
14843
|
+
/**
|
|
14844
|
+
* @description Navigates to the CRUD action route for the specified row.
|
|
14845
|
+
* @summary Verifies the requested `action` and navigates to the appropriate route.
|
|
14846
|
+
* @param {Event | IBaseCustomEvent} event - The originating event.
|
|
14847
|
+
* @param {string} uid - Primary key value of the target row.
|
|
14848
|
+
* @param {CrudOperations} action - The CRUD operation to navigate to.
|
|
14849
|
+
* @return {Promise<void>}
|
|
14850
|
+
*/
|
|
14517
14851
|
async handleRedirect(event, uid, action) {
|
|
14518
14852
|
if (event instanceof Event) {
|
|
14519
14853
|
event.preventDefault();
|
|
@@ -14523,6 +14857,12 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
14523
14857
|
await this.router.navigate([`/${this.route}/${action}/${uid}`]);
|
|
14524
14858
|
}
|
|
14525
14859
|
}
|
|
14860
|
+
/**
|
|
14861
|
+
* @description Opens the filter select UI, allowing the user to narrow table results by a field value.
|
|
14862
|
+
* @summary Determines the presentation mode and handles user selection.
|
|
14863
|
+
* @param {Event} event - The click event that triggered the filter open action.
|
|
14864
|
+
* @return {Promise<void>}
|
|
14865
|
+
*/
|
|
14526
14866
|
async openFilterSelectOptions(event) {
|
|
14527
14867
|
const type = this.filterOptions.length > 10 ? SelectFieldInterfaces.MODAL : SelectFieldInterfaces.POPOVER;
|
|
14528
14868
|
if (type === SelectFieldInterfaces.MODAL) {
|
|
@@ -14546,6 +14886,12 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
14546
14886
|
}
|
|
14547
14887
|
}
|
|
14548
14888
|
}
|
|
14889
|
+
/**
|
|
14890
|
+
* @description Clears the active filter selection and resets the table to an unfiltered state.
|
|
14891
|
+
* @summary Resets `filterValue` and reloads the full data set.
|
|
14892
|
+
* @param {CustomEvent} event - The clear event emitted by the filter select control.
|
|
14893
|
+
* @return {Promise<void>}
|
|
14894
|
+
*/
|
|
14549
14895
|
async handleFilterSelectClear(event) {
|
|
14550
14896
|
event.preventDefault();
|
|
14551
14897
|
event.stopImmediatePropagation();
|
|
@@ -14555,7 +14901,7 @@ let TableComponent = class TableComponent extends ListComponent {
|
|
|
14555
14901
|
}
|
|
14556
14902
|
}
|
|
14557
14903
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
|
|
14558
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: TableComponent, isStandalone: true, selector: "ngx-decaf-table", inputs: { filterModel: "filterModel", filterOptions: "filterOptions", filterLabel: "filterLabel", filterOptionsMapper: "filterOptionsMapper", allowOperations: "allowOperations" }, usesInheritance: true, ngImport: i0, template: "@if (showSearchbar && (data?.length || searching)) {\n <div class=\"dcf-grid-actions\">\n <div class=\"dcf-grid dcf-grid-small\">\n <div class=\"dcf-width-expand@s\">\n <ngx-decaf-searchbar\n [emitEventToWindow]=\"false\"\n [debounce]=\"500\"\n (searchEvent)=\"handleSearch($event)\"\n />\n </div>\n @if (filterOptions?.length) {\n <div\n class=\"dcf-width-1-3@s dcf-width-1-4@m dcf-select-filter-container dcf-flex dcf-flex-middle\"\n >\n <ion-select\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [mode]=\"'md'\"\n fill=\"outline\"\n [value]=\"filterValue ?? ''\"\n [labelPlacement]=\"'floating'\"\n [label]=\"locale + '.filter.label' | translate\"\n (click)=\"openFilterSelectOptions($event)\"\n [placeholder]=\"locale + '.filter.label' | translate\"\n interface=\"popover\"\n >\n <ion-select-option value=\"\">\n {{ locale + '.filter.all' | translate }}\n </ion-select-option>\n @for (option of filterOptions; track $index) {\n <ion-select-option value=\"{{ option.value }}\">\n {{ option.text }}\n </ion-select-option>\n }\n <ion-button\n fill=\"clear\"\n (click)=\"handleFilterSelectClear($event)\"\n slot=\"end\"\n size=\"small\"\n [disabled]=\"!filterValue\"\n >\n <ngx-decaf-icon\n fill=\"clear\"\n slot=\"icon-only\"\n [name]=\"'ti-input-x'\"\n />\n </ion-button>\n </ion-select>\n </div>\n }\n </div>\n </div>\n}\n<div\n class=\"dcf-table-container\"\n [class.dcf-empty]=\"!data?.length\"\n #component\n>\n @if (initialized && data?.length) {\n <table class=\"dcf-table\">\n <thead>\n <tr>\n @for (header of headers; track $index) {\n <th>{{ locale + '.' + header + '.label' | translate }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (item of items; track trackItemFn($index, item)) {\n <tr>\n @for (col of item | keyvalue; track $index) {\n @if (!['handler', 'actions', 'uid'].includes(col.key)) {\n <td\n (click)=\"\n handleAction(\n $event,\n col?.value.handler ? col.value.handler.handle : undefined,\n item.uid.value,\n OperationKeys.READ\n )\n \"\n [innerHTML]=\"col.value.value\"\n ></td>\n } @else {\n @if (allowOperations && col.key !== 'handler') {\n <td class=\"dcf-col-actions\">\n <div class=\"\">\n @if (operations?.includes(OperationKeys.UPDATE)) {\n <ngx-decaf-icon\n [button]=\"true\"\n (click)=\"\n handleRedirect(\n $event,\n item.uid.value,\n OperationKeys.UPDATE,\n true\n )\n \"\n fill=\"clear\"\n slot=\"icon-only\"\n color=\"primary\"\n name=\"ti-edit\"\n />\n }\n @if (operations?.includes(OperationKeys.DELETE)) {\n <ngx-decaf-icon\n [button]=\"true\"\n (click)=\"\n handleRedirect(\n $event,\n item.uid.value,\n OperationKeys.DELETE,\n true\n )\n \"\n fill=\"clear\"\n slot=\"icon-only\"\n color=\"danger\"\n name=\"ti-trash\"\n />\n }\n </div>\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n @if (!searching) {\n <ngx-decaf-empty-state\n [title]=\"'component.list.empty.title' | translate\"\n [subtitle]=\"'component.list.empty.subtitle' | translate\"\n [model]=\"empty?.showButton ? model : undefined\"\n [route]=\"route\"\n [refreshing]=\"refreshing\"\n [modelId]=\"modelId\"\n [buttonLink]=\"empty?.link ?? undefined\"\n [borders]=\"borders\"\n [icon]=\"(item?.icon ?? 'folder-open-outline') || empty.icon\"\n className=\"dcf-empty-data\"\n />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n [model]=\"empty?.showButton ? model : undefined\"\n [route]=\"route\"\n [modelId]=\"modelId\"\n [borders]=\"borders\"\n [operations]=\"operations\"\n [body]=\"'small'\"\n [translatable]=\"true\"\n [title]=\"'component.list.search.title' | translate\"\n [subtitle]=\"\n 'component.list.search.subtitle'\n | translate: { '0': parseSearchValue() }\n \"\n [searchValue]=\"searchValue\"\n />\n }\n }\n</div>\n\n<div class=\"dcf-table-pagination\">\n @if (pages > 0 && !searchValue) {\n <ngx-decaf-pagination\n [table]=\"component\"\n [totalPages]=\"pages\"\n [disablePages]=\"disablePaginationPages\"\n [truncatePages]=\"truncatePaginationPages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n }\n</div>\n", styles: [".dcf-table-container{display:block;overflow-x:auto!important;box-sizing:border-box;overflow-y:hidden;scrollbar-width:thin;border-radius:var(--dcf-border-radius-small);box-shadow:var(--dcf-box-shadow-small)!important;background-color:var(--dcf-card-background);border:1px solid var(--dcf-color-gray-2)}.dcf-table-container::-webkit-scrollbar{width:5px}.dcf-table-container table{min-width:680px}.dcf-table{width:100%;border-collapse:collapse;border-radius:var(--dcf-border-radius-xsmall);overflow:hidden;background:var(--dcf-card-background);color:var(--dcf-text-color);font-size:.8rem}.dcf-table thead{background:rgba(var(--dcf-color-primary-rgb),.075);text-transform:uppercase;color:var(--dcf-color-dark);letter-spacing:.06em;font-size:.825rem;white-space:nowrap;width:auto}.dcf-table thead th{text-align:left;padding:.875rem 1rem;font-weight:600;max-width:max-content}.dcf-table tbody tr{transition:background .12s ease,box-shadow .12s ease}.dcf-table tbody tr:hover{background:rgba(var(--dcf-color-primary-rgb),.05);cursor:pointer}.dcf-table tbody tr:not(:last-child){border-bottom:1px solid var(--dcf-color-gray-2)}.dcf-table tbody td{padding:1rem 1.125rem;font-size:.875rem}.dcf-table tbody td:first-child{font-weight:600}.dcf-table tbody td.dcf-col-actions{padding-top:0!important;padding-bottom:0!important}.dcf-table tfoot{font-size:.85rem}.dcf-table tfoot td{padding:.875rem 1.125rem;border-top:1px solid 1px solid var(--dcf-color-gray-2)}.dcf-select-filter-container{min-width:200px}.dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (max-width: 480px){.dcf-buttons-grid{flex-direction:row-reverse!important}.dcf-buttons-grid>div{width:100%}.dcf-buttons-grid>div+div{margin-top:1rem}.dcf-buttons-grid ion-button{width:100%}}ion-select{margin-top:.5rem;max-height:40px!important}ion-select ion-button{transform:scale(.75)!important;margin:0!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: "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: IconComponent, selector: "ngx-decaf-icon", inputs: ["name", "color", "slot", "button", "buttonFill", "buttonShape", "width", "size", "inline"] }, { kind: "component", type: PaginationComponent, selector: "ngx-decaf-pagination", inputs: ["table", "totalPages", "current", "truncatePages", "disablePages"], outputs: ["clickEvent"] }, { kind: "pipe", type: i1$1.KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
14904
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.17", type: TableComponent, isStandalone: true, selector: "ngx-decaf-table", inputs: { maxContentLength: "maxContentLength", preserve: "preserve", filterModel: "filterModel", filterOptions: "filterOptions", filterLabel: "filterLabel", filterOptionsMapper: "filterOptionsMapper", allowOperations: "allowOperations" }, usesInheritance: true, ngImport: i0, template: "@if (showSearchbar && (data?.length || searching)) {\n <div class=\"dcf-grid-actions\">\n <div class=\"dcf-grid dcf-grid-small\">\n <div class=\"dcf-width-expand@s\">\n <ngx-decaf-searchbar\n [emitEventToWindow]=\"false\"\n [debounce]=\"500\"\n (searchEvent)=\"handleSearch($event)\"\n />\n </div>\n @if (filterOptions?.length) {\n <div\n class=\"dcf-width-1-3@s dcf-width-1-4@m dcf-select-filter-container dcf-flex dcf-flex-middle\"\n >\n <ion-select\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [mode]=\"'md'\"\n fill=\"outline\"\n [value]=\"filterValue ?? ''\"\n [labelPlacement]=\"'floating'\"\n [label]=\"locale + '.filter.label' | translate\"\n (click)=\"openFilterSelectOptions($event)\"\n [placeholder]=\"locale + '.filter.label' | translate\"\n interface=\"popover\"\n >\n <ion-select-option value=\"\">\n {{ locale + '.filter.all' | translate }}\n </ion-select-option>\n @for (option of filterOptions; track $index) {\n <ion-select-option value=\"{{ option.value }}\">\n {{ option.text }}\n </ion-select-option>\n }\n <ion-button\n fill=\"clear\"\n (click)=\"handleFilterSelectClear($event)\"\n slot=\"end\"\n size=\"small\"\n [disabled]=\"!filterValue\"\n >\n <ngx-decaf-icon\n fill=\"clear\"\n slot=\"icon-only\"\n [name]=\"'ti-input-x'\"\n />\n </ion-button>\n </ion-select>\n </div>\n }\n </div>\n </div>\n}\n<div\n class=\"dcf-table-container\"\n [class.dcf-empty]=\"!data?.length\"\n #component\n>\n @if (initialized && data?.length) {\n <table class=\"dcf-table\">\n <thead>\n <tr>\n @for (header of headers; track $index) {\n <th>{{ locale + '.' + header + '.label' | translate }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (item of items; track trackItemFn($index, item)) {\n <tr>\n @for (col of item | keyvalue; track $index) {\n @if (!['handler', 'actions', 'uid'].includes(col.key)) {\n <td\n (click)=\"\n handleAction(\n $event,\n col?.value.handler ? col.value.handler.handle : undefined,\n item.uid.value,\n OperationKeys.READ\n )\n \"\n [innerHTML]=\"col.value.value\"\n [ngx-decaf-tooltip]=\"\n maxContentLength > 0 && !preserve.includes(col.value.prop)\n ? { text: col.value.value, truncate: maxContentLength }\n : {}\n \"\n ></td>\n } @else {\n @if (allowOperations && col.key !== 'handler') {\n <td class=\"dcf-col-actions\">\n <div class=\"\">\n @if (operations?.includes(OperationKeys.UPDATE)) {\n <ngx-decaf-icon\n [button]=\"true\"\n (click)=\"\n handleRedirect(\n $event,\n item.uid.value,\n OperationKeys.UPDATE,\n true\n )\n \"\n fill=\"clear\"\n slot=\"icon-only\"\n color=\"primary\"\n name=\"ti-edit\"\n />\n }\n @if (operations?.includes(OperationKeys.DELETE)) {\n <ngx-decaf-icon\n [button]=\"true\"\n (click)=\"\n handleRedirect(\n $event,\n item.uid.value,\n OperationKeys.DELETE,\n true\n )\n \"\n fill=\"clear\"\n slot=\"icon-only\"\n color=\"danger\"\n name=\"ti-trash\"\n />\n }\n </div>\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n @if (!searching) {\n <ngx-decaf-empty-state\n [title]=\"'component.list.empty.title' | translate\"\n [subtitle]=\"'component.list.empty.subtitle' | translate\"\n [model]=\"empty?.showButton ? model : undefined\"\n [route]=\"route\"\n [refreshing]=\"refreshing\"\n [modelId]=\"modelId\"\n [buttonLink]=\"empty?.link ?? undefined\"\n [borders]=\"borders\"\n [icon]=\"(item?.icon ?? 'folder-open-outline') || empty.icon\"\n className=\"dcf-empty-data\"\n />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n [model]=\"empty?.showButton ? model : undefined\"\n [route]=\"route\"\n [modelId]=\"modelId\"\n [borders]=\"borders\"\n [operations]=\"operations\"\n [body]=\"'small'\"\n [translatable]=\"true\"\n [title]=\"'component.list.search.title' | translate\"\n [subtitle]=\"\n 'component.list.search.subtitle'\n | translate: { '0': parseSearchValue() }\n \"\n [searchValue]=\"searchValue\"\n />\n }\n }\n</div>\n\n<div class=\"dcf-table-pagination\">\n @if (pages > 0 && !searchValue) {\n <ngx-decaf-pagination\n [table]=\"component\"\n [totalPages]=\"pages\"\n [disablePages]=\"disablePaginationPages\"\n [truncatePages]=\"truncatePaginationPages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n }\n</div>\n", styles: [".dcf-table-container{display:block;overflow-x:auto!important;box-sizing:border-box;overflow-y:hidden;scrollbar-width:thin;border-radius:var(--dcf-border-radius-small);box-shadow:var(--dcf-box-shadow-small)!important;background-color:var(--dcf-card-background);border:1px solid var(--dcf-color-gray-2)}.dcf-table-container::-webkit-scrollbar{width:5px}.dcf-table-container table{min-width:680px}.dcf-table{width:100%;border-collapse:collapse;border-radius:var(--dcf-border-radius-xsmall);overflow:hidden;background:var(--dcf-card-background);color:var(--dcf-text-color);font-size:.8rem}.dcf-table thead{background:rgba(var(--dcf-color-primary-rgb),.075);text-transform:uppercase;color:var(--dcf-color-dark);letter-spacing:.06em;font-size:.825rem;white-space:nowrap;width:auto}.dcf-table thead th{text-align:left;padding:.875rem 1rem;font-weight:600;max-width:max-content}.dcf-table tbody tr{transition:background .12s ease,box-shadow .12s ease}.dcf-table tbody tr:hover{background:rgba(var(--dcf-color-primary-rgb),.05);cursor:pointer}.dcf-table tbody tr:not(:last-child){border-bottom:1px solid var(--dcf-color-gray-2)}.dcf-table tbody td{padding:1rem 1.125rem;font-size:.875rem}.dcf-table tbody td:first-child{font-weight:600}.dcf-table tbody td.dcf-col-actions{padding-top:0!important;padding-bottom:0!important}.dcf-table tfoot{font-size:.85rem}.dcf-table tfoot td{padding:.875rem 1.125rem;border-top:1px solid 1px solid var(--dcf-color-gray-2)}.dcf-select-filter-container{min-width:200px}.dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (max-width: 480px){.dcf-buttons-grid{flex-direction:row-reverse!important}.dcf-buttons-grid>div{width:100%}.dcf-buttons-grid>div+div{margin-top:1rem}.dcf-buttons-grid ion-button{width:100%}}ion-select{margin-top:.5rem;max-height:40px!important}ion-select ion-button{transform:scale(.75)!important;margin:0!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: "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: IconComponent, selector: "ngx-decaf-icon", inputs: ["name", "color", "slot", "button", "buttonFill", "buttonShape", "width", "size", "inline"] }, { kind: "component", type: PaginationComponent, selector: "ngx-decaf-pagination", inputs: ["table", "totalPages", "current", "truncatePages", "disablePages"], outputs: ["clickEvent"] }, { kind: "directive", type: DecafTooltipDirective, selector: "[ngx-decaf-tooltip]", inputs: ["ngx-decaf-tooltip"] }, { kind: "pipe", type: i1$1.KeyValuePipe, name: "keyvalue" }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
|
|
14559
14905
|
};
|
|
14560
14906
|
TableComponent = __decorate([
|
|
14561
14907
|
Dynamic()
|
|
@@ -14571,8 +14917,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14571
14917
|
EmptyStateComponent,
|
|
14572
14918
|
IconComponent,
|
|
14573
14919
|
PaginationComponent,
|
|
14574
|
-
|
|
14575
|
-
}],
|
|
14920
|
+
DecafTooltipDirective,
|
|
14921
|
+
], template: "@if (showSearchbar && (data?.length || searching)) {\n <div class=\"dcf-grid-actions\">\n <div class=\"dcf-grid dcf-grid-small\">\n <div class=\"dcf-width-expand@s\">\n <ngx-decaf-searchbar\n [emitEventToWindow]=\"false\"\n [debounce]=\"500\"\n (searchEvent)=\"handleSearch($event)\"\n />\n </div>\n @if (filterOptions?.length) {\n <div\n class=\"dcf-width-1-3@s dcf-width-1-4@m dcf-select-filter-container dcf-flex dcf-flex-middle\"\n >\n <ion-select\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [mode]=\"'md'\"\n fill=\"outline\"\n [value]=\"filterValue ?? ''\"\n [labelPlacement]=\"'floating'\"\n [label]=\"locale + '.filter.label' | translate\"\n (click)=\"openFilterSelectOptions($event)\"\n [placeholder]=\"locale + '.filter.label' | translate\"\n interface=\"popover\"\n >\n <ion-select-option value=\"\">\n {{ locale + '.filter.all' | translate }}\n </ion-select-option>\n @for (option of filterOptions; track $index) {\n <ion-select-option value=\"{{ option.value }}\">\n {{ option.text }}\n </ion-select-option>\n }\n <ion-button\n fill=\"clear\"\n (click)=\"handleFilterSelectClear($event)\"\n slot=\"end\"\n size=\"small\"\n [disabled]=\"!filterValue\"\n >\n <ngx-decaf-icon\n fill=\"clear\"\n slot=\"icon-only\"\n [name]=\"'ti-input-x'\"\n />\n </ion-button>\n </ion-select>\n </div>\n }\n </div>\n </div>\n}\n<div\n class=\"dcf-table-container\"\n [class.dcf-empty]=\"!data?.length\"\n #component\n>\n @if (initialized && data?.length) {\n <table class=\"dcf-table\">\n <thead>\n <tr>\n @for (header of headers; track $index) {\n <th>{{ locale + '.' + header + '.label' | translate }}</th>\n }\n </tr>\n </thead>\n <tbody>\n @for (item of items; track trackItemFn($index, item)) {\n <tr>\n @for (col of item | keyvalue; track $index) {\n @if (!['handler', 'actions', 'uid'].includes(col.key)) {\n <td\n (click)=\"\n handleAction(\n $event,\n col?.value.handler ? col.value.handler.handle : undefined,\n item.uid.value,\n OperationKeys.READ\n )\n \"\n [innerHTML]=\"col.value.value\"\n [ngx-decaf-tooltip]=\"\n maxContentLength > 0 && !preserve.includes(col.value.prop)\n ? { text: col.value.value, truncate: maxContentLength }\n : {}\n \"\n ></td>\n } @else {\n @if (allowOperations && col.key !== 'handler') {\n <td class=\"dcf-col-actions\">\n <div class=\"\">\n @if (operations?.includes(OperationKeys.UPDATE)) {\n <ngx-decaf-icon\n [button]=\"true\"\n (click)=\"\n handleRedirect(\n $event,\n item.uid.value,\n OperationKeys.UPDATE,\n true\n )\n \"\n fill=\"clear\"\n slot=\"icon-only\"\n color=\"primary\"\n name=\"ti-edit\"\n />\n }\n @if (operations?.includes(OperationKeys.DELETE)) {\n <ngx-decaf-icon\n [button]=\"true\"\n (click)=\"\n handleRedirect(\n $event,\n item.uid.value,\n OperationKeys.DELETE,\n true\n )\n \"\n fill=\"clear\"\n slot=\"icon-only\"\n color=\"danger\"\n name=\"ti-trash\"\n />\n }\n </div>\n </td>\n }\n }\n }\n </tr>\n }\n </tbody>\n </table>\n } @else {\n @if (!searching) {\n <ngx-decaf-empty-state\n [title]=\"'component.list.empty.title' | translate\"\n [subtitle]=\"'component.list.empty.subtitle' | translate\"\n [model]=\"empty?.showButton ? model : undefined\"\n [route]=\"route\"\n [refreshing]=\"refreshing\"\n [modelId]=\"modelId\"\n [buttonLink]=\"empty?.link ?? undefined\"\n [borders]=\"borders\"\n [icon]=\"(item?.icon ?? 'folder-open-outline') || empty.icon\"\n className=\"dcf-empty-data\"\n />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n [model]=\"empty?.showButton ? model : undefined\"\n [route]=\"route\"\n [modelId]=\"modelId\"\n [borders]=\"borders\"\n [operations]=\"operations\"\n [body]=\"'small'\"\n [translatable]=\"true\"\n [title]=\"'component.list.search.title' | translate\"\n [subtitle]=\"\n 'component.list.search.subtitle'\n | translate: { '0': parseSearchValue() }\n \"\n [searchValue]=\"searchValue\"\n />\n }\n }\n</div>\n\n<div class=\"dcf-table-pagination\">\n @if (pages > 0 && !searchValue) {\n <ngx-decaf-pagination\n [table]=\"component\"\n [totalPages]=\"pages\"\n [disablePages]=\"disablePaginationPages\"\n [truncatePages]=\"truncatePaginationPages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n }\n</div>\n", styles: [".dcf-table-container{display:block;overflow-x:auto!important;box-sizing:border-box;overflow-y:hidden;scrollbar-width:thin;border-radius:var(--dcf-border-radius-small);box-shadow:var(--dcf-box-shadow-small)!important;background-color:var(--dcf-card-background);border:1px solid var(--dcf-color-gray-2)}.dcf-table-container::-webkit-scrollbar{width:5px}.dcf-table-container table{min-width:680px}.dcf-table{width:100%;border-collapse:collapse;border-radius:var(--dcf-border-radius-xsmall);overflow:hidden;background:var(--dcf-card-background);color:var(--dcf-text-color);font-size:.8rem}.dcf-table thead{background:rgba(var(--dcf-color-primary-rgb),.075);text-transform:uppercase;color:var(--dcf-color-dark);letter-spacing:.06em;font-size:.825rem;white-space:nowrap;width:auto}.dcf-table thead th{text-align:left;padding:.875rem 1rem;font-weight:600;max-width:max-content}.dcf-table tbody tr{transition:background .12s ease,box-shadow .12s ease}.dcf-table tbody tr:hover{background:rgba(var(--dcf-color-primary-rgb),.05);cursor:pointer}.dcf-table tbody tr:not(:last-child){border-bottom:1px solid var(--dcf-color-gray-2)}.dcf-table tbody td{padding:1rem 1.125rem;font-size:.875rem}.dcf-table tbody td:first-child{font-weight:600}.dcf-table tbody td.dcf-col-actions{padding-top:0!important;padding-bottom:0!important}.dcf-table tfoot{font-size:.85rem}.dcf-table tfoot td{padding:.875rem 1.125rem;border-top:1px solid 1px solid var(--dcf-color-gray-2)}.dcf-select-filter-container{min-width:200px}.dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (max-width: 480px){.dcf-buttons-grid{flex-direction:row-reverse!important}.dcf-buttons-grid>div{width:100%}.dcf-buttons-grid>div+div{margin-top:1rem}.dcf-buttons-grid ion-button{width:100%}}ion-select{margin-top:.5rem;max-height:40px!important}ion-select ion-button{transform:scale(.75)!important;margin:0!important}\n"] }]
|
|
14922
|
+
}], propDecorators: { maxContentLength: [{
|
|
14923
|
+
type: Input
|
|
14924
|
+
}], preserve: [{
|
|
14925
|
+
type: Input
|
|
14926
|
+
}], filterModel: [{
|
|
14576
14927
|
type: Input
|
|
14577
14928
|
}], filterOptions: [{
|
|
14578
14929
|
type: Input
|
|
@@ -14690,72 +15041,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14690
15041
|
*/
|
|
14691
15042
|
// Component exports
|
|
14692
15043
|
|
|
14693
|
-
/**
|
|
14694
|
-
* @description Abstract base class for dynamic Angular modules
|
|
14695
|
-
* @summary The DynamicModule serves as a base class for Angular modules that need to be
|
|
14696
|
-
* dynamically loaded or configured at runtime. It provides a common type for the rendering
|
|
14697
|
-
* engine to identify and work with dynamic modules.
|
|
14698
|
-
* @class DynamicModule
|
|
14699
|
-
* @example
|
|
14700
|
-
* ```typescript
|
|
14701
|
-
* @NgModule({
|
|
14702
|
-
* declarations: [MyComponent],
|
|
14703
|
-
* imports: [CommonModule]
|
|
14704
|
-
* })
|
|
14705
|
-
* export class MyDynamicModule extends DynamicModule {}
|
|
14706
|
-
* ```
|
|
14707
|
-
*/
|
|
14708
|
-
class DynamicModule {
|
|
14709
|
-
}
|
|
14710
|
-
|
|
14711
|
-
class NgxEventHandler extends DecafEventHandler {
|
|
14712
|
-
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
|
14713
|
-
constructor() {
|
|
14714
|
-
super();
|
|
14715
|
-
this._data = null;
|
|
14716
|
-
}
|
|
14717
|
-
async handle(event, data, instance, ...args) {
|
|
14718
|
-
this.log
|
|
14719
|
-
.for(this.handle)
|
|
14720
|
-
.info(`Handle called with args: ${event}, ${data}, ${instance}, ${args}`);
|
|
14721
|
-
}
|
|
14722
|
-
from(...args) {
|
|
14723
|
-
this.log.for(this.process).info(`Process called with args: ${args}`);
|
|
14724
|
-
return this;
|
|
14725
|
-
}
|
|
14726
|
-
async process(...args) {
|
|
14727
|
-
this.log.for(this.process).info(`Process called with args: ${args}`);
|
|
14728
|
-
}
|
|
14729
|
-
async delete(...args) {
|
|
14730
|
-
this.log.for(this.delete).info(`Delete called with args: ${args}`);
|
|
14731
|
-
}
|
|
14732
|
-
async batchOperation(...args) {
|
|
14733
|
-
this.log.for(this.batchOperation).info(`batchOperation called with args: ${args}`);
|
|
14734
|
-
}
|
|
14735
|
-
async beforeCreate(...args) {
|
|
14736
|
-
this.log.for(this.beforeCreate).info(`beforeCreate called with args: ${args}`);
|
|
14737
|
-
}
|
|
14738
|
-
async beforeUpdate(...args) {
|
|
14739
|
-
this.log.for(this.beforeUpdate).info(`beforeUpdate called with args: ${args}`);
|
|
14740
|
-
}
|
|
14741
|
-
async afterCreate(...args) {
|
|
14742
|
-
this.log.for(this.afterCreate).info(`afterCreate called with args: ${args}`);
|
|
14743
|
-
}
|
|
14744
|
-
async afterUpdate(...args) {
|
|
14745
|
-
this.log.for(this.afterUpdate).info(`afterUpdate called with args: ${args}`);
|
|
14746
|
-
}
|
|
14747
|
-
}
|
|
14748
|
-
|
|
14749
|
-
/**
|
|
14750
|
-
* @module engine
|
|
14751
|
-
* @description Angular rendering engine for Decaf applications
|
|
14752
|
-
* @summary The engine module provides core functionality for rendering Angular components
|
|
14753
|
-
* in Decaf applications. It includes constants, decorators, rendering engines, and utility types
|
|
14754
|
-
* that enable dynamic component creation, property mapping, and component lifecycle management.
|
|
14755
|
-
* Key exports include {@link NgxRenderingEngine}, {@link DynamicModule}, and various decorators
|
|
14756
|
-
* for component configuration.
|
|
14757
|
-
*/
|
|
14758
|
-
|
|
14759
15044
|
/**
|
|
14760
15045
|
* @module lib/for-angular-common.module
|
|
14761
15046
|
* @description Core Angular module and providers for Decaf's for-angular package.
|
|
@@ -14843,6 +15128,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14843
15128
|
}]
|
|
14844
15129
|
}] });
|
|
14845
15130
|
|
|
15131
|
+
/**
|
|
15132
|
+
* @module DecafTranslatePipe
|
|
15133
|
+
* @description Angular pipe for translating text using the `@ngx-translate/core` library.
|
|
15134
|
+
* @summary The `DecafTranslatePipe` provides a mechanism to translate text keys into localized
|
|
15135
|
+
* strings based on the current language settings. It integrates with the `TranslateService`
|
|
15136
|
+
* to fetch translations dynamically and supports fallback rendering for untranslated keys.
|
|
15137
|
+
* @class DecafTranslatePipe
|
|
15138
|
+
* @implements {PipeTransform}
|
|
15139
|
+
*/
|
|
15140
|
+
class DecafTranslatePipe {
|
|
15141
|
+
constructor() {
|
|
15142
|
+
/**
|
|
15143
|
+
* @description Injected instance of the `TranslateService` for handling translations.
|
|
15144
|
+
* @type {TranslateService}
|
|
15145
|
+
*/
|
|
15146
|
+
this.translate = inject(TranslateService);
|
|
15147
|
+
}
|
|
15148
|
+
/**
|
|
15149
|
+
* @description Transforms a text key into its localized string representation.
|
|
15150
|
+
* @summary Uses the `TranslateService` to fetch the translated string for the provided key.
|
|
15151
|
+
* If translations are disabled or the key is not found, it returns a fallback HTML-wrapped key.
|
|
15152
|
+
* @param {string} value - The translation key to be transformed.
|
|
15153
|
+
* @param {...any[]} args - Optional arguments to interpolate within the translation string.
|
|
15154
|
+
* @return {string} The translated string or a fallback HTML-wrapped key.
|
|
15155
|
+
* @example
|
|
15156
|
+
* ```html
|
|
15157
|
+
* {{ 'HELLO_WORLD' | translate }}
|
|
15158
|
+
* ```
|
|
15159
|
+
*/
|
|
15160
|
+
transform(value, ...args) {
|
|
15161
|
+
if (I18nLoader.enabled && value) {
|
|
15162
|
+
return this.translate.instant(value, ...args);
|
|
15163
|
+
}
|
|
15164
|
+
return `<div class="dcf-translation-key">${sf(value, args)}</div>`;
|
|
15165
|
+
}
|
|
15166
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DecafTranslatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
|
|
15167
|
+
static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.17", ngImport: i0, type: DecafTranslatePipe, isStandalone: true, name: "translate" }); }
|
|
15168
|
+
}
|
|
15169
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: DecafTranslatePipe, decorators: [{
|
|
15170
|
+
type: Pipe,
|
|
15171
|
+
args: [{
|
|
15172
|
+
name: 'translate',
|
|
15173
|
+
// pure: false,
|
|
15174
|
+
standalone: true,
|
|
15175
|
+
}]
|
|
15176
|
+
}] });
|
|
15177
|
+
|
|
14846
15178
|
/**
|
|
14847
15179
|
* @module module:lib/public-apis
|
|
14848
15180
|
* @description Public exports for the for-angular package.
|
|
@@ -14864,5 +15196,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
|
|
|
14864
15196
|
* Generated bundle index. Do not edit.
|
|
14865
15197
|
*/
|
|
14866
15198
|
|
|
14867
|
-
export { ActionRoles, AngularEngineKeys, BaseComponentProps, CPTKN, CardComponent, ComponentRendererComponent, ComponentsTagNames, CrudFieldComponent, CrudFormComponent, CssClasses, DB_ADAPTER_FLAVOUR_TOKEN, DB_ADAPTER_PROVIDER_TOKEN, DecafFakerRepository, DecafTranslatePipe, DefaultFormReactiveOptions, DefaultListEmptyOptions, DefaultModalOptions, Dynamic, DynamicModule, EmptyStateComponent, FieldsetComponent, FileUploadComponent, FilterComponent, ForAngularCommonModule, ForAngularComponentsModule, I18N_CONFIG_TOKEN, I18nLoader, I18nLoaderFactory, I18nParser, IconComponent, LOCALE_ROOT_TOKEN, LayoutComponent, ListComponent, ListComponentsTypes, ListItemComponent, ListItemPositions, ModalComponent, ModalConfirmComponent, ModelRendererComponent, NgxComponentDirective, NgxEventHandler, NgxFormDirective, NgxFormFieldDirective, NgxFormService, NgxMediaService, NgxModelPageDirective, NgxPageDirective, NgxParentComponentDirective, NgxRenderingEngine, NgxRouterService, NgxSvgDirective, PaginationComponent, RouteDirections, SearchbarComponent, SelectFieldInterfaces, SteppedFormComponent, TableComponent, WindowColorSchemes, cleanSpaces, dataMapper, decafPageTransition, filterString, formatDate, generateRandomValue, getDbAdapterFlavour, getFakerData, getInjectablesRegistry, getLocaleContext, getLocaleContextByKey, getLocaleFromClassName, getLocaleLanguage, getLogger, getMenuIcon, getModelAndRepository, getNgxInlineModal, getNgxModalComponent, getNgxModalCrudComponent, getNgxSelectOptionsModal, getOnWindow, getOnWindowDocument, getWindow, getWindowDocument, getWindowWidth, isDarkMode, isDevelopmentMode, isNotUndefined, isValidDate, itemMapper, patternValidators, presentModalConfirm, presentNgxInlineModal, presentNgxLightBoxModal, provideDecafDarkMode, provideDecafDbAdapter, provideDecafDynamicComponents, provideDecafI18nConfig, provideDecafI18nLoader, provideDecafPageTransition, removeFocusTrap, setOnWindow, stringToBoolean, windowEventEmitter };
|
|
15199
|
+
export { ActionRoles, AngularEngineKeys, BaseComponentProps, CPTKN, CardComponent, ComponentRendererComponent, ComponentsTagNames, CrudFieldComponent, CrudFormComponent, CssClasses, DB_ADAPTER_FLAVOUR_TOKEN, DB_ADAPTER_PROVIDER_TOKEN, DecafFakerRepository, DecafTooltipDirective, DecafTranslatePipe, DecafTruncatePipe, DefaultFormReactiveOptions, DefaultListEmptyOptions, DefaultModalOptions, Dynamic, DynamicModule, EmptyStateComponent, FieldsetComponent, FileUploadComponent, FilterComponent, ForAngularCommonModule, ForAngularComponentsModule, I18N_CONFIG_TOKEN, I18nLoader, I18nLoaderFactory, I18nParser, IconComponent, LOCALE_ROOT_TOKEN, LayoutComponent, ListComponent, ListComponentsTypes, ListItemComponent, ListItemPositions, ModalComponent, ModalConfirmComponent, ModelRendererComponent, NgxComponentDirective, NgxEventHandler, NgxFormDirective, NgxFormFieldDirective, NgxFormService, NgxMediaService, NgxModelPageDirective, NgxPageDirective, NgxParentComponentDirective, NgxRenderingEngine, NgxRouterService, NgxSvgDirective, PaginationComponent, RouteDirections, SearchbarComponent, SelectFieldInterfaces, SteppedFormComponent, TableComponent, WindowColorSchemes, cleanSpaces, dataMapper, dateFromString, decafPageTransition, filterString, formatDate, generateRandomValue, getDbAdapterFlavour, getFakerData, getInjectablesRegistry, getLocaleContext, getLocaleContextByKey, getLocaleFromClassName, getLocaleLanguage, getLogger, getMenuIcon, getModelAndRepository, getNgxInlineModal, getNgxModalComponent, getNgxModalCrudComponent, getNgxSelectOptionsModal, getOnWindow, getOnWindowDocument, getWindow, getWindowDocument, getWindowWidth, isDarkMode, isDevelopmentMode, isNotUndefined, isValidDate, itemMapper, patternValidators, presentModalConfirm, presentNgxInlineModal, presentNgxLightBoxModal, provideDecafDarkMode, provideDecafDbAdapter, provideDecafDynamicComponents, provideDecafI18nConfig, provideDecafI18nLoader, provideDecafPageTransition, removeFocusTrap, setOnWindow, stringToBoolean, windowEventEmitter };
|
|
14868
15200
|
//# sourceMappingURL=decaf-ts-for-angular.mjs.map
|