@decaf-ts/for-angular 0.1.42 → 0.1.43

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, uihandlers, 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, NgZone, Injectable, Input, Directive, signal, ChangeDetectorRef, EnvironmentInjector, Renderer2, EventEmitter, effect, ElementRef, Output, ViewChild, Inject, ViewContainerRef, TemplateRef, Component, ViewEncapsulation, HostListener, Pipe, NgModule } from '@angular/core';
3
+ import { InjectionToken, isDevMode, provideEnvironmentInitializer, reflectComponentType, Injector, createEnvironmentInjector, runInInjectionContext, createComponent, inject, NgZone, Injectable, Input, Directive, signal, ChangeDetectorRef, EnvironmentInjector, Renderer2, EventEmitter, effect, ElementRef, Output, ViewChild, Inject, ViewContainerRef, TemplateRef, Component, Pipe, ViewEncapsulation, HostListener, 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 { OperationKeys, InternalError, NotFoundError } from '@decaf-ts/db-decorators';
@@ -6064,6 +6064,213 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
6064
6064
  type: Input
6065
6065
  }] } });
6066
6066
 
6067
+ /**
6068
+ * @module lib/directives/NgxSvgDirective
6069
+ * @description Standalone directive that inlines SVG assets into the host element.
6070
+ * @summary Provides {@link NgxSvgDirective}, a lightweight Angular directive that resolves
6071
+ * an SVG file path from either its input binding or the host element's `src` attribute and
6072
+ * delegates the HTTP fetch and DOM injection to {@link NgxMediaService}.
6073
+ * @link {@link NgxSvgDirective}
6074
+ */
6075
+ /**
6076
+ * @description Angular directive that fetches an SVG file and inlines it into the host element.
6077
+ * @summary Standalone directive bound to the `[ngx-decaf-svg]` attribute selector. On
6078
+ * initialisation it resolves the SVG asset path from the `[ngx-decaf-svg]` input binding or,
6079
+ * as a fallback, the host element's native `src` attribute. Once a non-empty path is determined
6080
+ * it calls {@link NgxMediaService.loadSvgObserver}, which performs the HTTP request via
6081
+ * {@link HttpClient} and injects the SVG markup directly into the host element's DOM, enabling
6082
+ * full CSS styling of the inlined SVG.
6083
+ * @class NgxSvgDirective
6084
+ * @implements {OnInit}
6085
+ * @example
6086
+ * ```html
6087
+ * <!-- Via directive binding -->
6088
+ * <div [ngx-decaf-svg]="'/assets/icons/logo.svg'"></div>
6089
+ *
6090
+ * <!-- Fallback to src attribute -->
6091
+ * <img ngx-decaf-svg src="/assets/icons/arrow.svg" />
6092
+ * ```
6093
+ */
6094
+ class NgxSvgDirective {
6095
+ constructor() {
6096
+ /**
6097
+ * @description Service responsible for fetching and inlining the SVG markup.
6098
+ * @summary Injected {@link NgxMediaService} instance used by `ngOnInit` to perform the
6099
+ * HTTP request and inject the resulting SVG markup into the host element's DOM.
6100
+ * @type {NgxMediaService}
6101
+ * @memberOf module:lib/directives/NgxSvgDirective
6102
+ */
6103
+ this.mediaService = inject(NgxMediaService);
6104
+ /**
6105
+ * @description Reference to the host DOM element into which the SVG will be injected.
6106
+ * @summary Obtained via Angular's `inject(ElementRef)`. Provides access to the native
6107
+ * element forwarded to {@link NgxMediaService.loadSvgObserver} as the injection target,
6108
+ * and used as a fallback source for the `src` attribute when `path` is not set.
6109
+ * @type {ElementRef}
6110
+ * @memberOf module:lib/directives/NgxSvgDirective
6111
+ */
6112
+ this.element = inject(ElementRef);
6113
+ /**
6114
+ * @description HTTP client instance forwarded to the media service for the SVG fetch.
6115
+ * @summary Injected {@link HttpClient} passed directly to
6116
+ * {@link NgxMediaService.loadSvgObserver} so the service can issue the GET request for
6117
+ * the SVG file without managing its own HTTP dependency.
6118
+ * @type {HttpClient}
6119
+ * @memberOf module:lib/directives/NgxSvgDirective
6120
+ */
6121
+ this.http = inject(HttpClient);
6122
+ }
6123
+ /**
6124
+ * @description Resolves the SVG path and triggers the inline load.
6125
+ * @summary Trims `path` and, when empty, falls back to the host element's `src` attribute.
6126
+ * When a valid path is found, delegates to {@link NgxMediaService.loadSvgObserver} to
6127
+ * fetch the file and inject the SVG markup into the host element.
6128
+ * @returns {void}
6129
+ * @memberOf module:lib/directives/NgxSvgDirective
6130
+ */
6131
+ ngOnInit() {
6132
+ this.path = this.path?.trim() || this.element?.nativeElement?.getAttribute('src')?.trim() || '';
6133
+ if (this.path) {
6134
+ this.mediaService.loadSvgObserver(this.http, this.path, this.element.nativeElement);
6135
+ }
6136
+ }
6137
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: NgxSvgDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6138
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: NgxSvgDirective, isStandalone: true, selector: "[ngx-decaf-svg]", inputs: { path: ["ngx-decaf-svg", "path"] }, ngImport: i0 }); }
6139
+ }
6140
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: NgxSvgDirective, decorators: [{
6141
+ type: Directive,
6142
+ args: [{
6143
+ selector: '[ngx-decaf-svg]',
6144
+ standalone: true,
6145
+ }]
6146
+ }], propDecorators: { path: [{
6147
+ type: Input,
6148
+ args: ['ngx-decaf-svg']
6149
+ }] } });
6150
+
6151
+ class DecafTruncatePipe {
6152
+ transform(value, limit = 30, trail = '...') {
6153
+ if (!value) {
6154
+ return '';
6155
+ }
6156
+ const sanitized = this.sanitize(value);
6157
+ return sanitized.length > limit ? `${sanitized.substring(0, limit)}${trail}` : sanitized;
6158
+ }
6159
+ sanitize(value) {
6160
+ return value.replace(/<[^>]+>/g, '').trim();
6161
+ }
6162
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DecafTruncatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
6163
+ static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: DecafTruncatePipe, isStandalone: true, name: "truncate" }); }
6164
+ }
6165
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DecafTruncatePipe, decorators: [{
6166
+ type: Pipe,
6167
+ args: [{
6168
+ name: 'truncate',
6169
+ // pure: true,
6170
+ standalone: true,
6171
+ }]
6172
+ }] });
6173
+
6174
+ /**
6175
+ * @module DecafTooltipDirective
6176
+ * @description Provides a tooltip directive for the decaf-ts for-angular library.
6177
+ * @summary This module defines the {@link DecafTooltipDirective}, a standalone Angular directive
6178
+ * that dynamically appends a tooltip element to any host element it decorates. It also supports
6179
+ * optional text truncation using the {@link DecafTruncatePipe}.
6180
+ */
6181
+ /**
6182
+ * @description Angular directive that appends a tooltip `<span>` to the host element and
6183
+ * optionally truncates its visible text content.
6184
+ * @summary The `DecafTooltipDirective` is a standalone Angular directive bound to the
6185
+ * `[ngx-decaf-tooltip]` attribute selector. It processes the {@link TooltipConfig} provided
6186
+ * via the `options` input, sanitizes the text, and appends a `.dcf-tooltip` `<span>` containing
6187
+ * the sanitized full text to the host element. The directive also applies the `dcf-tooltip-parent`
6188
+ * CSS class to the host for tooltip positioning. When truncation is enabled, the host element's
6189
+ * inner content is replaced with the truncated text before the tooltip span is added.
6190
+ * @example
6191
+ * ```html
6192
+ * <!-- Basic tooltip -->
6193
+ * <span [ngx-decaf-tooltip]="{ text: 'Full description here' }">Hover me</span>
6194
+ *
6195
+ * <!-- Truncated visible text with tooltip showing the full content -->
6196
+ * <span [ngx-decaf-tooltip]="{ text: veryLongLabel, truncate: true, limit: 20, trail: '…' }">
6197
+ * {{ veryLongLabel }}
6198
+ * </span>
6199
+ * ```
6200
+ * @class DecafTooltipDirective
6201
+ */
6202
+ /**
6203
+ * @description Angular lifecycle hook invoked whenever one or more input properties change.
6204
+ * @summary Processes the {@link ITooltipConfig} options, sanitizes the text, and updates the
6205
+ * host element's content and tooltip span accordingly. Applies the `dcf-tooltip-parent` CSS class
6206
+ * to the host for styling.
6207
+ * @return {void}
6208
+ */
6209
+ class DecafTooltipDirective {
6210
+ constructor() {
6211
+ /**
6212
+ * @description Reference to the host DOM element into which the SVG will be injected.
6213
+ * @summary Obtained via Angular's `inject(ElementRef)`. Provides access to the native
6214
+ * element forwarded to {@link NgxMediaService.loadSvgObserver} as the injection target,
6215
+ * and used as a fallback source for the `src` attribute when `path` is not set.
6216
+ * @type {ElementRef}
6217
+ * @memberOf module:lib/directives/NgxSvgDirective
6218
+ */
6219
+ this.element = inject(ElementRef);
6220
+ this.renderer = inject(Renderer2);
6221
+ this.truncatePipe = inject(DecafTruncatePipe);
6222
+ }
6223
+ /**
6224
+ * @description Angular lifecycle hook invoked whenever one or more input properties change.
6225
+ * @summary Processes the {@link TooltipConfig} options, sanitizes the text, and updates the
6226
+ * host element's content and tooltip span accordingly. Applies the `dcf-tooltip-parent` CSS class
6227
+ * to the host for styling.
6228
+ * @return {void}
6229
+ */
6230
+ ngOnChanges() {
6231
+ const options = {
6232
+ truncate: false,
6233
+ limit: 30,
6234
+ ...{ position: 'top' },
6235
+ ...this.options,
6236
+ };
6237
+ if (options?.text && options?.text.trim().length) {
6238
+ const value = options.text.replace(/<[^>]+>/g, '').trim();
6239
+ if (value.length > options.limit) {
6240
+ const text = !options.truncate
6241
+ ? value
6242
+ : this.truncatePipe.transform(value, options.limit, options.trail || '...');
6243
+ const element = this.element?.nativeElement ? this.element?.nativeElement : this.element;
6244
+ if (options.truncate) {
6245
+ this.renderer.setProperty(element, 'innerHTML', '');
6246
+ const textNode = this.renderer.createText(text);
6247
+ this.renderer.appendChild(element, textNode);
6248
+ }
6249
+ // creating tooltip element
6250
+ const tooltip = this.renderer.createElement('span');
6251
+ this.renderer.addClass(tooltip, `dcf-tooltip`);
6252
+ this.renderer.addClass(tooltip, `dcf-tooltip-${options.position}`);
6253
+ this.renderer.appendChild(tooltip, this.renderer.createText(this.truncatePipe.sanitize(value)));
6254
+ this.renderer.appendChild(element, tooltip);
6255
+ this.renderer.addClass(element, 'dcf-tooltip-parent');
6256
+ }
6257
+ }
6258
+ }
6259
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DecafTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6260
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: DecafTooltipDirective, isStandalone: true, selector: "[ngx-decaf-tooltip]", inputs: { options: ["ngx-decaf-tooltip", "options"] }, providers: [DecafTruncatePipe], usesOnChanges: true, ngImport: i0 }); }
6261
+ }
6262
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DecafTooltipDirective, decorators: [{
6263
+ type: Directive,
6264
+ args: [{
6265
+ selector: '[ngx-decaf-tooltip]',
6266
+ providers: [DecafTruncatePipe],
6267
+ standalone: true,
6268
+ }]
6269
+ }], propDecorators: { options: [{
6270
+ type: Input,
6271
+ args: ['ngx-decaf-tooltip']
6272
+ }] } });
6273
+
6067
6274
  /**
6068
6275
  * @module lib/engine/NgxFormFieldDirective
6069
6276
  * @description Base directive for CRUD form fields in Decaf Angular applications.
@@ -6527,90 +6734,6 @@ function Dynamic() {
6527
6734
  // };
6528
6735
  // }
6529
6736
 
6530
- /**
6531
- * @module lib/directives/NgxSvgDirective
6532
- * @description Standalone directive that inlines SVG assets into the host element.
6533
- * @summary Provides {@link NgxSvgDirective}, a lightweight Angular directive that resolves
6534
- * an SVG file path from either its input binding or the host element's `src` attribute and
6535
- * delegates the HTTP fetch and DOM injection to {@link NgxMediaService}.
6536
- * @link {@link NgxSvgDirective}
6537
- */
6538
- /**
6539
- * @description Angular directive that fetches an SVG file and inlines it into the host element.
6540
- * @summary Standalone directive bound to the `[ngx-decaf-svg]` attribute selector. On
6541
- * initialisation it resolves the SVG asset path from the `[ngx-decaf-svg]` input binding or,
6542
- * as a fallback, the host element's native `src` attribute. Once a non-empty path is determined
6543
- * it calls {@link NgxMediaService.loadSvgObserver}, which performs the HTTP request via
6544
- * {@link HttpClient} and injects the SVG markup directly into the host element's DOM, enabling
6545
- * full CSS styling of the inlined SVG.
6546
- * @class NgxSvgDirective
6547
- * @implements {OnInit}
6548
- * @example
6549
- * ```html
6550
- * <!-- Via directive binding -->
6551
- * <div [ngx-decaf-svg]="'/assets/icons/logo.svg'"></div>
6552
- *
6553
- * <!-- Fallback to src attribute -->
6554
- * <img ngx-decaf-svg src="/assets/icons/arrow.svg" />
6555
- * ```
6556
- */
6557
- class NgxSvgDirective {
6558
- constructor() {
6559
- /**
6560
- * @description Service responsible for fetching and inlining the SVG markup.
6561
- * @summary Injected {@link NgxMediaService} instance used by `ngOnInit` to perform the
6562
- * HTTP request and inject the resulting SVG markup into the host element's DOM.
6563
- * @type {NgxMediaService}
6564
- * @memberOf module:lib/directives/NgxSvgDirective
6565
- */
6566
- this.mediaService = inject(NgxMediaService);
6567
- /**
6568
- * @description Reference to the host DOM element into which the SVG will be injected.
6569
- * @summary Obtained via Angular's `inject(ElementRef)`. Provides access to the native
6570
- * element forwarded to {@link NgxMediaService.loadSvgObserver} as the injection target,
6571
- * and used as a fallback source for the `src` attribute when `path` is not set.
6572
- * @type {ElementRef}
6573
- * @memberOf module:lib/directives/NgxSvgDirective
6574
- */
6575
- this.element = inject(ElementRef);
6576
- /**
6577
- * @description HTTP client instance forwarded to the media service for the SVG fetch.
6578
- * @summary Injected {@link HttpClient} passed directly to
6579
- * {@link NgxMediaService.loadSvgObserver} so the service can issue the GET request for
6580
- * the SVG file without managing its own HTTP dependency.
6581
- * @type {HttpClient}
6582
- * @memberOf module:lib/directives/NgxSvgDirective
6583
- */
6584
- this.http = inject(HttpClient);
6585
- }
6586
- /**
6587
- * @description Resolves the SVG path and triggers the inline load.
6588
- * @summary Trims `path` and, when empty, falls back to the host element's `src` attribute.
6589
- * When a valid path is found, delegates to {@link NgxMediaService.loadSvgObserver} to
6590
- * fetch the file and inject the SVG markup into the host element.
6591
- * @returns {void}
6592
- * @memberOf module:lib/directives/NgxSvgDirective
6593
- */
6594
- ngOnInit() {
6595
- this.path = this.path?.trim() || this.element?.nativeElement?.getAttribute('src')?.trim() || '';
6596
- if (this.path) {
6597
- this.mediaService.loadSvgObserver(this.http, this.path, this.element.nativeElement);
6598
- }
6599
- }
6600
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: NgxSvgDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
6601
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: NgxSvgDirective, isStandalone: true, selector: "[ngx-decaf-svg]", inputs: { path: ["ngx-decaf-svg", "path"] }, ngImport: i0 }); }
6602
- }
6603
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: NgxSvgDirective, decorators: [{
6604
- type: Directive,
6605
- args: [{
6606
- selector: '[ngx-decaf-svg]',
6607
- standalone: true,
6608
- }]
6609
- }], propDecorators: { path: [{
6610
- type: Input,
6611
- args: ['ngx-decaf-svg']
6612
- }] } });
6613
-
6614
6737
  let IconComponent = class IconComponent {
6615
6738
  constructor() {
6616
6739
  this.color = 'dark';
@@ -7522,6 +7645,12 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
7522
7645
  * @memberOf CrudFieldComponent
7523
7646
  */
7524
7647
  this.childOf = '';
7648
+ /**
7649
+ * @description Maximum character count before text content is truncated. `-1` disables truncation.
7650
+ * @type {number}
7651
+ * @default -1
7652
+ */
7653
+ this.maxContentLength = -1;
7525
7654
  /**
7526
7655
  * @description The initial value of the field.
7527
7656
  * @summary Sets the initial value of the form field. This can be a string, number, or Date
@@ -7676,6 +7805,7 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
7676
7805
  this.hidden = true;
7677
7806
  if ([OperationKeys.READ, OperationKeys.DELETE].includes(this.operation)) {
7678
7807
  this.formGroup = undefined;
7808
+ this.value = `${this.value ?? ''}`;
7679
7809
  }
7680
7810
  else {
7681
7811
  this.options = await this.getOptions();
@@ -7857,7 +7987,7 @@ let CrudFieldComponent = class CrudFieldComponent extends NgxFormFieldDirective
7857
7987
  return this.formControl.value.includes(value);
7858
7988
  }
7859
7989
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: CrudFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7860
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: CrudFieldComponent, isStandalone: true, selector: "ngx-decaf-crud-field", inputs: { operation: "operation", name: "name", className: "className", path: "path", childOf: "childOf", type: "type", subType: "subType", validationMessage: "validationMessage", value: "value", disabled: "disabled", label: "label", placeholder: "placeholder", format: "format", hidden: "hidden", max: "max", maxlength: "maxlength", min: "min", minlength: "minlength", pattern: "pattern", readonly: "readonly", required: "required", step: "step", equals: "equals", different: "different", lessThan: "lessThan", lessThanOrEqual: "lessThanOrEqual", greaterThan: "greaterThan", greaterThanOrEqual: "greaterThanOrEqual", alignment: "alignment", checked: "checked", justify: "justify", cancelText: "cancelText", interface: "interface", options: "options", mode: "mode", spellcheck: "spellcheck", startEmpty: "startEmpty", inputmode: "inputmode", autocomplete: "autocomplete", fill: "fill", labelPlacement: "labelPlacement", updateOn: "updateOn", formGroup: "formGroup", formControl: "formControl", multiple: "multiple", uid: "uid", page: "page" }, host: { properties: { "attr.id": "uid", "attr.class": "className" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "@if (\n operation === OperationKeys.READ ||\n operation === OperationKeys.DELETE ||\n readonly\n) {\n @if (!hidden) {\n <ng-container>\n <div>\n <ion-item\n [class.dcf-item-readonly]=\"\n readonly && operation !== OperationKeys.READ\n \"\n [class]=\"'dcf-input-item ' + operation\"\n #component\n >\n <ion-label [id]=\"name\">\n @if (refreshing) {\n <br />\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n } @else {\n {{ label | translate }}\n <br />\n @if (type !== 'checkbox' && value) {\n <ion-text\n [innerHTML]=\"type === 'password' ? '********' : value\"\n ></ion-text>\n } @else {\n @if (type === 'checkbox') {\n <ion-badge\n mode=\"md\"\n color=\"light\"\n >\n <ion-text [color]=\"!value ? 'danger' : 'primary'\">\n {{ value }}\n </ion-text>\n </ion-badge>\n } @else {\n <ion-text [innerHTML]=\"value\"></ion-text>\n }\n }\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n }\n} @else {\n @if (formControl) {\n <ng-container [formGroup]=\"multiple ? activeFormGroup : formControl.parent\">\n <div\n [id]=\"uid\"\n #container\n [class]=\"'dcf-input-item ' + (operation || 'create')\"\n [class.dcf-field-required]=\"required\"\n [class.dcf-field-readonly]=\"readonly\"\n >\n @if (type === HTML5InputTypes.TEXTAREA) {\n <ion-textarea\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [attr.readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component\n ></ion-textarea>\n } @else if (type === HTML5InputTypes.CHECKBOX) {\n @if (!options?.length) {\n <ion-item\n class=\"dcf-width-1-1\"\n [hidden]=\"hidden\"\n >\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify || 'start'\"\n [value]=\"value\"\n [checked]=\"checked\"\n [attr.readonly]=\"readonly\"\n [formControlName]=\"name\"\n #component\n >\n <span>{{ label | translate }}</span>\n </ion-checkbox>\n </ion-item>\n } @else {\n <div class=\"dcf-checkbox-group\">\n <label\n class=\"dcf-label\"\n [for]=\"path\"\n >\n {{ label | translate }}\n </label>\n @for (option of options; track trackItemFn($index, option.text)) {\n <ion-item\n class=\"dcf-width-1-1\"\n [button]=\"true\"\n >\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"path\"\n [mode]=\"'md'\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"option.value\"\n [attr.readonly]=\"readonly\"\n [checked]=\"isOptionChecked(option.value)\"\n (ionChange)=\"toggleOptionSelection(option.value, $event)\"\n #component\n >\n <span>\n {{ $index + 1 }}.\n {{\n translatable ? (option?.text | translate) : option?.text\n }}\n </span>\n </ion-checkbox>\n </ion-item>\n }\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n </div>\n }\n } @else if (type === HTML5InputTypes.RADIO && options?.length) {\n <ion-radio-group\n class=\"dcf-width-1-1\"\n [formControlName]=\"name\"\n [value]=\"value\"\n #component\n >\n <label\n class=\"dcf-radio-group-label\"\n [for]=\"path\"\n >\n {{ label | translate }}\n </label>\n @for (option of options; track $index) {\n <ion-item>\n <ion-radio\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"path\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [attr.readonly]=\"readonly\"\n [value]=\"option.value\"\n >\n {{ translatable ? (option?.text | translate) : option?.text }}\n </ion-radio>\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n </ion-item>\n }\n </ion-radio-group>\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n } @else if (type === HTML5InputTypes.SELECT) {\n <div>\n <ion-select\n (ionInput)=\"handleModalChildChanges($event)\"\n (ionChange)=\"handleModalChildChanges($event)\"\n (click)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [interface]=\"interface\"\n [mode]=\"'md'\"\n [hidden]=\"hidden || !options?.length\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"label | translate\"\n [value]=\"value ?? null\"\n (click)=\"openSelectOptions($event, interface)\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [interface]=\"interface\"\n #component\n >\n @if (options?.length) {\n @for (\n option of options;\n track trackItemFn($index, option.text)\n ) {\n <ion-select-option\n [value]=\"option.value\"\n [class.dcf-disabled]=\"option.disabled\"\n [class.dcf-hidden]=\"option.hidden\"\n [hidden]=\"option.hidden\"\n >\n {{ option.text }}\n </ion-select-option>\n }\n }\n @if (\n (value && !required) ||\n (!required && value !== undefined && value !== '')\n ) {\n <ion-button\n fill=\"clear\"\n (click)=\"handleClearValue($event)\"\n slot=\"end\"\n aria-label=\"Show/hide password\"\n >\n <ngx-decaf-icon\n size=\"small\"\n slot=\"icon-only\"\n [name]=\"'ti-input-x'\"\n />\n </ion-button>\n }\n </ion-select>\n <div\n class=\"dcf-error\"\n [class.dcf-options-error]=\"!options?.length\"\n [innerHTML]=\"\n options?.length\n ? getErrors(container)\n : ('errors.empty_options' | translate: { '0': name })\n \"\n ></div>\n </div>\n } @else {\n <ion-input\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [type]=\"type\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [attr.readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\"\n #component\n />\n\n <!-- <span class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></span> -->\n }\n </div>\n </ng-container>\n } @else {\n <div>\n <p class=\"dcf-error\">\n {{ 'errors.form.control' | translate: { '0': name } }}\n </p>\n </div>\n }\n}\n", styles: [".dcf-item-readonly .create ion-label,.dcf-item-readonly .update ion-label{font-weight:600;transform:translatey(-.8rem)}.dcf-item-readonly .create ion-label ion-text,.dcf-item-readonly .update ion-label ion-text{font-weight:initial;position:relative;top:.8rem}ion-badge{font-weight:600!important;margin-top:.25rem;font-weight:600}ion-badge ion-text{font-weight:600;text-transform:capitalize}ion-item{--border-color: transparent}ion-item:not(.dcf-input-item){--inner-padding-start: 0rem;--padding-start: 0rem;--background: transparent}ion-item.dcf-input-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--inner-padding-start: .75rem;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15;--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}ion-item.dcf-input-item.dcf-palette-dark{--border-color: var(--dcf-color-gray-6) !important}ion-item.dcf-input-item.read,ion-item.dcf-input-item.delete{--min-height: 30px;padding:unset;margin:unset!important;margin-bottom:var(--dcf-margin-xsmall)!important}ion-item.dcf-input-item.read ion-label,ion-item.dcf-input-item.delete ion-label{font-weight:600;margin-top:0!important;margin-bottom:.25rem!important;font-size:.925rem}ion-item.dcf-input-item.read ion-label:not(:first-of-type),ion-item.dcf-input-item.delete ion-label:not(:first-of-type){margin:100rem}ion-item.dcf-input-item.read span,ion-item.dcf-input-item.read ion-text,ion-item.dcf-input-item.delete span,ion-item.dcf-input-item.delete ion-text{font-weight:400!important;font-size:.825rem;min-height:.5rem!important}ion-item.dcf-input-item.read span:not(.dcf-display-block),ion-item.dcf-input-item.read ion-text:not(.dcf-display-block),ion-item.dcf-input-item.delete span:not(.dcf-display-block),ion-item.dcf-input-item.delete ion-text:not(.dcf-display-block){display:inline-block}ion-item.dcf-input-item.read span.dcf-display-block,ion-item.dcf-input-item.read ion-text.dcf-display-block,ion-item.dcf-input-item.delete span.dcf-display-block,ion-item.dcf-input-item.delete ion-text.dcf-display-block{display:block!important}ion-item.dcf-input-item>*,ion-item.dcf-input-item ion-select{width:100%!important}ion-item.dcf-input-item.create.checkbox+.checkbox,ion-item.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}ion-item.dcf-input-item.create ion-item,ion-item.dcf-input-item.update ion-item{--border-color: transparent}ion-item.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,ion-item.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox::part(container){border:2px solid var(--dcf-color-primary);margin-left:.5rem;margin-right:.5rem;border-radius:var(--dcf-border-radius-small);padding:3px}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-radio-group .dcf-radio-group-label{font-weight:600}ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-checkbox-group{width:100%}.dcf-checkbox-group .dcf-label{font-weight:600}.dcf-checkbox-group .dcf-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}.dcf-checkbox-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:500!important;line-height:1.1rem;z-index:9999}.dcf-error.dcf-options-error{position:relative;margin-bottom:.25rem!important;max-width:200px!important}.dcf-error .ti,.dcf-error ngx-decaf-icon,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin!important;margin-bottom:.5rem!important}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonBadge, selector: "ion-badge", inputs: ["color", "mode"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IconComponent, selector: "ngx-decaf-icon", inputs: ["name", "color", "slot", "button", "buttonFill", "buttonShape", "width", "size", "inline"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
7990
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.18", type: CrudFieldComponent, isStandalone: true, selector: "ngx-decaf-crud-field", inputs: { operation: "operation", name: "name", className: "className", path: "path", childOf: "childOf", type: "type", subType: "subType", validationMessage: "validationMessage", maxContentLength: "maxContentLength", value: "value", disabled: "disabled", label: "label", placeholder: "placeholder", format: "format", hidden: "hidden", max: "max", maxlength: "maxlength", min: "min", minlength: "minlength", pattern: "pattern", readonly: "readonly", required: "required", step: "step", equals: "equals", different: "different", lessThan: "lessThan", lessThanOrEqual: "lessThanOrEqual", greaterThan: "greaterThan", greaterThanOrEqual: "greaterThanOrEqual", alignment: "alignment", checked: "checked", justify: "justify", cancelText: "cancelText", interface: "interface", options: "options", mode: "mode", spellcheck: "spellcheck", startEmpty: "startEmpty", inputmode: "inputmode", autocomplete: "autocomplete", fill: "fill", labelPlacement: "labelPlacement", updateOn: "updateOn", formGroup: "formGroup", formControl: "formControl", multiple: "multiple", uid: "uid", page: "page" }, host: { properties: { "attr.id": "uid", "attr.class": "className" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef }], usesInheritance: true, ngImport: i0, template: "@if (\n operation === OperationKeys.READ ||\n operation === OperationKeys.DELETE ||\n readonly\n) {\n @if (!hidden) {\n <ng-container>\n <div>\n <ion-item\n [class.dcf-item-readonly]=\"\n readonly && operation !== OperationKeys.READ\n \"\n [class]=\"'dcf-input-item ' + operation\"\n #component\n >\n <ion-label [id]=\"name\">\n @if (refreshing) {\n <br />\n <ion-skeleton-text [animated]=\"true\" />\n } @else {\n {{ label | translate }}\n <br />\n @if (type !== 'checkbox') {\n <ion-text\n [class.dcf-empty]=\"!value?.length\"\n [ngx-decaf-tooltip]=\"\n maxContentLength > 0 && value?.length\n ? {\n text: value,\n truncate: true,\n limit: maxContentLength,\n position: 'over',\n }\n : {}\n \"\n [innerHTML]=\"\n type === 'password'\n ? '********'\n : value?.length\n ? value\n : '-'\n \"\n />\n } @else {\n <ion-badge\n mode=\"md\"\n color=\"light\"\n >\n <ion-text\n [color]=\"!value ? 'danger' : 'primary'\"\n [innerHTML]=\"value\"\n />\n </ion-badge>\n }\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n }\n} @else {\n @if (formControl) {\n <ng-container [formGroup]=\"multiple ? activeFormGroup : formControl.parent\">\n <div\n [id]=\"uid\"\n #container\n [class]=\"'dcf-input-item ' + (operation || 'create')\"\n [class.dcf-field-required]=\"required\"\n [class.dcf-field-readonly]=\"readonly\"\n >\n @if (type === HTML5InputTypes.TEXTAREA) {\n <ion-textarea\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [attr.readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component\n ></ion-textarea>\n } @else if (type === HTML5InputTypes.CHECKBOX) {\n @if (!options?.length) {\n <ion-item\n class=\"dcf-width-1-1\"\n [hidden]=\"hidden\"\n >\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify || 'start'\"\n [value]=\"value\"\n [checked]=\"checked\"\n [attr.readonly]=\"readonly\"\n [formControlName]=\"name\"\n #component\n >\n <span>{{ label | translate }}</span>\n </ion-checkbox>\n </ion-item>\n } @else {\n <div class=\"dcf-checkbox-group\">\n <label\n class=\"dcf-label\"\n [for]=\"path\"\n >\n {{ label | translate }}\n </label>\n @for (option of options; track trackItemFn($index, option.text)) {\n <ion-item\n class=\"dcf-width-1-1\"\n [button]=\"true\"\n >\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"path\"\n [mode]=\"'md'\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"option.value\"\n [attr.readonly]=\"readonly\"\n [checked]=\"isOptionChecked(option.value)\"\n (ionChange)=\"toggleOptionSelection(option.value, $event)\"\n #component\n >\n <span>\n {{ $index + 1 }}.\n {{\n translatable ? (option?.text | translate) : option?.text\n }}\n </span>\n </ion-checkbox>\n </ion-item>\n }\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n </div>\n }\n } @else if (type === HTML5InputTypes.RADIO && options?.length) {\n <ion-radio-group\n class=\"dcf-width-1-1\"\n [formControlName]=\"name\"\n [value]=\"value\"\n #component\n >\n <label\n class=\"dcf-radio-group-label\"\n [for]=\"path\"\n >\n {{ label | translate }}\n </label>\n @for (option of options; track $index) {\n <ion-item>\n <ion-radio\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"path\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [attr.readonly]=\"readonly\"\n [value]=\"option.value\"\n >\n {{ translatable ? (option?.text | translate) : option?.text }}\n </ion-radio>\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n </ion-item>\n }\n </ion-radio-group>\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n } @else if (type === HTML5InputTypes.SELECT) {\n <div>\n <ion-select\n (ionInput)=\"handleModalChildChanges($event)\"\n (ionChange)=\"handleModalChildChanges($event)\"\n (click)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [interface]=\"interface\"\n [mode]=\"'md'\"\n [hidden]=\"hidden || !options?.length\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"label | translate\"\n [value]=\"value ?? null\"\n (click)=\"openSelectOptions($event, interface)\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [interface]=\"interface\"\n #component\n >\n @if (options?.length) {\n @for (\n option of options;\n track trackItemFn($index, option.text)\n ) {\n <ion-select-option\n [value]=\"option.value\"\n [class.dcf-disabled]=\"option.disabled\"\n [class.dcf-hidden]=\"option.hidden\"\n [hidden]=\"option.hidden\"\n >\n {{ option.text }}\n </ion-select-option>\n }\n }\n @if (\n (value && !required) ||\n (!required && value !== undefined && value !== '')\n ) {\n <ion-button\n fill=\"clear\"\n (click)=\"handleClearValue($event)\"\n slot=\"end\"\n aria-label=\"Show/hide password\"\n >\n <ngx-decaf-icon\n size=\"small\"\n slot=\"icon-only\"\n [name]=\"'ti-input-x'\"\n />\n </ion-button>\n }\n </ion-select>\n <div\n class=\"dcf-error\"\n [class.dcf-options-error]=\"!options?.length\"\n [innerHTML]=\"\n options?.length\n ? getErrors(container)\n : ('errors.empty_options' | translate: { '0': name })\n \"\n ></div>\n </div>\n } @else {\n <ion-input\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [type]=\"type\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [attr.readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\"\n #component\n />\n\n <!-- <span class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></span> -->\n }\n </div>\n </ng-container>\n } @else {\n <div>\n <p class=\"dcf-error\">\n {{ 'errors.form.control' | translate: { '0': name } }}\n </p>\n </div>\n }\n}\n", styles: [".dcf-item-readonly .create ion-label,.dcf-item-readonly .update ion-label{font-weight:600;transform:translatey(-.8rem)}.dcf-item-readonly .create ion-label ion-text,.dcf-item-readonly .update ion-label ion-text{font-weight:initial;position:relative;top:.8rem}ion-badge{font-weight:600!important;margin-top:.25rem;font-weight:600}ion-badge ion-text{font-weight:600;text-transform:capitalize}ion-item{--border-color: transparent}ion-item:not(.dcf-input-item){--inner-padding-start: 0rem;--padding-start: 0rem;--background: transparent}ion-item.dcf-input-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--inner-padding-start: .75rem;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15;--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}ion-item.dcf-input-item.dcf-palette-dark{--border-color: var(--dcf-color-gray-6) !important}ion-item.dcf-input-item .dcf-empty{padding-left:.05rem}ion-item.dcf-input-item ::ng-deep a{cursor:pointer}ion-item.dcf-input-item.read,ion-item.dcf-input-item.delete{--min-height: 30px;padding:unset;margin:unset!important;margin-bottom:var(--dcf-margin-xsmall)!important}ion-item.dcf-input-item.read ion-label,ion-item.dcf-input-item.delete ion-label{font-weight:600;margin-top:0!important;margin-bottom:.25rem!important;font-size:.925rem}ion-item.dcf-input-item.read ion-label:not(:first-of-type),ion-item.dcf-input-item.delete ion-label:not(:first-of-type){margin:100rem}ion-item.dcf-input-item.read span,ion-item.dcf-input-item.read ion-text,ion-item.dcf-input-item.delete span,ion-item.dcf-input-item.delete ion-text{font-weight:400!important;font-size:.825rem;min-height:.5rem!important}ion-item.dcf-input-item.read span:not(.dcf-display-block),ion-item.dcf-input-item.read ion-text:not(.dcf-display-block),ion-item.dcf-input-item.delete span:not(.dcf-display-block),ion-item.dcf-input-item.delete ion-text:not(.dcf-display-block){display:inline-block}ion-item.dcf-input-item.read span.dcf-display-block,ion-item.dcf-input-item.read ion-text.dcf-display-block,ion-item.dcf-input-item.delete span.dcf-display-block,ion-item.dcf-input-item.delete ion-text.dcf-display-block{display:block!important}ion-item.dcf-input-item>*,ion-item.dcf-input-item ion-select{width:100%!important}ion-item.dcf-input-item.create.checkbox+.checkbox,ion-item.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}ion-item.dcf-input-item.create ion-item,ion-item.dcf-input-item.update ion-item{--border-color: transparent}ion-item.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,ion-item.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox::part(container){border:2px solid var(--dcf-color-primary);margin-left:.5rem;margin-right:.5rem;border-radius:var(--dcf-border-radius-small);padding:3px}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-radio-group .dcf-radio-group-label{font-weight:600}ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-checkbox-group{width:100%}.dcf-checkbox-group .dcf-label{font-weight:600}.dcf-checkbox-group .dcf-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}.dcf-checkbox-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:500!important;line-height:1.1rem;z-index:9999}.dcf-error.dcf-options-error{position:relative;margin-bottom:.25rem!important;max-width:200px!important}.dcf-error .ti,.dcf-error ngx-decaf-icon,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin!important;margin-bottom:.5rem!important}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinLengthValidator, selector: "[minlength][formControlName],[minlength][formControl],[minlength][ngModel]", inputs: ["minlength"] }, { kind: "directive", type: i1.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: IonInput, selector: "ion-input", inputs: ["accept", "autocapitalize", "autocomplete", "autocorrect", "autofocus", "clearInput", "clearOnEdit", "color", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "max", "maxlength", "min", "minlength", "mode", "multiple", "name", "pattern", "placeholder", "readonly", "required", "shape", "size", "spellcheck", "step", "type", "value"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonCheckbox, selector: "ion-checkbox", inputs: ["checked", "color", "disabled", "errorText", "helperText", "indeterminate", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonRadioGroup, selector: "ion-radio-group", inputs: ["allowEmptySelection", "compareWith", "errorText", "helperText", "name", "value"] }, { kind: "component", type: IonRadio, selector: "ion-radio", inputs: ["alignment", "color", "disabled", "justify", "labelPlacement", "mode", "name", "value"] }, { kind: "component", type: IonSelect, selector: "ion-select", inputs: ["cancelText", "color", "compareWith", "disabled", "errorText", "expandedIcon", "fill", "helperText", "interface", "interfaceOptions", "justify", "label", "labelPlacement", "mode", "multiple", "name", "okText", "placeholder", "selectedText", "shape", "toggleIcon", "value"] }, { kind: "component", type: IonSelectOption, selector: "ion-select-option", inputs: ["disabled", "value"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonBadge, selector: "ion-badge", inputs: ["color", "mode"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonTextarea, selector: "ion-textarea", inputs: ["autoGrow", "autocapitalize", "autofocus", "clearOnEdit", "color", "cols", "counter", "counterFormatter", "debounce", "disabled", "enterkeyhint", "errorText", "fill", "helperText", "inputmode", "label", "labelPlacement", "maxlength", "minlength", "mode", "name", "placeholder", "readonly", "required", "rows", "shape", "spellcheck", "value", "wrap"] }, { kind: "component", type: IconComponent, selector: "ngx-decaf-icon", inputs: ["name", "color", "slot", "button", "buttonFill", "buttonShape", "width", "size", "inline"] }, { kind: "directive", type: DecafTooltipDirective, selector: "[ngx-decaf-tooltip]", inputs: ["ngx-decaf-tooltip"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
7861
7991
  };
7862
7992
  CrudFieldComponent = __decorate([
7863
7993
  Dynamic(),
@@ -7880,7 +8010,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
7880
8010
  IonText,
7881
8011
  IonTextarea,
7882
8012
  IconComponent,
7883
- ], selector: 'ngx-decaf-crud-field', host: { '[attr.id]': 'uid', '[attr.class]': 'className' }, template: "@if (\n operation === OperationKeys.READ ||\n operation === OperationKeys.DELETE ||\n readonly\n) {\n @if (!hidden) {\n <ng-container>\n <div>\n <ion-item\n [class.dcf-item-readonly]=\"\n readonly && operation !== OperationKeys.READ\n \"\n [class]=\"'dcf-input-item ' + operation\"\n #component\n >\n <ion-label [id]=\"name\">\n @if (refreshing) {\n <br />\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n } @else {\n {{ label | translate }}\n <br />\n @if (type !== 'checkbox' && value) {\n <ion-text\n [innerHTML]=\"type === 'password' ? '********' : value\"\n ></ion-text>\n } @else {\n @if (type === 'checkbox') {\n <ion-badge\n mode=\"md\"\n color=\"light\"\n >\n <ion-text [color]=\"!value ? 'danger' : 'primary'\">\n {{ value }}\n </ion-text>\n </ion-badge>\n } @else {\n <ion-text [innerHTML]=\"value\"></ion-text>\n }\n }\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n }\n} @else {\n @if (formControl) {\n <ng-container [formGroup]=\"multiple ? activeFormGroup : formControl.parent\">\n <div\n [id]=\"uid\"\n #container\n [class]=\"'dcf-input-item ' + (operation || 'create')\"\n [class.dcf-field-required]=\"required\"\n [class.dcf-field-readonly]=\"readonly\"\n >\n @if (type === HTML5InputTypes.TEXTAREA) {\n <ion-textarea\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [attr.readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component\n ></ion-textarea>\n } @else if (type === HTML5InputTypes.CHECKBOX) {\n @if (!options?.length) {\n <ion-item\n class=\"dcf-width-1-1\"\n [hidden]=\"hidden\"\n >\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify || 'start'\"\n [value]=\"value\"\n [checked]=\"checked\"\n [attr.readonly]=\"readonly\"\n [formControlName]=\"name\"\n #component\n >\n <span>{{ label | translate }}</span>\n </ion-checkbox>\n </ion-item>\n } @else {\n <div class=\"dcf-checkbox-group\">\n <label\n class=\"dcf-label\"\n [for]=\"path\"\n >\n {{ label | translate }}\n </label>\n @for (option of options; track trackItemFn($index, option.text)) {\n <ion-item\n class=\"dcf-width-1-1\"\n [button]=\"true\"\n >\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"path\"\n [mode]=\"'md'\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"option.value\"\n [attr.readonly]=\"readonly\"\n [checked]=\"isOptionChecked(option.value)\"\n (ionChange)=\"toggleOptionSelection(option.value, $event)\"\n #component\n >\n <span>\n {{ $index + 1 }}.\n {{\n translatable ? (option?.text | translate) : option?.text\n }}\n </span>\n </ion-checkbox>\n </ion-item>\n }\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n </div>\n }\n } @else if (type === HTML5InputTypes.RADIO && options?.length) {\n <ion-radio-group\n class=\"dcf-width-1-1\"\n [formControlName]=\"name\"\n [value]=\"value\"\n #component\n >\n <label\n class=\"dcf-radio-group-label\"\n [for]=\"path\"\n >\n {{ label | translate }}\n </label>\n @for (option of options; track $index) {\n <ion-item>\n <ion-radio\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"path\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [attr.readonly]=\"readonly\"\n [value]=\"option.value\"\n >\n {{ translatable ? (option?.text | translate) : option?.text }}\n </ion-radio>\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n </ion-item>\n }\n </ion-radio-group>\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n } @else if (type === HTML5InputTypes.SELECT) {\n <div>\n <ion-select\n (ionInput)=\"handleModalChildChanges($event)\"\n (ionChange)=\"handleModalChildChanges($event)\"\n (click)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [interface]=\"interface\"\n [mode]=\"'md'\"\n [hidden]=\"hidden || !options?.length\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"label | translate\"\n [value]=\"value ?? null\"\n (click)=\"openSelectOptions($event, interface)\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [interface]=\"interface\"\n #component\n >\n @if (options?.length) {\n @for (\n option of options;\n track trackItemFn($index, option.text)\n ) {\n <ion-select-option\n [value]=\"option.value\"\n [class.dcf-disabled]=\"option.disabled\"\n [class.dcf-hidden]=\"option.hidden\"\n [hidden]=\"option.hidden\"\n >\n {{ option.text }}\n </ion-select-option>\n }\n }\n @if (\n (value && !required) ||\n (!required && value !== undefined && value !== '')\n ) {\n <ion-button\n fill=\"clear\"\n (click)=\"handleClearValue($event)\"\n slot=\"end\"\n aria-label=\"Show/hide password\"\n >\n <ngx-decaf-icon\n size=\"small\"\n slot=\"icon-only\"\n [name]=\"'ti-input-x'\"\n />\n </ion-button>\n }\n </ion-select>\n <div\n class=\"dcf-error\"\n [class.dcf-options-error]=\"!options?.length\"\n [innerHTML]=\"\n options?.length\n ? getErrors(container)\n : ('errors.empty_options' | translate: { '0': name })\n \"\n ></div>\n </div>\n } @else {\n <ion-input\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [type]=\"type\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [attr.readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\"\n #component\n />\n\n <!-- <span class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></span> -->\n }\n </div>\n </ng-container>\n } @else {\n <div>\n <p class=\"dcf-error\">\n {{ 'errors.form.control' | translate: { '0': name } }}\n </p>\n </div>\n }\n}\n", styles: [".dcf-item-readonly .create ion-label,.dcf-item-readonly .update ion-label{font-weight:600;transform:translatey(-.8rem)}.dcf-item-readonly .create ion-label ion-text,.dcf-item-readonly .update ion-label ion-text{font-weight:initial;position:relative;top:.8rem}ion-badge{font-weight:600!important;margin-top:.25rem;font-weight:600}ion-badge ion-text{font-weight:600;text-transform:capitalize}ion-item{--border-color: transparent}ion-item:not(.dcf-input-item){--inner-padding-start: 0rem;--padding-start: 0rem;--background: transparent}ion-item.dcf-input-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--inner-padding-start: .75rem;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15;--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}ion-item.dcf-input-item.dcf-palette-dark{--border-color: var(--dcf-color-gray-6) !important}ion-item.dcf-input-item.read,ion-item.dcf-input-item.delete{--min-height: 30px;padding:unset;margin:unset!important;margin-bottom:var(--dcf-margin-xsmall)!important}ion-item.dcf-input-item.read ion-label,ion-item.dcf-input-item.delete ion-label{font-weight:600;margin-top:0!important;margin-bottom:.25rem!important;font-size:.925rem}ion-item.dcf-input-item.read ion-label:not(:first-of-type),ion-item.dcf-input-item.delete ion-label:not(:first-of-type){margin:100rem}ion-item.dcf-input-item.read span,ion-item.dcf-input-item.read ion-text,ion-item.dcf-input-item.delete span,ion-item.dcf-input-item.delete ion-text{font-weight:400!important;font-size:.825rem;min-height:.5rem!important}ion-item.dcf-input-item.read span:not(.dcf-display-block),ion-item.dcf-input-item.read ion-text:not(.dcf-display-block),ion-item.dcf-input-item.delete span:not(.dcf-display-block),ion-item.dcf-input-item.delete ion-text:not(.dcf-display-block){display:inline-block}ion-item.dcf-input-item.read span.dcf-display-block,ion-item.dcf-input-item.read ion-text.dcf-display-block,ion-item.dcf-input-item.delete span.dcf-display-block,ion-item.dcf-input-item.delete ion-text.dcf-display-block{display:block!important}ion-item.dcf-input-item>*,ion-item.dcf-input-item ion-select{width:100%!important}ion-item.dcf-input-item.create.checkbox+.checkbox,ion-item.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}ion-item.dcf-input-item.create ion-item,ion-item.dcf-input-item.update ion-item{--border-color: transparent}ion-item.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,ion-item.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox::part(container){border:2px solid var(--dcf-color-primary);margin-left:.5rem;margin-right:.5rem;border-radius:var(--dcf-border-radius-small);padding:3px}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-radio-group .dcf-radio-group-label{font-weight:600}ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-checkbox-group{width:100%}.dcf-checkbox-group .dcf-label{font-weight:600}.dcf-checkbox-group .dcf-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}.dcf-checkbox-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:500!important;line-height:1.1rem;z-index:9999}.dcf-error.dcf-options-error{position:relative;margin-bottom:.25rem!important;max-width:200px!important}.dcf-error .ti,.dcf-error ngx-decaf-icon,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin!important;margin-bottom:.5rem!important}\n"] }]
8013
+ DecafTooltipDirective,
8014
+ ], selector: 'ngx-decaf-crud-field', host: { '[attr.id]': 'uid', '[attr.class]': 'className' }, template: "@if (\n operation === OperationKeys.READ ||\n operation === OperationKeys.DELETE ||\n readonly\n) {\n @if (!hidden) {\n <ng-container>\n <div>\n <ion-item\n [class.dcf-item-readonly]=\"\n readonly && operation !== OperationKeys.READ\n \"\n [class]=\"'dcf-input-item ' + operation\"\n #component\n >\n <ion-label [id]=\"name\">\n @if (refreshing) {\n <br />\n <ion-skeleton-text [animated]=\"true\" />\n } @else {\n {{ label | translate }}\n <br />\n @if (type !== 'checkbox') {\n <ion-text\n [class.dcf-empty]=\"!value?.length\"\n [ngx-decaf-tooltip]=\"\n maxContentLength > 0 && value?.length\n ? {\n text: value,\n truncate: true,\n limit: maxContentLength,\n position: 'over',\n }\n : {}\n \"\n [innerHTML]=\"\n type === 'password'\n ? '********'\n : value?.length\n ? value\n : '-'\n \"\n />\n } @else {\n <ion-badge\n mode=\"md\"\n color=\"light\"\n >\n <ion-text\n [color]=\"!value ? 'danger' : 'primary'\"\n [innerHTML]=\"value\"\n />\n </ion-badge>\n }\n }\n </ion-label>\n </ion-item>\n </div>\n </ng-container>\n }\n} @else {\n @if (formControl) {\n <ng-container [formGroup]=\"multiple ? activeFormGroup : formControl.parent\">\n <div\n [id]=\"uid\"\n #container\n [class]=\"'dcf-input-item ' + (operation || 'create')\"\n [class.dcf-field-required]=\"required\"\n [class.dcf-field-readonly]=\"readonly\"\n >\n @if (type === HTML5InputTypes.TEXTAREA) {\n <ion-textarea\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [autoGrow]=\"true\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [attr.readonly]=\"readonly !== undefined ? readonly : null\"\n [inputmode]=\"inputmode\"\n [spellcheck]=\"spellcheck\"\n [rows]=\"rows\"\n [labelPlacement]=\"labelPlacement\"\n [value]=\"value\"\n [fill]=\"fill\"\n [errorText]=\"getErrors(container)\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [label]=\"label | translate\"\n #component\n ></ion-textarea>\n } @else if (type === HTML5InputTypes.CHECKBOX) {\n @if (!options?.length) {\n <ion-item\n class=\"dcf-width-1-1\"\n [hidden]=\"hidden\"\n >\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [mode]=\"'md'\"\n [errorText]=\"getErrors(container)\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify || 'start'\"\n [value]=\"value\"\n [checked]=\"checked\"\n [attr.readonly]=\"readonly\"\n [formControlName]=\"name\"\n #component\n >\n <span>{{ label | translate }}</span>\n </ion-checkbox>\n </ion-item>\n } @else {\n <div class=\"dcf-checkbox-group\">\n <label\n class=\"dcf-label\"\n [for]=\"path\"\n >\n {{ label | translate }}\n </label>\n @for (option of options; track trackItemFn($index, option.text)) {\n <ion-item\n class=\"dcf-width-1-1\"\n [button]=\"true\"\n >\n <ion-checkbox\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"path\"\n [mode]=\"'md'\"\n [labelPlacement]=\"labelPlacement\"\n [justify]=\"justify\"\n [value]=\"option.value\"\n [attr.readonly]=\"readonly\"\n [checked]=\"isOptionChecked(option.value)\"\n (ionChange)=\"toggleOptionSelection(option.value, $event)\"\n #component\n >\n <span>\n {{ $index + 1 }}.\n {{\n translatable ? (option?.text | translate) : option?.text\n }}\n </span>\n </ion-checkbox>\n </ion-item>\n }\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n </div>\n }\n } @else if (type === HTML5InputTypes.RADIO && options?.length) {\n <ion-radio-group\n class=\"dcf-width-1-1\"\n [formControlName]=\"name\"\n [value]=\"value\"\n #component\n >\n <label\n class=\"dcf-radio-group-label\"\n [for]=\"path\"\n >\n {{ label | translate }}\n </label>\n @for (option of options; track $index) {\n <ion-item>\n <ion-radio\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"path\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [labelPlacement]=\"labelPlacement\"\n [alignment]=\"alignment\"\n [justify]=\"justify\"\n [attr.readonly]=\"readonly\"\n [value]=\"option.value\"\n >\n {{ translatable ? (option?.text | translate) : option?.text }}\n </ion-radio>\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n </ion-item>\n }\n </ion-radio-group>\n <span\n class=\"dcf-error\"\n [innerHTML]=\"getErrors(container)\"\n ></span>\n } @else if (type === HTML5InputTypes.SELECT) {\n <div>\n <ion-select\n (ionInput)=\"handleModalChildChanges($event)\"\n (ionChange)=\"handleModalChildChanges($event)\"\n (click)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n [interface]=\"interface\"\n [mode]=\"'md'\"\n [hidden]=\"hidden || !options?.length\"\n [labelPlacement]=\"labelPlacement\"\n [label]=\"label | translate\"\n [value]=\"value ?? null\"\n (click)=\"openSelectOptions($event, interface)\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [interface]=\"interface\"\n #component\n >\n @if (options?.length) {\n @for (\n option of options;\n track trackItemFn($index, option.text)\n ) {\n <ion-select-option\n [value]=\"option.value\"\n [class.dcf-disabled]=\"option.disabled\"\n [class.dcf-hidden]=\"option.hidden\"\n [hidden]=\"option.hidden\"\n >\n {{ option.text }}\n </ion-select-option>\n }\n }\n @if (\n (value && !required) ||\n (!required && value !== undefined && value !== '')\n ) {\n <ion-button\n fill=\"clear\"\n (click)=\"handleClearValue($event)\"\n slot=\"end\"\n aria-label=\"Show/hide password\"\n >\n <ngx-decaf-icon\n size=\"small\"\n slot=\"icon-only\"\n [name]=\"'ti-input-x'\"\n />\n </ion-button>\n }\n </ion-select>\n <div\n class=\"dcf-error\"\n [class.dcf-options-error]=\"!options?.length\"\n [innerHTML]=\"\n options?.length\n ? getErrors(container)\n : ('errors.empty_options' | translate: { '0': name })\n \"\n ></div>\n </div>\n } @else {\n <ion-input\n (ionInput)=\"handleModalChildChanges($event, formControl)\"\n (ionChange)=\"handleModalChildChanges($event, formControl)\"\n [id]=\"name\"\n [type]=\"type\"\n [mode]=\"'md'\"\n [hidden]=\"hidden\"\n [inputmode]=\"inputmode\"\n [labelPlacement]=\"labelPlacement\"\n [minlength]=\"minlength !== undefined ? minlength : null\"\n [maxlength]=\"maxlength !== undefined ? maxlength : null\"\n [attr.readonly]=\"readonly !== undefined ? readonly : null\"\n [max]=\"max !== undefined ? max : null\"\n [min]=\"min !== undefined ? min : null\"\n [step]=\"step !== undefined ? step : null\"\n [fill]=\"fill\"\n [placeholder]=\"placeholder | translate\"\n [formControlName]=\"name\"\n [errorText]=\"getErrors(container)\"\n [label]=\"label | translate\"\n #component\n />\n\n <!-- <span class=\"dcf-error\" [innerHTML]=\"getErrors(container)\"></span> -->\n }\n </div>\n </ng-container>\n } @else {\n <div>\n <p class=\"dcf-error\">\n {{ 'errors.form.control' | translate: { '0': name } }}\n </p>\n </div>\n }\n}\n", styles: [".dcf-item-readonly .create ion-label,.dcf-item-readonly .update ion-label{font-weight:600;transform:translatey(-.8rem)}.dcf-item-readonly .create ion-label ion-text,.dcf-item-readonly .update ion-label ion-text{font-weight:initial;position:relative;top:.8rem}ion-badge{font-weight:600!important;margin-top:.25rem;font-weight:600}ion-badge ion-text{font-weight:600;text-transform:capitalize}ion-item{--border-color: transparent}ion-item:not(.dcf-input-item){--inner-padding-start: 0rem;--padding-start: 0rem;--background: transparent}ion-item.dcf-input-item{--padding-end: 0rem;--padding-start: 0px !important;--padding-top: 0px !important;--inner-padding-start: .75rem;--background: transparent;--background-hover-opacity: .1;--background-activated-opacity: .15;--background-focused-opacity: .15;--background-hover: var(--dcf-color-primary);--background-focused: var(--dcf-color-primary);--border-color: var(--dcf-color-gray-2)}ion-item.dcf-input-item.dcf-palette-dark{--border-color: var(--dcf-color-gray-6) !important}ion-item.dcf-input-item .dcf-empty{padding-left:.05rem}ion-item.dcf-input-item ::ng-deep a{cursor:pointer}ion-item.dcf-input-item.read,ion-item.dcf-input-item.delete{--min-height: 30px;padding:unset;margin:unset!important;margin-bottom:var(--dcf-margin-xsmall)!important}ion-item.dcf-input-item.read ion-label,ion-item.dcf-input-item.delete ion-label{font-weight:600;margin-top:0!important;margin-bottom:.25rem!important;font-size:.925rem}ion-item.dcf-input-item.read ion-label:not(:first-of-type),ion-item.dcf-input-item.delete ion-label:not(:first-of-type){margin:100rem}ion-item.dcf-input-item.read span,ion-item.dcf-input-item.read ion-text,ion-item.dcf-input-item.delete span,ion-item.dcf-input-item.delete ion-text{font-weight:400!important;font-size:.825rem;min-height:.5rem!important}ion-item.dcf-input-item.read span:not(.dcf-display-block),ion-item.dcf-input-item.read ion-text:not(.dcf-display-block),ion-item.dcf-input-item.delete span:not(.dcf-display-block),ion-item.dcf-input-item.delete ion-text:not(.dcf-display-block){display:inline-block}ion-item.dcf-input-item.read span.dcf-display-block,ion-item.dcf-input-item.read ion-text.dcf-display-block,ion-item.dcf-input-item.delete span.dcf-display-block,ion-item.dcf-input-item.delete ion-text.dcf-display-block{display:block!important}ion-item.dcf-input-item>*,ion-item.dcf-input-item ion-select{width:100%!important}ion-item.dcf-input-item.create.checkbox+.checkbox,ion-item.dcf-input-item.update.checkbox+.checkbox{margin-top:-.25rem!important}ion-item.dcf-input-item.create ion-item,ion-item.dcf-input-item.update ion-item{--border-color: transparent}ion-item.dcf-input-item.create ion-item.dcf-text-wrap ion-label>*,ion-item.dcf-input-item.update ion-item.dcf-text-wrap ion-label>*{white-space:wrap!important;word-break:break-all!important}ion-textarea textarea{scrollbar-width:thin!important;margin-bottom:.5rem!important}ion-select.dcf-select-label-placement-floating::part(label){line-height:1.2rem!important}.dcf-proccessing,.dcf-proccessing *{pointer-events:none;touch-action:none;cursor:text}ion-checkbox::part(container){border:2px solid var(--dcf-color-primary);margin-left:.5rem;margin-right:.5rem;border-radius:var(--dcf-border-radius-small);padding:3px}ion-checkbox{--size: 1.5rem;--checkbox-background-checked: var(--dcf-color-primary);--checkmark-width: 2px}ion-radio-group .dcf-radio-group-label{font-weight:600}ion-radio-group .dcf-radio-group-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}ion-radio-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-checkbox-group{width:100%}.dcf-checkbox-group .dcf-label{font-weight:600}.dcf-checkbox-group .dcf-label~ion-item{margin-top:.5rem;--inner-padding-start: .75rem}.dcf-checkbox-group+.dcf-helper{padding-left:.75rem;position:relative}.dcf-error{position:absolute;color:var(--dcf-color-danger)!important;font-size:.8rem!important;font-weight:500!important;line-height:1.1rem;z-index:9999}.dcf-error.dcf-options-error{position:relative;margin-bottom:.25rem!important;max-width:200px!important}.dcf-error .ti,.dcf-error ngx-decaf-icon,.dcf-error ion-icon{position:relative;top:2px!important;min-width:20px;font-size:1rem!important;text-align:left}.dcf-helper{font-size:.875rem!important;font-weight:500;margin-top:.25rem;margin-bottom:-.75rem}.dcf-helper.dcf-has-action{cursor:pointer;text-decoration:underline}.dcf-error+.dcf-helper{padding-top:1rem}::ng-deep ion-textarea{min-height:80px!important;scrollbar-color:#888 #f0f0f0;scrollbar-width:thin!important;margin-bottom:.5rem!important}\n"] }]
7884
8015
  }], ctorParameters: () => [], propDecorators: { operation: [{
7885
8016
  type: Input,
7886
8017
  args: [{ required: true }]
@@ -7901,6 +8032,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
7901
8032
  type: Input
7902
8033
  }], validationMessage: [{
7903
8034
  type: Input
8035
+ }], maxContentLength: [{
8036
+ type: Input
7904
8037
  }], value: [{
7905
8038
  type: Input
7906
8039
  }], disabled: [{
@@ -14236,127 +14369,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImpo
14236
14369
  type: Input
14237
14370
  }] } });
14238
14371
 
14239
- class DecafTruncatePipe {
14240
- transform(value, limit = 30, trail = '...') {
14241
- if (!value) {
14242
- return '';
14243
- }
14244
- const sanitized = this.sanitize(value);
14245
- return sanitized.length > limit ? `${sanitized.substring(0, limit)}${trail}` : sanitized;
14246
- }
14247
- sanitize(value) {
14248
- return value.replace(/<[^>]+>/g, '').trim();
14249
- }
14250
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DecafTruncatePipe, deps: [], target: i0.ɵɵFactoryTarget.Pipe }); }
14251
- static { this.ɵpipe = i0.ɵɵngDeclarePipe({ minVersion: "14.0.0", version: "20.3.18", ngImport: i0, type: DecafTruncatePipe, isStandalone: true, name: "truncate" }); }
14252
- }
14253
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DecafTruncatePipe, decorators: [{
14254
- type: Pipe,
14255
- args: [{
14256
- name: 'truncate',
14257
- // pure: true,
14258
- standalone: true,
14259
- }]
14260
- }] });
14261
-
14262
- /**
14263
- * @module DecafTooltipDirective
14264
- * @description Provides a tooltip directive for the decaf-ts for-angular library.
14265
- * @summary This module defines the {@link DecafTooltipDirective}, a standalone Angular directive
14266
- * that dynamically appends a tooltip element to any host element it decorates. It also supports
14267
- * optional text truncation using the {@link DecafTruncatePipe}.
14268
- */
14269
- /**
14270
- * @description Angular directive that appends a tooltip `<span>` to the host element and
14271
- * optionally truncates its visible text content.
14272
- * @summary The `DecafTooltipDirective` is a standalone Angular directive bound to the
14273
- * `[ngx-decaf-tooltip]` attribute selector. It processes the {@link TooltipConfig} provided
14274
- * via the `options` input, sanitizes the text, and appends a `.dcf-tooltip` `<span>` containing
14275
- * the sanitized full text to the host element. The directive also applies the `dcf-tooltip-parent`
14276
- * CSS class to the host for tooltip positioning. When truncation is enabled, the host element's
14277
- * inner content is replaced with the truncated text before the tooltip span is added.
14278
- * @example
14279
- * ```html
14280
- * <!-- Basic tooltip -->
14281
- * <span [ngx-decaf-tooltip]="{ text: 'Full description here' }">Hover me</span>
14282
- *
14283
- * <!-- Truncated visible text with tooltip showing the full content -->
14284
- * <span [ngx-decaf-tooltip]="{ text: veryLongLabel, truncate: true, limit: 20, trail: '…' }">
14285
- * {{ veryLongLabel }}
14286
- * </span>
14287
- * ```
14288
- * @class DecafTooltipDirective
14289
- */
14290
- /**
14291
- * @description Angular lifecycle hook invoked whenever one or more input properties change.
14292
- * @summary Processes the {@link ITooltipConfig} options, sanitizes the text, and updates the
14293
- * host element's content and tooltip span accordingly. Applies the `dcf-tooltip-parent` CSS class
14294
- * to the host for styling.
14295
- * @return {void}
14296
- */
14297
- class DecafTooltipDirective {
14298
- constructor() {
14299
- /**
14300
- * @description Reference to the host DOM element into which the SVG will be injected.
14301
- * @summary Obtained via Angular's `inject(ElementRef)`. Provides access to the native
14302
- * element forwarded to {@link NgxMediaService.loadSvgObserver} as the injection target,
14303
- * and used as a fallback source for the `src` attribute when `path` is not set.
14304
- * @type {ElementRef}
14305
- * @memberOf module:lib/directives/NgxSvgDirective
14306
- */
14307
- this.element = inject(ElementRef);
14308
- this.renderer = inject(Renderer2);
14309
- this.truncatePipe = inject(DecafTruncatePipe);
14310
- }
14311
- /**
14312
- * @description Angular lifecycle hook invoked whenever one or more input properties change.
14313
- * @summary Processes the {@link TooltipConfig} options, sanitizes the text, and updates the
14314
- * host element's content and tooltip span accordingly. Applies the `dcf-tooltip-parent` CSS class
14315
- * to the host for styling.
14316
- * @return {void}
14317
- */
14318
- ngOnChanges() {
14319
- const options = {
14320
- truncate: false,
14321
- limit: 30,
14322
- ...this.options,
14323
- };
14324
- if (options?.text && options?.text.trim().length) {
14325
- const value = options.text.replace(/<[^>]+>/g, '').trim();
14326
- if (value.length > options.limit) {
14327
- const text = !options.truncate
14328
- ? value
14329
- : this.truncatePipe.transform(value, options.limit, options.trail || '...');
14330
- const element = this.element?.nativeElement ? this.element?.nativeElement : this.element;
14331
- if (options.truncate) {
14332
- this.renderer.setProperty(element, 'innerHTML', '');
14333
- const textNode = this.renderer.createText(text);
14334
- this.renderer.appendChild(element, textNode);
14335
- }
14336
- // creating tooltip element
14337
- const tooltip = this.renderer.createElement('span');
14338
- this.renderer.addClass(tooltip, 'dcf-tooltip');
14339
- this.renderer.appendChild(tooltip, this.renderer.createText(this.truncatePipe.sanitize(value)));
14340
- this.renderer.appendChild(element, tooltip);
14341
- this.renderer.addClass(element, 'dcf-tooltip-parent');
14342
- }
14343
- }
14344
- }
14345
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DecafTooltipDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
14346
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.18", type: DecafTooltipDirective, isStandalone: true, selector: "[ngx-decaf-tooltip]", inputs: { options: ["ngx-decaf-tooltip", "options"] }, providers: [DecafTruncatePipe], usesOnChanges: true, ngImport: i0 }); }
14347
- }
14348
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.18", ngImport: i0, type: DecafTooltipDirective, decorators: [{
14349
- type: Directive,
14350
- args: [{
14351
- selector: '[ngx-decaf-tooltip]',
14352
- providers: [DecafTruncatePipe],
14353
- standalone: true,
14354
- }]
14355
- }], propDecorators: { options: [{
14356
- type: Input,
14357
- args: ['ngx-decaf-tooltip']
14358
- }] } });
14359
-
14360
14372
  /**
14361
14373
  * @description Abstract base class for dynamic Angular modules
14362
14374
  * @summary The DynamicModule serves as a base class for Angular modules that need to be