@decaf-ts/for-angular 0.1.18 → 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.
@@ -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, Pipe, NgZone, Injectable, Input, Directive, signal, ChangeDetectorRef, EnvironmentInjector, Renderer2, EventEmitter, ElementRef, Output, ViewChild, Inject, ViewContainerRef, TemplateRef, Component, ViewEncapsulation, HostListener, NgModule } from '@angular/core';
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) || '');
@@ -1867,6 +1871,7 @@ class NgxFormService {
1867
1871
  const parentProps = NgxFormService.getPropsFromControl(formGroup);
1868
1872
  for (const key in formGroup.controls) {
1869
1873
  const control = formGroup.controls[key];
1874
+ const props = NgxFormService.getPropsFromControl(control);
1870
1875
  if (!(control instanceof FormControl)) {
1871
1876
  if (control.disabled) {
1872
1877
  if (control instanceof FormGroup) {
@@ -1875,6 +1880,7 @@ class NgxFormService {
1875
1880
  continue;
1876
1881
  }
1877
1882
  data[key] = NgxFormService.getFormData(control);
1883
+ continue;
1878
1884
  }
1879
1885
  if (control instanceof FormArray) {
1880
1886
  const value = this.getFormArrayControlsValue(control);
@@ -1893,7 +1899,7 @@ class NgxFormService {
1893
1899
  }
1894
1900
  const value = control.value;
1895
1901
  const isValid = control.valid;
1896
- if (parentProps.multiple) {
1902
+ if (parentProps?.multiple) {
1897
1903
  if (isValid) {
1898
1904
  data[key] = Array.isArray(value) ? value : [value];
1899
1905
  }
@@ -1905,7 +1911,6 @@ class NgxFormService {
1905
1911
  data[key] = NgxFormService.getFormData(control);
1906
1912
  continue;
1907
1913
  }
1908
- const props = NgxFormService.getPropsFromControl(control);
1909
1914
  // const { readonly } = (props as IFormComponentProperties) || false; TODO: dont send readonly fields?
1910
1915
  let value = control.value;
1911
1916
  if (!HTML5CheckTypes.includes(props['type'])) {
@@ -1915,7 +1920,7 @@ class NgxFormService {
1915
1920
  break;
1916
1921
  case HTML5InputTypes.DATE:
1917
1922
  case HTML5InputTypes.DATETIME_LOCAL:
1918
- value = typeof value === Primitives.STRING ? new Date(`${value}T00:00:00`) : value;
1923
+ value = typeof value === Primitives.STRING ? dateFromString(value) : value;
1919
1924
  break;
1920
1925
  default:
1921
1926
  value = !isNaN(value) ? value : escapeHtml(value)?.trim();
@@ -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
- return this.instant(key, params);
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 = (await handler.bind(this)(model, repository, this.modelId));
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 = (await handler.bind(this)(model, repository, this.modelId));
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 = "dark";
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;
@@ -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,18 +14709,22 @@ 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
14719
  const getFilterOptionsMapper = (pk) => {
14423
14720
  if (!this.filterBy) {
14424
14721
  this.filterBy = pk;
14425
14722
  }
14426
14723
  if (!this.filterOptionsMapper) {
14427
- this.filterOptionsMapper =
14428
- this.filterOptionsMapper ||
14429
- ((item) => ({
14430
- text: `${item[pk]}`,
14431
- value: `${item[pk]}`,
14432
- }));
14724
+ this.filterOptionsMapper = (item) => ({
14725
+ text: `${item[pk]}`,
14726
+ value: `${item[pk]}`,
14727
+ });
14433
14728
  }
14434
14729
  };
14435
14730
  if (typeof this.filterModel === 'function') {
@@ -14445,6 +14740,14 @@ let TableComponent = class TableComponent extends ListComponent {
14445
14740
  }
14446
14741
  }
14447
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
+ */
14448
14751
  async itemMapper(item, mapper, props = {}) {
14449
14752
  this.model = item;
14450
14753
  const mapped = super.itemMapper(item, this.cols.filter((c) => c !== 'actions'), props);
@@ -14509,12 +14812,27 @@ let TableComponent = class TableComponent extends ListComponent {
14509
14812
  }
14510
14813
  return mapped;
14511
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
+ */
14512
14821
  async mapResults(data) {
14513
14822
  this._data = [...data];
14514
14823
  if (!data || !data.length)
14515
14824
  return [];
14516
14825
  return await Promise.all(data.map(async (curr) => await this.itemMapper(curr, this.mapper, { uid: curr[this.pk] })));
14517
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
+ */
14518
14836
  async handleAction(event, handler, uid, action) {
14519
14837
  if (handler) {
14520
14838
  const handlerFn = await handler(this, event, uid);
@@ -14522,6 +14840,14 @@ let TableComponent = class TableComponent extends ListComponent {
14522
14840
  }
14523
14841
  await this.handleRedirect(event, uid, action);
14524
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
+ */
14525
14851
  async handleRedirect(event, uid, action) {
14526
14852
  if (event instanceof Event) {
14527
14853
  event.preventDefault();
@@ -14531,6 +14857,12 @@ let TableComponent = class TableComponent extends ListComponent {
14531
14857
  await this.router.navigate([`/${this.route}/${action}/${uid}`]);
14532
14858
  }
14533
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
+ */
14534
14866
  async openFilterSelectOptions(event) {
14535
14867
  const type = this.filterOptions.length > 10 ? SelectFieldInterfaces.MODAL : SelectFieldInterfaces.POPOVER;
14536
14868
  if (type === SelectFieldInterfaces.MODAL) {
@@ -14554,6 +14886,12 @@ let TableComponent = class TableComponent extends ListComponent {
14554
14886
  }
14555
14887
  }
14556
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
+ */
14557
14895
  async handleFilterSelectClear(event) {
14558
14896
  event.preventDefault();
14559
14897
  event.stopImmediatePropagation();
@@ -14563,7 +14901,7 @@ let TableComponent = class TableComponent extends ListComponent {
14563
14901
  }
14564
14902
  }
14565
14903
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.17", ngImport: i0, type: TableComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
14566
- 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" }] }); }
14567
14905
  };
14568
14906
  TableComponent = __decorate([
14569
14907
  Dynamic()
@@ -14579,8 +14917,13 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
14579
14917
  EmptyStateComponent,
14580
14918
  IconComponent,
14581
14919
  PaginationComponent,
14582
- ], 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"] }]
14583
- }], propDecorators: { filterModel: [{
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: [{
14584
14927
  type: Input
14585
14928
  }], filterOptions: [{
14586
14929
  type: Input
@@ -14698,72 +15041,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
14698
15041
  */
14699
15042
  // Component exports
14700
15043
 
14701
- /**
14702
- * @description Abstract base class for dynamic Angular modules
14703
- * @summary The DynamicModule serves as a base class for Angular modules that need to be
14704
- * dynamically loaded or configured at runtime. It provides a common type for the rendering
14705
- * engine to identify and work with dynamic modules.
14706
- * @class DynamicModule
14707
- * @example
14708
- * ```typescript
14709
- * @NgModule({
14710
- * declarations: [MyComponent],
14711
- * imports: [CommonModule]
14712
- * })
14713
- * export class MyDynamicModule extends DynamicModule {}
14714
- * ```
14715
- */
14716
- class DynamicModule {
14717
- }
14718
-
14719
- class NgxEventHandler extends DecafEventHandler {
14720
- // eslint-disable-next-line @typescript-eslint/no-useless-constructor
14721
- constructor() {
14722
- super();
14723
- this._data = null;
14724
- }
14725
- async handle(event, data, instance, ...args) {
14726
- this.log
14727
- .for(this.handle)
14728
- .info(`Handle called with args: ${event}, ${data}, ${instance}, ${args}`);
14729
- }
14730
- from(...args) {
14731
- this.log.for(this.process).info(`Process called with args: ${args}`);
14732
- return this;
14733
- }
14734
- async process(...args) {
14735
- this.log.for(this.process).info(`Process called with args: ${args}`);
14736
- }
14737
- async delete(...args) {
14738
- this.log.for(this.delete).info(`Delete called with args: ${args}`);
14739
- }
14740
- async batchOperation(...args) {
14741
- this.log.for(this.batchOperation).info(`batchOperation called with args: ${args}`);
14742
- }
14743
- async beforeCreate(...args) {
14744
- this.log.for(this.beforeCreate).info(`beforeCreate called with args: ${args}`);
14745
- }
14746
- async beforeUpdate(...args) {
14747
- this.log.for(this.beforeUpdate).info(`beforeUpdate called with args: ${args}`);
14748
- }
14749
- async afterCreate(...args) {
14750
- this.log.for(this.afterCreate).info(`afterCreate called with args: ${args}`);
14751
- }
14752
- async afterUpdate(...args) {
14753
- this.log.for(this.afterUpdate).info(`afterUpdate called with args: ${args}`);
14754
- }
14755
- }
14756
-
14757
- /**
14758
- * @module engine
14759
- * @description Angular rendering engine for Decaf applications
14760
- * @summary The engine module provides core functionality for rendering Angular components
14761
- * in Decaf applications. It includes constants, decorators, rendering engines, and utility types
14762
- * that enable dynamic component creation, property mapping, and component lifecycle management.
14763
- * Key exports include {@link NgxRenderingEngine}, {@link DynamicModule}, and various decorators
14764
- * for component configuration.
14765
- */
14766
-
14767
15044
  /**
14768
15045
  * @module lib/for-angular-common.module
14769
15046
  * @description Core Angular module and providers for Decaf's for-angular package.
@@ -14851,6 +15128,53 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
14851
15128
  }]
14852
15129
  }] });
14853
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
+
14854
15178
  /**
14855
15179
  * @module module:lib/public-apis
14856
15180
  * @description Public exports for the for-angular package.
@@ -14872,5 +15196,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.17", ngImpo
14872
15196
  * Generated bundle index. Do not edit.
14873
15197
  */
14874
15198
 
14875
- 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 };
14876
15200
  //# sourceMappingURL=decaf-ts-for-angular.mjs.map