@decaf-ts/for-angular 0.0.47 → 0.0.48

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,15 +1,15 @@
1
- import { HTML5InputTypes, parseValueByType, HTML5CheckTypes, escapeHtml, parseToNumber, RenderingEngine, DecafComponent, UIKeys, RenderingError, UIMediaBreakPoints } from '@decaf-ts/ui-decorators';
1
+ import { HTML5InputTypes, parseValueByType, HTML5CheckTypes, escapeHtml, parseToNumber, RenderingEngine, DecafComponent, UIKeys, RenderingError, UIMediaBreakPoints, DecafEventHandler } from '@decaf-ts/ui-decorators';
2
2
  import * as i0 from '@angular/core';
3
3
  import { InjectionToken, NgModule, isDevMode, reflectComponentType, Injector, createEnvironmentInjector, runInInjectionContext, createComponent, inject, NgZone, Injectable, ChangeDetectorRef, Renderer2, EventEmitter, ElementRef, Input, Output, ViewChild, Inject, Directive, EnvironmentInjector, ViewContainerRef, TemplateRef, Component, HostListener, CUSTOM_ELEMENTS_SCHEMA, ViewEncapsulation } from '@angular/core';
4
4
  import * as i1$1 from '@angular/common';
5
5
  import { CommonModule, Location, NgComponentOutlet } from '@angular/common';
6
6
  import { VALIDATION_PARENT_KEY, ValidationKeys, DEFAULT_PATTERNS, Validation, Primitives, ComparisonValidationKeys, PathProxyEngine, Model, ModelKeys, isValidDate as isValidDate$1, parseDate, sf, ReservedModels } from '@decaf-ts/decorator-validation';
7
- import { OperationKeys, InternalError } from '@decaf-ts/db-decorators';
7
+ import { OperationKeys, InternalError, NotFoundError } from '@decaf-ts/db-decorators';
8
8
  import * as i1 from '@angular/forms';
9
9
  import { FormGroup, FormControl, FormsModule, ReactiveFormsModule, FormArray, AbstractControl, Validators } from '@angular/forms';
10
10
  import { InjectableRegistryImp } from '@decaf-ts/injectable-decorators';
11
11
  import { TranslateModule, TranslatePipe, TranslateParser, provideTranslateService, TranslateLoader, provideTranslateParser, TranslateService } from '@ngx-translate/core';
12
- import { Logging, LoggedClass } from '@decaf-ts/logging';
12
+ import { Logging } from '@decaf-ts/logging';
13
13
  import { Repository, OrderDirection, Condition } from '@decaf-ts/core';
14
14
  import { uses, Metadata, apply, metadata } from '@decaf-ts/decoration';
15
15
  import { faker } from '@faker-js/faker';
@@ -572,9 +572,10 @@ function getModelAndRepository(model) {
572
572
  uses(dbAdapterFlavour)(constructor);
573
573
  const repository = Repository.forModel(constructor);
574
574
  model = new constructor();
575
- if (!repository.pk)
575
+ const pk = Model.pk(repository.class);
576
+ if (!pk)
576
577
  return undefined;
577
- return { repository, model };
578
+ return { repository, model, pk };
578
579
  }
579
580
  catch (error) {
580
581
  getLogger(getModelAndRepository).warn(error?.message || error);
@@ -603,13 +604,12 @@ function getModelAndRepository(model) {
603
604
  * provideDbAdapter(PostgresAdapter, { host: 'localhost', port: 5432 })
604
605
  * ]
605
606
  */
606
- function provideDbAdapter(adapterClass, options = {}, flavour) {
607
- const adapter = new adapterClass(options);
607
+ function provideDbAdapter(clazz, options = {}, flavour) {
608
+ const adapter = new clazz(options);
608
609
  if (flavour)
609
610
  flavour = adapter.flavour;
610
- // Log and expose adapter flavour globally
611
611
  getLogger(provideDbAdapter).info(`Using ${adapter.constructor.name} ${flavour} as Db Provider`);
612
- getWindow()[DB_ADAPTER_PROVIDER] = flavour;
612
+ setOnWindow(DB_ADAPTER_PROVIDER, flavour);
613
613
  return {
614
614
  provide: DB_ADAPTER_PROVIDER_TOKEN,
615
615
  useValue: adapter,
@@ -1423,6 +1423,7 @@ class NgxFormService {
1423
1423
  partFormGroup[BaseComponentProps.FORM_GROUP_COMPONENT_PROPS] = {
1424
1424
  childOf: childOf || '',
1425
1425
  isMultiple: isMultiple,
1426
+ required: parentProps?.required ?? false,
1426
1427
  name: part,
1427
1428
  pk,
1428
1429
  [ModelKeys.MODEL]: {},
@@ -1970,13 +1971,27 @@ class NgxFormService {
1970
1971
  if (control instanceof FormArray) {
1971
1972
  const totalGroups = control.length;
1972
1973
  const hasValid = control.controls.some(control => control.valid);
1973
- if (totalGroups > 1 && hasValid) {
1974
+ const parentProps = control[BaseComponentProps.FORM_GROUP_COMPONENT_PROPS] || {};
1975
+ const childControl = control.at(0);
1976
+ if (totalGroups === 1) {
1977
+ const parent = childControl.parent;
1978
+ if (!parentProps.required) {
1979
+ parent.setErrors(null);
1980
+ parent.updateValueAndValidity({ emitEvent: true });
1981
+ childControl.disable();
1982
+ }
1983
+ else {
1984
+ this.validateFields(childControl);
1985
+ }
1986
+ }
1987
+ else if (totalGroups > 1 && hasValid) {
1974
1988
  for (let i = control.length - 1; i >= 0; i--) {
1975
1989
  const childControl = control.at(i);
1976
1990
  // disable no valid groups on array
1977
1991
  if (!childControl.valid) {
1978
- childControl.parent.setErrors(null);
1979
- childControl.parent.updateValueAndValidity({ emitEvent: true });
1992
+ const parent = childControl.parent;
1993
+ parent.setErrors(null);
1994
+ parent.updateValueAndValidity({ emitEvent: true });
1980
1995
  childControl.disable();
1981
1996
  }
1982
1997
  else {
@@ -2199,25 +2214,23 @@ class DecafFakerRepository {
2199
2214
  if (!this._repository)
2200
2215
  this._repository = this.repository;
2201
2216
  }
2202
- async generateData(pkValues, pk, pkType) {
2203
- const limit = pkValues
2204
- ? Object.values(pkValues || {}).length - 1
2205
- : this.limit;
2206
- if (!pk)
2207
- pk = this._repository?.pk;
2208
- if (!pkType)
2209
- pkType = Metadata.type(this.repository.class, pk).name.toLowerCase();
2217
+ async generateData(values, key, keyType) {
2218
+ const limit = values ? Object.values(values || {}).length : this.limit;
2219
+ if (!key)
2220
+ key = Model.pk(this.repository.class);
2221
+ if (!keyType)
2222
+ keyType = Metadata.type(this.repository.class, key).name.toLowerCase();
2210
2223
  const props = Object.keys(this.model).filter((k) => {
2211
- if (pkType === Primitives.STRING)
2224
+ if (keyType === Primitives.STRING)
2212
2225
  return !['updatedBy', 'createdAt', 'createdBy', 'updatedAt'].includes(k);
2213
- return ![pk, 'updatedBy', 'createdAt', 'createdBy', 'updatedAt'].includes(k);
2226
+ return ![key, 'updatedBy', 'createdAt', 'createdBy', 'updatedAt'].includes(k);
2214
2227
  });
2215
2228
  const dataProps = {};
2216
2229
  for (const prop of props) {
2217
- const type = Metadata.type(this.repository.class, prop).name.toLowerCase();
2218
- switch ((type?.name || '').toLowerCase()) {
2230
+ const type = Metadata.type(this.repository.class, prop);
2231
+ switch (type.name.toLowerCase()) {
2219
2232
  case 'string':
2220
- dataProps[prop] = () => `${faker.lorem.word()} ${pk === prop ? ' - ' + faker.number.int({ min: 1, max: 200 }) : ''}`;
2233
+ dataProps[prop] = () => `${faker.lorem.word()} ${key === prop ? ' - ' + faker.number.int({ min: 1, max: 200 }) : ''}`;
2221
2234
  break;
2222
2235
  case 'step':
2223
2236
  dataProps[prop] = () => faker.lorem.word();
@@ -2243,25 +2256,25 @@ class DecafFakerRepository {
2243
2256
  }
2244
2257
  }
2245
2258
  const data = getFakerData(limit, dataProps, typeof this.model === 'string' ? this.model : this.model?.constructor.name);
2246
- if (!pkValues)
2259
+ if (!values)
2247
2260
  return data;
2248
- const values = Object.values(pkValues);
2261
+ const _values = Object.values(values);
2249
2262
  const iterated = [];
2250
2263
  function getPkValue(item) {
2251
- if (values.length > 0) {
2252
- const randomIndex = Math.floor(Math.random() * values.length);
2253
- const selected = values.splice(randomIndex, 1)[0];
2254
- const value = pkType === Primitives.STRING
2264
+ if (_values.length > 0) {
2265
+ const randomIndex = Math.floor(Math.random() * _values.length);
2266
+ const selected = _values.splice(randomIndex, 1)[0];
2267
+ const value = keyType === Primitives.STRING
2255
2268
  ? selected
2256
- : pkType === Primitives.NUMBER
2269
+ : keyType === Primitives.NUMBER
2257
2270
  ? parseToNumber(selected)
2258
- : pkType === Array.name
2271
+ : keyType === Array.name
2259
2272
  ? [selected]
2260
2273
  : selected;
2261
- item[pk] = value;
2274
+ item[key] = value;
2262
2275
  }
2263
- if (!iterated.includes(item[pk])) {
2264
- iterated.push(item[pk]);
2276
+ if (!iterated.includes(item[key])) {
2277
+ iterated.push(item[key]);
2265
2278
  return item;
2266
2279
  }
2267
2280
  return undefined;
@@ -2270,9 +2283,9 @@ class DecafFakerRepository {
2270
2283
  return data
2271
2284
  .map((d) => getPkValue(d))
2272
2285
  .filter((item) => {
2273
- if (!item || uids.has(item[pk]) || !item[pk] || item[pk] === undefined)
2286
+ if (!item || uids.has(item[key]) || !item[key] || item[key] === undefined)
2274
2287
  return false;
2275
- uids.add(item[pk]);
2288
+ uids.add(item[key]);
2276
2289
  return true;
2277
2290
  })
2278
2291
  .filter(Boolean);
@@ -2290,6 +2303,8 @@ function getFakerData(limit = 100, data, model) {
2290
2303
  // (item as any).code = `${index}`;
2291
2304
  // item.id = index;
2292
2305
  // item.createdAt = faker.date.past({ refDate: '2025-01-01' });
2306
+ if (item['productCode'])
2307
+ item['productCode'] = `${index}`;
2293
2308
  index = index + 1;
2294
2309
  return (!model ? item : Model.build(item, model));
2295
2310
  });
@@ -2810,6 +2825,10 @@ var operations = {
2810
2825
  "delete": {
2811
2826
  success: "Successfully deleted item with {0} {1}.",
2812
2827
  error: "Error deleting item with {0} {1}."
2828
+ },
2829
+ multiple: {
2830
+ success: "Successfully processed all operations.",
2831
+ error: "Error processing operations."
2813
2832
  }
2814
2833
  };
2815
2834
  var component = {
@@ -2819,7 +2838,8 @@ var component = {
2819
2838
  cancel: "Cancel",
2820
2839
  not_unique: "The value entered already exists. Value {0}",
2821
2840
  max_items: "You can create up to {0} items.",
2822
- max_items_reached: "Maximum of {0} items reached."
2841
+ max_items_reached: "Maximum of {0} items reached.",
2842
+ empty: "No items found."
2823
2843
  },
2824
2844
  list: {
2825
2845
  pagination: "Showing page <span class=\"text-bold\">{0} of {1}</span>",
@@ -3552,9 +3572,9 @@ class NgxComponentDirective extends DecafComponent {
3552
3572
  * The operation affects form validation, field availability, and the specific repository
3553
3573
  * method called during data submission.
3554
3574
  *
3555
- * @type {OperationKeys.CREATE | OperationKeys.READ | OperationKeys.UPDATE | OperationKeys.DELETE}
3575
+ * @type {OperationKeys}
3556
3576
  * @default OperationKeys.READ
3557
- * @memberOf ModelPage
3577
+ * @memberOf module:lib/engine/NgxComponentDirective
3558
3578
  */
3559
3579
  this.operation = OperationKeys.READ;
3560
3580
  /**
@@ -3642,6 +3662,16 @@ class NgxComponentDirective extends DecafComponent {
3642
3662
  * @memberOf module:lib/engine/NgxComponentDirective
3643
3663
  */
3644
3664
  this.listenEvent = new EventEmitter();
3665
+ /**
3666
+ * @description Event emitter for custom component events.
3667
+ * @summary Emits custom events that occur within child components or the component itself.
3668
+ * This allows parent components to listen for and respond to user interactions or
3669
+ * state changes. Events are passed up the component hierarchy to enable coordinated
3670
+ * behavior across the application.
3671
+ * @type {EventEmitter<IBaseCustomEvent>}
3672
+ * @memberOf module:lib/engine/NgxComponentDirective
3673
+ */
3674
+ this.refreshEvent = new EventEmitter();
3645
3675
  /**
3646
3676
  * @description Angular Router instance for programmatic navigation.
3647
3677
  * @summary Injected Router service used for programmatic navigation between routes
@@ -3723,7 +3753,17 @@ class NgxComponentDirective extends DecafComponent {
3723
3753
  this.isModalChild = false;
3724
3754
  this.handlers = {};
3725
3755
  this.events = {};
3726
- this.componentName = componentName || "NgxComponentDirective";
3756
+ /**
3757
+ * @description Indicates whether a refresh operation is in progress.
3758
+ * @summary When true, the component is currently fetching new data. This is used
3759
+ * to control loading indicators and prevent duplicate refresh operations from
3760
+ * being triggered simultaneously.
3761
+ *
3762
+ * @type {boolean}
3763
+ * @default false
3764
+ */
3765
+ this.refreshing = false;
3766
+ this.componentName = componentName || 'NgxComponentDirective';
3727
3767
  this.localeRoot = localeRoot;
3728
3768
  if (!this.localeRoot && this.componentName)
3729
3769
  this.localeRoot = this.componentName;
@@ -3742,6 +3782,11 @@ class NgxComponentDirective extends DecafComponent {
3742
3782
  ngOnDestroy() {
3743
3783
  this.mediaService.destroy();
3744
3784
  }
3785
+ //TODO: Pass to ui decoretators
3786
+ async refresh(...args) {
3787
+ this.log.for(this.refresh).debug(`Refresh called with args: ${args}`);
3788
+ this.refreshEvent.emit(true);
3789
+ }
3745
3790
  /**
3746
3791
  * @description Getter for the current locale context identifier.
3747
3792
  * @summary Returns the current locale identifier by calling the getLocale method.
@@ -3767,8 +3812,7 @@ class NgxComponentDirective extends DecafComponent {
3767
3812
  if (!this._repository) {
3768
3813
  this._repository = getModelAndRepository(this.model)?.repository;
3769
3814
  if (this.model && !this.pk)
3770
- this.pk =
3771
- this._repository.pk || 'id';
3815
+ this.pk = Model.pk(this._repository?.class);
3772
3816
  }
3773
3817
  }
3774
3818
  catch (error) {
@@ -3776,6 +3820,9 @@ class NgxComponentDirective extends DecafComponent {
3776
3820
  }
3777
3821
  return this._repository;
3778
3822
  }
3823
+ set repository(repository) {
3824
+ this._repository = repository;
3825
+ }
3779
3826
  /**
3780
3827
  * @description Angular lifecycle hook for handling input property changes.
3781
3828
  * @summary Responds to changes in component input properties, specifically monitoring changes
@@ -3795,21 +3842,39 @@ class NgxComponentDirective extends DecafComponent {
3795
3842
  if (!this.initialized)
3796
3843
  this.initialized = true;
3797
3844
  }
3845
+ // if (changes[UIKeys.HANDLERS]) {
3846
+ // const { currentValue, previousValue } = changes[UIKeys.HANDLERS];
3847
+ // if (currentValue && typeof currentValue !== previousValue) {
3848
+ // for(const key in currentValue) {
3849
+ // const event = currentValue[key]();
3850
+ // if (event && typeof event === 'function') {
3851
+ // const clazz = new event();
3852
+ // this.handlers[key] = clazz[key].bind(this);
3853
+ // console.log(this.handlers);
3854
+ // }
3855
+ // }
3856
+ // }
3857
+ // }
3798
3858
  if (changes[UIKeys.EVENTS]) {
3799
3859
  const { currentValue, previousValue } = changes[UIKeys.EVENTS];
3800
- if (currentValue && typeof currentValue !== previousValue) {
3860
+ if (currentValue && currentValue !== previousValue) {
3801
3861
  if (!this._repository)
3802
3862
  this._repository = this.repository;
3803
3863
  for (const key in currentValue) {
3804
3864
  const event = currentValue[key]();
3805
3865
  if (event && typeof event === 'function') {
3806
- const clazz = new event();
3807
- this.events[key] = clazz[key].bind(this);
3808
- if (event[key] instanceof Promise) {
3809
- await clazz[key].bind(this)();
3866
+ try {
3867
+ const clazz = new event();
3868
+ this.events[key] = clazz[key].bind(this);
3869
+ if (event[key] instanceof Promise) {
3870
+ await clazz[key].bind(this)();
3871
+ }
3872
+ else {
3873
+ clazz[key].bind(this)();
3874
+ }
3810
3875
  }
3811
- else {
3812
- clazz[key].bind(this)();
3876
+ catch (error) {
3877
+ this.log.for(this.ngOnChanges).warn(`Error occurred while processing event "${key}": ${error?.message || error}`);
3813
3878
  }
3814
3879
  }
3815
3880
  }
@@ -3839,7 +3904,7 @@ class NgxComponentDirective extends DecafComponent {
3839
3904
  ;
3840
3905
  }
3841
3906
  checkDarkMode() {
3842
- this.mediaService.isDarkMode().subscribe(isDark => {
3907
+ this.mediaService.isDarkMode().subscribe((isDark) => {
3843
3908
  this.isDarkMode = isDark;
3844
3909
  this.mediaService.toggleClass([this.component], AngularEngineKeys.DARK_PALETTE_CLASS, this.isDarkMode);
3845
3910
  });
@@ -4016,7 +4081,7 @@ class NgxComponentDirective extends DecafComponent {
4016
4081
  * end
4017
4082
  * @memberOf module:lib/engine/NgxComponentDirective
4018
4083
  */
4019
- async handleEvent(event) {
4084
+ async handleEvent(event, repository) {
4020
4085
  let name = "";
4021
4086
  const log = this.log.for(this.handleEvent);
4022
4087
  if (event instanceof CustomEvent) {
@@ -4031,8 +4096,11 @@ class NgxComponentDirective extends DecafComponent {
4031
4096
  if (!handlers[name])
4032
4097
  return log.debug(`No handler found for event ${name}`);
4033
4098
  try {
4034
- const clazz = new handlers[name](this.router);
4035
- const result = clazz.handle(event);
4099
+ const clazz = new handlers[name]();
4100
+ const handler = clazz.handle.bind(this);
4101
+ //const clazz = new event();
4102
+ // this.events[key] = clazz[key].bind(this);
4103
+ const result = handler(event);
4036
4104
  return (result instanceof Promise) ?
4037
4105
  await result : result;
4038
4106
  }
@@ -4042,6 +4110,10 @@ class NgxComponentDirective extends DecafComponent {
4042
4110
  }
4043
4111
  this.listenEvent.emit(event);
4044
4112
  }
4113
+ // passed for ui decorators
4114
+ // async submit(...args: unknown[]): Promise<any> {
4115
+ // this.log.for(this.submit).info(`submit for ${this.componentName} with ${JSON.stringify(args)}`);
4116
+ // }
4045
4117
  /**
4046
4118
  * @description Determines if a specific operation is allowed in the current context.
4047
4119
  * @summary This method checks if an operation is included in the list of available
@@ -4068,7 +4140,9 @@ class NgxComponentDirective extends DecafComponent {
4068
4140
  isAllowed(operation) {
4069
4141
  if (!this.operations)
4070
4142
  return false;
4071
- return this.operations.includes(operation) && (this.operation !== OperationKeys.CREATE && ((this.operation || "").toLowerCase() !== operation || !this.operation));
4143
+ return (this.operations.includes(operation) &&
4144
+ this.operation !== OperationKeys.CREATE &&
4145
+ ((this.operation || '').toLowerCase() !== operation || !this.operation));
4072
4146
  }
4073
4147
  /**
4074
4148
  * @description Navigates to a different operation for the current model.
@@ -4105,7 +4179,7 @@ class NgxComponentDirective extends DecafComponent {
4105
4179
  return this.router.navigateByUrl(page);
4106
4180
  }
4107
4181
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgxComponentDirective, deps: [{ token: CPTKN }, { token: CPTKN }], target: i0.ɵɵFactoryTarget.Directive }); }
4108
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgxComponentDirective, isStandalone: true, inputs: { enableDarkMode: "enableDarkMode", isDarkMode: "isDarkMode", name: "name", childOf: "childOf", uid: "uid", model: "model", modelId: "modelId", pk: "pk", mapper: "mapper", operations: "operations", operation: "operation", row: "row", col: "col", className: "className", locale: "locale", item: "item", props: "props", route: "route", borders: "borders", isModalChild: "isModalChild", handlers: "handlers", events: "events" }, outputs: { listenEvent: "listenEvent" }, host: { properties: { "attr.id": "uid" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
4182
+ static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "20.3.9", type: NgxComponentDirective, isStandalone: true, inputs: { enableDarkMode: "enableDarkMode", isDarkMode: "isDarkMode", name: "name", childOf: "childOf", uid: "uid", model: "model", modelId: "modelId", value: "value", pk: "pk", mapper: "mapper", operations: "operations", operation: "operation", row: "row", col: "col", className: "className", locale: "locale", item: "item", props: "props", route: "route", borders: "borders", isModalChild: "isModalChild", handlers: "handlers", events: "events" }, outputs: { listenEvent: "listenEvent", refreshEvent: "refreshEvent" }, host: { properties: { "attr.id": "uid" } }, viewQueries: [{ propertyName: "component", first: true, predicate: ["component"], descendants: true, read: ElementRef, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
4109
4183
  }
4110
4184
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgxComponentDirective, decorators: [{
4111
4185
  type: Directive,
@@ -4133,6 +4207,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
4133
4207
  type: Input
4134
4208
  }], modelId: [{
4135
4209
  type: Input
4210
+ }], value: [{
4211
+ type: Input
4136
4212
  }], pk: [{
4137
4213
  type: Input
4138
4214
  }], mapper: [{
@@ -4149,6 +4225,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
4149
4225
  type: Input
4150
4226
  }], listenEvent: [{
4151
4227
  type: Output
4228
+ }], refreshEvent: [{
4229
+ type: Output
4152
4230
  }], locale: [{
4153
4231
  type: Input
4154
4232
  }], item: [{
@@ -4913,7 +4991,7 @@ class ModelRendererComponent extends NgxRenderableComponentDirective {
4913
4991
  * @description Refreshes the rendered model
4914
4992
  * @param {string | M} model - The model to be rendered
4915
4993
  */
4916
- refresh(model) {
4994
+ async refresh(model) {
4917
4995
  model =
4918
4996
  typeof model === 'string'
4919
4997
  ? Model.build({}, model)
@@ -5094,7 +5172,7 @@ class NgxParentComponentDirective extends NgxComponentDirective {
5094
5172
  const content = this.children[page];
5095
5173
  this.activePage = undefined;
5096
5174
  this.preloadCards = [...new Array(1)];
5097
- this.timerSubscription = timer(1).subscribe(() => this.activePage = { ...this.children[page] });
5175
+ this.timerSubscription = timer(25).subscribe(() => this.activePage = { ...this.children[page] });
5098
5176
  this.activeIndex = page;
5099
5177
  if (content)
5100
5178
  return content;
@@ -6060,7 +6138,7 @@ class NgxFormDirective extends NgxParentComponentDirective {
6060
6138
  return NgxFormService.reset(this.formGroup);
6061
6139
  this.location.back();
6062
6140
  }
6063
- async handleSubmit(event, eventName, componentName) {
6141
+ async submit(event, eventName, componentName) {
6064
6142
  if (event) {
6065
6143
  event.preventDefault();
6066
6144
  event.stopImmediatePropagation();
@@ -6530,7 +6608,7 @@ let LayoutComponent = class LayoutComponent extends NgxParentComponentDirective
6530
6608
  this.changeDetectorRef.detectChanges();
6531
6609
  }
6532
6610
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LayoutComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6533
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: LayoutComponent, isStandalone: true, selector: "ngx-decaf-layout", inputs: { gap: "gap", grid: "grid", flexMode: "flexMode", rowCard: "rowCard", maxColsLength: "maxColsLength" }, usesInheritance: true, ngImport: i0, template: "<section class=\"dcf-layout-container\">\n @if (initialized) {\n @for (row of rows; track trackItemFn($index, row); let rowIndex = $index) {\n @if (row?.cols?.length) {\n <div\n [id]=\"uid\"\n [class]=\"\n (!grid\n ? 'dcf-layout-row '\n : 'dcf-layout-row dcf-grid ' + 'dcf-grid-' + gap) +\n ' ' +\n (className || '')\n \"\n [class.dcf-grid-match]=\"match\"\n [class.dcf-grid-bordered]=\"borders\"\n >\n @if (row?.title?.length) {\n <div class=\"dcf-width-1-1 dcf-grid-title\">\n <h3 class=\"\">{{ row.title | translate }}</h3>\n </div>\n }\n @for (\n child of row.cols;\n track trackItemFn($index, child.col);\n let colIndex = $index\n ) {\n\n <div\n [class]=\"'dcf-grid-col ' + child.colClass\"\n [class.dcf-first-column]=\"$index === 0\"\n [class.dcf-layout-separator]=\"child.props?.separator ?? false\"\n >\n <div>\n\n @if (child.tag === \"ngx-decaf-crud-form\") {\n\n <ngx-decaf-card\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [body]=\"cardBody\"\n [type]=\"cardType\"\n >\n <ngx-decaf-model-renderer\n [model]=\"child.props.name\"\n (listenEvent)=\"handleEvent($event)\"\n />\n </ngx-decaf-card>\n } @else {\n\n <ngx-decaf-component-renderer\n [tag]=\"child.tag\"\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [parentForm]=\"parentForm || child.parentForm || child?.formGroup\"\n [children]=\"child?.children || []\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{ props: child.props }\"\n />\n }\n </div>\n </div>\n }\n </div>\n }\n }\n }\n</section>\n", styles: [".dcf-grid.dcf-grid-bordered>div>div{padding:var(--dcf-padding-small) var(--dcf-padding);border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-2);background:var(--dcf-card-background)!important}.dcf-grid .dcf-grid-title{padding:unset;margin:unset}.dcf-grid .dcf-grid-title>*{padding:unset;margin:unset;padding-left:var(--dcf-padding-small);font-size:1.05rem!important;font-weight:600;background:none;box-shadow:none;display:flex;align-items:center;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.dcf-grid.dcf-grid-match ::ng-deep ngx-decaf-component-renderer>*>*{height:100%!important}.dcf-grid.dcf-grid-small.dcf-grid-nested{padding:0 .5rem!important}.dcf-grid.dcf-grid-small>div{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small>div.dcf-layout-separator{margin-bottom:1rem}.dcf-grid.dcf-grid-small>div.dcf-grid-bordered:last-child{margin-bottom:0}.dcf-grid.dcf-grid-small+.dcf-grid-small{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small+.dcf-grid-small.dcf-layout-separator{margin-bottom:1rem}::ng-deep ngx-decaf-component-renderer>*>div{margin-bottom:0!important}\n"], dependencies: [{ kind: "component", type: CardComponent, selector: "ngx-decaf-card", inputs: ["type", "title", "body", "subtitle", "color", "separator", "borders", "inlineContent", "inlineContentPosition"] }, { kind: "component", type: ModelRendererComponent, selector: "ngx-decaf-model-renderer", inputs: ["projectable"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "children", "projectable", "parent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6611
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: LayoutComponent, isStandalone: true, selector: "ngx-decaf-layout", inputs: { gap: "gap", grid: "grid", flexMode: "flexMode", rowCard: "rowCard", maxColsLength: "maxColsLength" }, usesInheritance: true, ngImport: i0, template: "<section class=\"dcf-layout-container\">\n @if (initialized) {\n @for (row of rows; track trackItemFn($index, row); let rowIndex = $index) {\n @if (row?.cols?.length) {\n <div\n [id]=\"uid\"\n [class]=\"\n (!grid\n ? 'dcf-layout-row '\n : 'dcf-layout-row dcf-grid ' + 'dcf-grid-' + gap) +\n ' ' +\n (className || '')\n \"\n [class.dcf-grid-match]=\"match\"\n [class.dcf-grid-bordered]=\"borders\"\n >\n @if (row?.title?.length) {\n <div class=\"dcf-width-1-1 dcf-grid-title\">\n <h3 class=\"\">{{ row.title | translate }}</h3>\n </div>\n }\n @for (\n child of row.cols;\n track trackItemFn($index, child.col);\n let colIndex = $index\n ) {\n\n <div\n [class]=\"'dcf-grid-col ' + child.colClass\"\n [class.dcf-first-column]=\"$index === 0\"\n [class.dcf-layout-separator]=\"child.props?.separator ?? false\"\n >\n <div>\n\n @if (child.tag === \"ngx-decaf-crud-form\") {\n\n <ngx-decaf-card\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [body]=\"cardBody\"\n [type]=\"cardType\"\n >\n <ngx-decaf-model-renderer\n [model]=\"child.props.name\"\n (listenEvent)=\"handleEvent($event)\"\n />\n </ngx-decaf-card>\n } @else {\n\n <ngx-decaf-component-renderer\n [tag]=\"child.tag\"\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [parentForm]=\"parentForm || child.parentForm || child?.formGroup\"\n [children]=\"child?.children || []\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{ props: child.props }\"\n />\n }\n </div>\n </div>\n }\n </div>\n }\n }\n }\n</section>\n", styles: [".dcf-grid.dcf-grid-collapse.read>div{margin:var(--dcf-margin-small) 0!important}.dcf-grid.dcf-grid-bordered>div>div{padding:var(--dcf-padding-small) var(--dcf-padding);border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-2);background:var(--dcf-card-background)!important}.dcf-grid .dcf-grid-title{padding:unset;margin:unset}.dcf-grid .dcf-grid-title>*{padding:unset;margin:unset;padding-left:var(--dcf-padding-small);font-size:1.05rem!important;font-weight:600;background:none;box-shadow:none;display:flex;align-items:center;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.dcf-grid.dcf-grid-match ::ng-deep ngx-decaf-component-renderer>*>*{height:100%!important}.dcf-grid.dcf-grid-small.dcf-grid-nested{padding:0 .5rem!important}.dcf-grid.dcf-grid-small>div{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small>div.dcf-layout-separator{margin-bottom:1rem}.dcf-grid.dcf-grid-small>div.dcf-grid-bordered:last-child{margin-bottom:0}.dcf-grid.dcf-grid-small+.dcf-grid-small{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small+.dcf-grid-small.dcf-layout-separator{margin-bottom:1rem}::ng-deep ngx-decaf-component-renderer>*>div{margin-bottom:0!important}\n"], dependencies: [{ kind: "component", type: CardComponent, selector: "ngx-decaf-card", inputs: ["type", "title", "body", "subtitle", "color", "separator", "borders", "inlineContent", "inlineContentPosition"] }, { kind: "component", type: ModelRendererComponent, selector: "ngx-decaf-model-renderer", inputs: ["projectable"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "children", "projectable", "parent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
6534
6612
  };
6535
6613
  LayoutComponent = __decorate([
6536
6614
  Dynamic(),
@@ -6538,7 +6616,7 @@ LayoutComponent = __decorate([
6538
6616
  ], LayoutComponent);
6539
6617
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: LayoutComponent, decorators: [{
6540
6618
  type: Component,
6541
- args: [{ selector: 'ngx-decaf-layout', imports: [TranslatePipe, CardComponent, ModelRendererComponent, ComponentRendererComponent], standalone: true, template: "<section class=\"dcf-layout-container\">\n @if (initialized) {\n @for (row of rows; track trackItemFn($index, row); let rowIndex = $index) {\n @if (row?.cols?.length) {\n <div\n [id]=\"uid\"\n [class]=\"\n (!grid\n ? 'dcf-layout-row '\n : 'dcf-layout-row dcf-grid ' + 'dcf-grid-' + gap) +\n ' ' +\n (className || '')\n \"\n [class.dcf-grid-match]=\"match\"\n [class.dcf-grid-bordered]=\"borders\"\n >\n @if (row?.title?.length) {\n <div class=\"dcf-width-1-1 dcf-grid-title\">\n <h3 class=\"\">{{ row.title | translate }}</h3>\n </div>\n }\n @for (\n child of row.cols;\n track trackItemFn($index, child.col);\n let colIndex = $index\n ) {\n\n <div\n [class]=\"'dcf-grid-col ' + child.colClass\"\n [class.dcf-first-column]=\"$index === 0\"\n [class.dcf-layout-separator]=\"child.props?.separator ?? false\"\n >\n <div>\n\n @if (child.tag === \"ngx-decaf-crud-form\") {\n\n <ngx-decaf-card\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [body]=\"cardBody\"\n [type]=\"cardType\"\n >\n <ngx-decaf-model-renderer\n [model]=\"child.props.name\"\n (listenEvent)=\"handleEvent($event)\"\n />\n </ngx-decaf-card>\n } @else {\n\n <ngx-decaf-component-renderer\n [tag]=\"child.tag\"\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [parentForm]=\"parentForm || child.parentForm || child?.formGroup\"\n [children]=\"child?.children || []\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{ props: child.props }\"\n />\n }\n </div>\n </div>\n }\n </div>\n }\n }\n }\n</section>\n", styles: [".dcf-grid.dcf-grid-bordered>div>div{padding:var(--dcf-padding-small) var(--dcf-padding);border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-2);background:var(--dcf-card-background)!important}.dcf-grid .dcf-grid-title{padding:unset;margin:unset}.dcf-grid .dcf-grid-title>*{padding:unset;margin:unset;padding-left:var(--dcf-padding-small);font-size:1.05rem!important;font-weight:600;background:none;box-shadow:none;display:flex;align-items:center;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.dcf-grid.dcf-grid-match ::ng-deep ngx-decaf-component-renderer>*>*{height:100%!important}.dcf-grid.dcf-grid-small.dcf-grid-nested{padding:0 .5rem!important}.dcf-grid.dcf-grid-small>div{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small>div.dcf-layout-separator{margin-bottom:1rem}.dcf-grid.dcf-grid-small>div.dcf-grid-bordered:last-child{margin-bottom:0}.dcf-grid.dcf-grid-small+.dcf-grid-small{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small+.dcf-grid-small.dcf-layout-separator{margin-bottom:1rem}::ng-deep ngx-decaf-component-renderer>*>div{margin-bottom:0!important}\n"] }]
6619
+ args: [{ selector: 'ngx-decaf-layout', imports: [TranslatePipe, CardComponent, ModelRendererComponent, ComponentRendererComponent], standalone: true, template: "<section class=\"dcf-layout-container\">\n @if (initialized) {\n @for (row of rows; track trackItemFn($index, row); let rowIndex = $index) {\n @if (row?.cols?.length) {\n <div\n [id]=\"uid\"\n [class]=\"\n (!grid\n ? 'dcf-layout-row '\n : 'dcf-layout-row dcf-grid ' + 'dcf-grid-' + gap) +\n ' ' +\n (className || '')\n \"\n [class.dcf-grid-match]=\"match\"\n [class.dcf-grid-bordered]=\"borders\"\n >\n @if (row?.title?.length) {\n <div class=\"dcf-width-1-1 dcf-grid-title\">\n <h3 class=\"\">{{ row.title | translate }}</h3>\n </div>\n }\n @for (\n child of row.cols;\n track trackItemFn($index, child.col);\n let colIndex = $index\n ) {\n\n <div\n [class]=\"'dcf-grid-col ' + child.colClass\"\n [class.dcf-first-column]=\"$index === 0\"\n [class.dcf-layout-separator]=\"child.props?.separator ?? false\"\n >\n <div>\n\n @if (child.tag === \"ngx-decaf-crud-form\") {\n\n <ngx-decaf-card\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [body]=\"cardBody\"\n [type]=\"cardType\"\n >\n <ngx-decaf-model-renderer\n [model]=\"child.props.name\"\n (listenEvent)=\"handleEvent($event)\"\n />\n </ngx-decaf-card>\n } @else {\n\n <ngx-decaf-component-renderer\n [tag]=\"child.tag\"\n [className]=\"\n (match ? 'dcf-height-1-1 dcf-card-layout' : '') +\n className\n \"\n [parentForm]=\"parentForm || child.parentForm || child?.formGroup\"\n [children]=\"child?.children || []\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]=\"{ props: child.props }\"\n />\n }\n </div>\n </div>\n }\n </div>\n }\n }\n }\n</section>\n", styles: [".dcf-grid.dcf-grid-collapse.read>div{margin:var(--dcf-margin-small) 0!important}.dcf-grid.dcf-grid-bordered>div>div{padding:var(--dcf-padding-small) var(--dcf-padding);border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-2);background:var(--dcf-card-background)!important}.dcf-grid .dcf-grid-title{padding:unset;margin:unset}.dcf-grid .dcf-grid-title>*{padding:unset;margin:unset;padding-left:var(--dcf-padding-small);font-size:1.05rem!important;font-weight:600;background:none;box-shadow:none;display:flex;align-items:center;white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.dcf-grid.dcf-grid-match ::ng-deep ngx-decaf-component-renderer>*>*{height:100%!important}.dcf-grid.dcf-grid-small.dcf-grid-nested{padding:0 .5rem!important}.dcf-grid.dcf-grid-small>div{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small>div.dcf-layout-separator{margin-bottom:1rem}.dcf-grid.dcf-grid-small>div.dcf-grid-bordered:last-child{margin-bottom:0}.dcf-grid.dcf-grid-small+.dcf-grid-small{margin-bottom:1.75rem}.dcf-grid.dcf-grid-small+.dcf-grid-small.dcf-layout-separator{margin-bottom:1rem}::ng-deep ngx-decaf-component-renderer>*>div{margin-bottom:0!important}\n"] }]
6542
6620
  }], ctorParameters: () => [], propDecorators: { gap: [{
6543
6621
  type: Input
6544
6622
  }], grid: [{
@@ -6587,7 +6665,7 @@ let CrudFormComponent = class CrudFormComponent extends NgxFormDirective {
6587
6665
  });
6588
6666
  }
6589
6667
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CrudFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
6590
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: CrudFormComponent, isStandalone: true, selector: "ngx-decaf-crud-form", host: { properties: { "attr.id": "uid" } }, usesInheritance: true, ngImport: i0, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"handleSubmit($event)\"\n novalidate\n [target]=\"target\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n <ngx-decaf-layout\n [className]=\"'dcf-crud-form-grid dcf-grid-nested '\"\n [children]=\"children || []\"\n [parentForm]=\"formGroup || parentForm\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n }\n @if (initialized) {\n <div class=\"dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left\">\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : options.buttons.submit.text}}\n </ion-button>\n </div>\n @if (!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n Back\n </ion-button>\n </div>\n }\n </div>\n }\n\n </form>\n} @else {\n <section [class]=\"'dcf-grid dcf-grid-small dcf-child-width-1-1 dcf-form-grid ' + operation\" #component [id]=\"uid\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n @for (child of children; track $index) {\n <div class=\"dcf-form-item\">\n <ngx-decaf-component-renderer\n [tag]=\"child?.tag\"\n [projectable]=\"false\"\n [children]=\"child?.children || []\"\n [globals]=\"{props: child.props}\"\n />\n </div>\n }\n }\n </section>\n <section [class]=\"'dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if ([OperationKeys.READ, OperationKeys.DELETE].includes(operation) && modelId) {\n <div>\n <ion-button\n (click)=\"handleDelete()\"\n color=\"danger\"\n type=\"button\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n Delete\n </ion-button>\n </div>\n\n }\n @if (operation === OperationKeys.CREATE || operation === OperationKeys.UPDATE) {\n\n <div>\n <ion-button\n type=\"submit\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{options.buttons.submit.text}}\n </ion-button>\n </div>\n }\n\n @if (options.buttons.clear) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ [OperationKeys.DELETE, OperationKeys.READ, OperationKeys.UPDATE].includes(operation) ? 'Back' : options.buttons.clear?.text}}\n </ion-button>\n </div>\n\n }\n </section>\n}\n\n", styles: [".dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (min-width: 577px){.dcf-buttons-grid.dcf-flex{flex-direction:row-reverse}}@media (max-width: 576px){.dcf-buttons-grid.dcf-flex>div{width:100%}.dcf-buttons-grid.dcf-flex>div+div{margin-top:1rem}.dcf-buttons-grid.dcf-flex ion-button{width:100%}}.dcf-form-grid.create,.dcf-form-grid.update{margin-top:var(--dcf-margin-small)}.dcf-form-grid .dcf-form-item{margin-top:0!important}.dcf-form-grid.read .dcf-form-item{margin-bottom:var(--dcf-margin-small)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: LayoutComponent, selector: "ngx-decaf-layout", inputs: ["gap", "grid", "flexMode", "rowCard", "maxColsLength"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "children", "projectable", "parent"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
6668
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: CrudFormComponent, isStandalone: true, selector: "ngx-decaf-crud-form", host: { properties: { "attr.id": "uid" } }, usesInheritance: true, ngImport: i0, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"submit($event)\"\n novalidate\n [target]=\"target\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n <ngx-decaf-layout\n [className]=\"'dcf-crud-form-grid dcf-grid-nested '\"\n [children]=\"children || []\"\n [parentForm]=\"formGroup || parentForm\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n }\n @if (initialized) {\n <div class=\"dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left\">\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : options.buttons.submit.text}}\n </ion-button>\n </div>\n @if (!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n Back\n </ion-button>\n </div>\n }\n </div>\n }\n\n </form>\n} @else {\n <section [class]=\"'dcf-grid dcf-grid-small dcf-child-width-1-1 dcf-form-grid ' + operation\" #component [id]=\"uid\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n @for (child of children; track $index) {\n <div class=\"dcf-form-item\">\n <ngx-decaf-component-renderer\n [tag]=\"child?.tag\"\n [projectable]=\"false\"\n [children]=\"child?.children || []\"\n [globals]=\"{props: child.props}\"\n />\n </div>\n }\n }\n </section>\n <section [class]=\"'dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if ([OperationKeys.READ, OperationKeys.DELETE].includes(operation) && modelId) {\n <div>\n <ion-button\n (click)=\"handleDelete()\"\n color=\"danger\"\n type=\"button\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n Delete\n </ion-button>\n </div>\n\n }\n @if (operation === OperationKeys.CREATE || operation === OperationKeys.UPDATE) {\n\n <div>\n <ion-button\n type=\"submit\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{options.buttons.submit.text}}\n </ion-button>\n </div>\n }\n\n @if (options.buttons.clear) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ [OperationKeys.DELETE, OperationKeys.READ, OperationKeys.UPDATE].includes(operation) ? 'Back' : options.buttons.clear?.text}}\n </ion-button>\n </div>\n\n }\n </section>\n}\n\n", styles: [".dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (min-width: 577px){.dcf-buttons-grid.dcf-flex{flex-direction:row-reverse}}@media (max-width: 576px){.dcf-buttons-grid.dcf-flex>div{width:100%}.dcf-buttons-grid.dcf-flex>div+div{margin-top:1rem}.dcf-buttons-grid.dcf-flex ion-button{width:100%}}.dcf-form-grid.create,.dcf-form-grid.update{margin-top:var(--dcf-margin-small)}.dcf-form-grid .dcf-form-item{margin-top:0!important}.dcf-form-grid.read .dcf-form-item{margin-bottom:var(--dcf-margin-small)}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: LayoutComponent, selector: "ngx-decaf-layout", inputs: ["gap", "grid", "flexMode", "rowCard", "maxColsLength"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "children", "projectable", "parent"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
6591
6669
  };
6592
6670
  CrudFormComponent = __decorate([
6593
6671
  Dynamic(),
@@ -6595,7 +6673,7 @@ CrudFormComponent = __decorate([
6595
6673
  ], CrudFormComponent);
6596
6674
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: CrudFormComponent, decorators: [{
6597
6675
  type: Component,
6598
- args: [{ standalone: true, selector: 'ngx-decaf-crud-form', imports: [ReactiveFormsModule, LayoutComponent, ComponentRendererComponent, IonButton, IonIcon], host: { '[attr.id]': 'uid' }, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"handleSubmit($event)\"\n novalidate\n [target]=\"target\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n <ngx-decaf-layout\n [className]=\"'dcf-crud-form-grid dcf-grid-nested '\"\n [children]=\"children || []\"\n [parentForm]=\"formGroup || parentForm\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n }\n @if (initialized) {\n <div class=\"dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left\">\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : options.buttons.submit.text}}\n </ion-button>\n </div>\n @if (!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n Back\n </ion-button>\n </div>\n }\n </div>\n }\n\n </form>\n} @else {\n <section [class]=\"'dcf-grid dcf-grid-small dcf-child-width-1-1 dcf-form-grid ' + operation\" #component [id]=\"uid\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n @for (child of children; track $index) {\n <div class=\"dcf-form-item\">\n <ngx-decaf-component-renderer\n [tag]=\"child?.tag\"\n [projectable]=\"false\"\n [children]=\"child?.children || []\"\n [globals]=\"{props: child.props}\"\n />\n </div>\n }\n }\n </section>\n <section [class]=\"'dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if ([OperationKeys.READ, OperationKeys.DELETE].includes(operation) && modelId) {\n <div>\n <ion-button\n (click)=\"handleDelete()\"\n color=\"danger\"\n type=\"button\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n Delete\n </ion-button>\n </div>\n\n }\n @if (operation === OperationKeys.CREATE || operation === OperationKeys.UPDATE) {\n\n <div>\n <ion-button\n type=\"submit\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{options.buttons.submit.text}}\n </ion-button>\n </div>\n }\n\n @if (options.buttons.clear) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ [OperationKeys.DELETE, OperationKeys.READ, OperationKeys.UPDATE].includes(operation) ? 'Back' : options.buttons.clear?.text}}\n </ion-button>\n </div>\n\n }\n </section>\n}\n\n", styles: [".dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (min-width: 577px){.dcf-buttons-grid.dcf-flex{flex-direction:row-reverse}}@media (max-width: 576px){.dcf-buttons-grid.dcf-flex>div{width:100%}.dcf-buttons-grid.dcf-flex>div+div{margin-top:1rem}.dcf-buttons-grid.dcf-flex ion-button{width:100%}}.dcf-form-grid.create,.dcf-form-grid.update{margin-top:var(--dcf-margin-small)}.dcf-form-grid .dcf-form-item{margin-top:0!important}.dcf-form-grid.read .dcf-form-item{margin-bottom:var(--dcf-margin-small)}\n"] }]
6676
+ args: [{ standalone: true, selector: 'ngx-decaf-crud-form', imports: [ReactiveFormsModule, LayoutComponent, ComponentRendererComponent, IonButton, IonIcon], host: { '[attr.id]': 'uid' }, template: "@if (operation !== 'read' && operation !== 'delete') {\n <form\n [class]=\"'dcf-form-grid ' + operation\" #component\n [id]=\"rendererId\"\n [formGroup]=\"formGroup\"\n (ngSubmit)=\"submit($event)\"\n novalidate\n [target]=\"target\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n <ngx-decaf-layout\n [className]=\"'dcf-crud-form-grid dcf-grid-nested '\"\n [children]=\"children || []\"\n [parentForm]=\"formGroup || parentForm\"\n [match]=\"match ?? false\"\n [gap]=\"'small'\"\n [flexMode]=\"props.flexMode || false\"\n [rows]=\"rows\"\n [borders]=\"borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [cols]=\"cols\" />\n }\n @if (initialized) {\n <div class=\"dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left\">\n <div>\n <ion-button type=\"submit\" [expand]=\"action ? 'block' : 'default'\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{ action ? action : options.buttons.submit.text}}\n </ion-button>\n </div>\n @if (!action) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n Back\n </ion-button>\n </div>\n }\n </div>\n }\n\n </form>\n} @else {\n <section [class]=\"'dcf-grid dcf-grid-small dcf-child-width-1-1 dcf-form-grid ' + operation\" #component [id]=\"uid\">\n @if (!children?.length) {\n <ng-content #formContent></ng-content>\n } @else {\n @for (child of children; track $index) {\n <div class=\"dcf-form-item\">\n <ngx-decaf-component-renderer\n [tag]=\"child?.tag\"\n [projectable]=\"false\"\n [children]=\"child?.children || []\"\n [globals]=\"{props: child.props}\"\n />\n </div>\n }\n }\n </section>\n <section [class]=\"'dcf-buttons-grid dcf-grid dcf-grid-small dcf-flex dcf-flex-left ' + operation\" [id]=\"uid\">\n @if ([OperationKeys.READ, OperationKeys.DELETE].includes(operation) && modelId) {\n <div>\n <ion-button\n (click)=\"handleDelete()\"\n color=\"danger\"\n type=\"button\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n Delete\n </ion-button>\n </div>\n\n }\n @if (operation === OperationKeys.CREATE || operation === OperationKeys.UPDATE) {\n\n <div>\n <ion-button\n type=\"submit\">\n @if (options.buttons.submit.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.submit.iconSlot\" [name]=\"options.buttons.submit.icon\"></ion-icon>\n }\n {{options.buttons.submit.text}}\n </ion-button>\n </div>\n }\n\n @if (options.buttons.clear) {\n <div>\n <ion-button fill=\"clear\" (click)=\"handleReset()\">\n @if (options.buttons.clear?.icon) {\n <ion-icon aria-hidden=\"true\" [slot]=\"options.buttons.clear?.iconSlot\" [name]=\"options.buttons.clear?.icon\"></ion-icon>\n }\n {{ [OperationKeys.DELETE, OperationKeys.READ, OperationKeys.UPDATE].includes(operation) ? 'Back' : options.buttons.clear?.text}}\n </ion-button>\n </div>\n\n }\n </section>\n}\n\n", styles: [".dcf-buttons-grid{margin-top:var(--dcf-margin-medium);margin-bottom:var(--dcf-margin)}@media (min-width: 577px){.dcf-buttons-grid.dcf-flex{flex-direction:row-reverse}}@media (max-width: 576px){.dcf-buttons-grid.dcf-flex>div{width:100%}.dcf-buttons-grid.dcf-flex>div+div{margin-top:1rem}.dcf-buttons-grid.dcf-flex ion-button{width:100%}}.dcf-form-grid.create,.dcf-form-grid.update{margin-top:var(--dcf-margin-small)}.dcf-form-grid .dcf-form-item{margin-top:0!important}.dcf-form-grid.read .dcf-form-item{margin-bottom:var(--dcf-margin-small)}\n"] }]
6599
6677
  }], ctorParameters: () => [] });
6600
6678
 
6601
6679
  class NgxSvgDirective {
@@ -7230,6 +7308,7 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
7230
7308
  * @memberOf FieldsetComponent
7231
7309
  */
7232
7310
  async ngOnInit() {
7311
+ console.log(this.title);
7233
7312
  await super.ngOnInit(this.model);
7234
7313
  if (this.max && this.max === 1)
7235
7314
  this.multiple = false;
@@ -7323,6 +7402,29 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
7323
7402
  // this.formGroup = (this.formGroup as FormGroup)
7324
7403
  // this.changeDetectorRef.detectChanges();
7325
7404
  }
7405
+ async refresh() {
7406
+ this.refreshing = true;
7407
+ this.changeDetectorRef.detectChanges();
7408
+ if ([OperationKeys.READ, OperationKeys.DELETE].includes(this.operation)) {
7409
+ // if(!this.multiple) {
7410
+ // this.required = this.collapsable = false;
7411
+ // }
7412
+ this.items = [...this.value.map((v) => {
7413
+ return this.children.map((child) => {
7414
+ const { props, tag } = child;
7415
+ return {
7416
+ tag,
7417
+ props: {
7418
+ ...props,
7419
+ value: v[props.name] || ""
7420
+ }
7421
+ };
7422
+ });
7423
+ })];
7424
+ }
7425
+ this.refreshing = false;
7426
+ this.changeDetectorRef.detectChanges();
7427
+ }
7326
7428
  /**
7327
7429
  * @description Handles removal of the fieldset with slide animation.
7328
7430
  * @summary Initiates the removal process for the fieldset with a smooth slide-up animation.
@@ -7586,7 +7688,7 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
7586
7688
  return child;
7587
7689
  });
7588
7690
  });
7589
- if (this.multiple)
7691
+ if (this.multiple && [OperationKeys.CREATE, OperationKeys.UPDATE].includes(this.operation))
7590
7692
  this.getFormArrayIndex(this.activeFormGroupIndex);
7591
7693
  return this.children;
7592
7694
  }
@@ -7643,7 +7745,7 @@ let FieldsetComponent = class FieldsetComponent extends NgxFormDirective {
7643
7745
  return this.mapper;
7644
7746
  }
7645
7747
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: FieldsetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
7646
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: FieldsetComponent, isStandalone: true, selector: "ngx-decaf-fieldset", inputs: { formControl: "formControl", collapsable: "collapsable", customTypes: "customTypes", title: "title", description: "description", multiple: "multiple", value: "value", borders: "borders", max: "max", required: "required", ordenable: "ordenable", editable: "editable" }, viewQueries: [{ propertyName: "accordionComponent", first: true, predicate: ["accordionComponent"], descendants: true }], usesInheritance: true, ngImport: i0, template: "\n\n<fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.open]=\"isOpen\"\n [class.dcf-not-collapsable]=\"!collapsable\"\n #component>\n <div class=\"dcf-width-1-1\">\n @if (!collapsable || required) {\n <legend class=\"dcf-title\">{{ (title ? title : name) | translate }}</legend>\n }\n <ion-accordion-group class=\"dcf-width-1-1\" [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" [value]=\"(operation === 'read' || !collapsable) ? 'open' : ''\" #accordionComponent>\n <ion-accordion\n value=\"open\"\n [class.dcf-disabled]=\"!activePage\"\n [class.dcf-empty]=\"!items?.length\"\n >\n @if (collapsable && !required) {\n <ion-item slot=\"header\" [button]=\"collapsable\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create', 'update'].includes(operation) && collapsable && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleClear($event)\">\n <ion-icon aria-hidden=\"true\" name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n }\n\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if (activePage) {\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested'\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n </div>\n </ion-accordion>\n </ion-accordion-group>\n\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon aria-hidden=\"true\" name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon aria-hidden=\"true\" class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n }\n\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n\n @if(editable) {\n @if (!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"create-outline\" color=\"dark\" ></ion-icon>\n </ion-button>\n }\n }\n\n\n @if (!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleRemoveItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"close-outline\" color=\"dark\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon aria-hidden=\"true\" name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n @if(max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text class=\"dcf-text-small\"\n [color]=\"items.length !== max ? (!isDarkMode ? 'medium' : '') : 'primary'\"\n >\n {{ locale + (items.length !== max ? '.max_items' : '.max_items_reached') | translate : { '0': max } }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\" [class.dcf-not-collapsable]=\"!collapsable\" [class.dcf-empty]=\"!activePage\" [class.dcf-blank]=\"!borders\">\n @if (updatingItem) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button size=\"small\" fill=\"clear\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"refresh-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.update' | translate }}\n </ion-button>\n </div>\n } @else {\n\n @if (items.length < max || !max) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" [color]=\"isDarkMode ? 'light' : 'dark'\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.add' | translate }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n</fieldset>\n\n", styles: ["ion-accordion ion-item[slot=header] .dcf-delete{width:30px}ion-accordion ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}ion-accordion.dcf-disabled [slot=content]{padding-bottom:0rem!important}ion-accordion.dcf-empty,ion-accordion.dcf-disabled{opacity:1!important}ion-accordion.dcf-empty ::ng-deep .ion-accordion-toggle-icon,ion-accordion.dcf-disabled ::ng-deep .ion-accordion-toggle-icon{display:none!important}ion-accordion.dcf-empty .dcf-delete,ion-accordion.dcf-disabled .dcf-delete{display:none!important}ion-accordion.dcf-empty ion-item[slot=header],ion-accordion.dcf-disabled ion-item[slot=header]{pointer-events:none;cursor:default!important}.dcf-not-collapsable .dcf-max-message-container{margin:.75rem;margin-top:0rem!important}.dcf-not-collapsable .dcf-max-message-container+.dcf-buttons-container{margin-top:var(--dcf-margin-small)!important}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:0rem!important;margin:0!important}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-fieldset-component ion-accordion:not(.dcf-empty){background:var(--dcf-card-background)!important}.dcf-fieldset-component ion-accordion ion-item{--background-hover: transparent !important}.dcf-fieldset-component.read,.dcf-fieldset-component.delete{margin:var(--dcf-margin-small) 0rem!important}.dcf-fieldset-component.read [slot=header],.dcf-fieldset-component.delete [slot=header]{margin-bottom:0rem!important}.dcf-fieldset-component [slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: .65rem;--color: var(--ion-color-text) !important;margin:unset}.dcf-fieldset-component legend,.dcf-fieldset-component .dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-component .dcf-title{padding:.8rem!important}.dcf-fieldset-component [slot=content]{padding:var(--dcf-padding-small) .25rem!important}.dcf-fieldset-component [slot=content]>div{padding-top:.25rem!important}.dcf-fieldset-component:not(.dcf-blank) ion-accordion [slot=header]{margin-top:.125rem}.dcf-fieldset-component .dcf-max-message-container{margin:var(--dcf-padding-small) .75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:var(--dcf-spacement);flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{padding:.25rem var(--dcf-margin-small);margin-bottom:var(--dcf-margin-small)!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.925rem;color:var(--ion-color-gray-4)}.dcf-buttons-container{margin-bottom:0!important;margin-top:-.5rem;padding:0rem .125rem}.dcf-buttons-container:not(.dcf-blank){padding-bottom:var(--dcf-padding-small)!important}.dcf-buttons-container.dcf-not-collapsable.dcf-empty{position:relative;top:-1rem!important}@media (max-width: 480px){.dcf-buttons-container{flex-direction:column-reverse;gap:.5rem;align-items:stretch}.dcf-buttons-container ion-button{width:100%;justify-content:center;height:40px}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: IonAccordionGroup, selector: "ion-accordion-group", inputs: ["animated", "disabled", "expand", "mode", "multiple", "readonly", "value"] }, { kind: "component", type: IonAccordion, selector: "ion-accordion", inputs: ["disabled", "mode", "readonly", "toggleIcon", "toggleIconSlot", "value"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonReorder, selector: "ion-reorder" }, { kind: "component", type: IonReorderGroup, selector: "ion-reorder-group", inputs: ["disabled"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: LayoutComponent, selector: "ngx-decaf-layout", inputs: ["gap", "grid", "flexMode", "rowCard", "maxColsLength"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
7748
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: FieldsetComponent, isStandalone: true, selector: "ngx-decaf-fieldset", inputs: { formControl: "formControl", collapsable: "collapsable", customTypes: "customTypes", title: "title", description: "description", multiple: "multiple", value: "value", borders: "borders", max: "max", required: "required", ordenable: "ordenable", editable: "editable" }, viewQueries: [{ propertyName: "accordionComponent", first: true, predicate: ["accordionComponent"], descendants: true }], usesInheritance: true, ngImport: i0, template: "\n\n <fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.open]=\"isOpen\"\n [class.dcf-not-collapsable]=\"!collapsable\"\n #component>\n <div class=\"dcf-width-1-1\">\n @if (!collapsable || required) {\n <legend class=\"dcf-title\">{{ (title ? title : name) | translate }}</legend>\n }\n <ion-accordion-group class=\"dcf-width-1-1\" [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" [value]=\"(operation === 'read' || !collapsable) ? 'open' : ''\" #accordionComponent>\n <ion-accordion\n value=\"open\"\n [class.dcf-disabled]=\"!activePage\"\n [class.dcf-empty]=\"!items?.length\"\n >\n @if (collapsable && !required) {\n <ion-item slot=\"header\" [button]=\"collapsable\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create', 'update'].includes(operation) && collapsable && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleClear($event)\">\n <ion-icon aria-hidden=\"true\" name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n }\n\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if (['create', 'update'].includes(operation) || !multiple) {\n @if(activePage) {\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested'\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n } @else {\n @if(refreshing) {\n <div class=\"dcf-loading-container\">\n <ion-spinner name=\"crescent\" color=\"primary\"></ion-spinner>\n </div>\n } @else {\n @if(!items.length) {\n <div class=\"dcf-padding-xsmall\">\n <ion-text class=\"dcf-text-small\">{{ locale + '.empty' | translate }}</ion-text>\n </div>\n } @else {\n @for(item of items; track trackItemFn($index, item)) {\n <div class=\"dcf-fieldset-item\">\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested ' + operation\"\n [flexMode]=\"item?.props?.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'collapse'\"\n [children]=\"item || []\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"item?.props?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n />\n </div>\n </div>\n }\n }\n }\n }\n </div>\n </ion-accordion>\n </ion-accordion-group>\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon aria-hidden=\"true\" name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon aria-hidden=\"true\" class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n }\n\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n\n @if(editable) {\n @if (!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"create-outline\" color=\"dark\" ></ion-icon>\n </ion-button>\n }\n }\n\n\n @if (!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleRemoveItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"close-outline\" color=\"dark\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon aria-hidden=\"true\" name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n\n @if(max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text class=\"dcf-text-small\"\n [color]=\"items.length !== max ? (!isDarkMode ? 'medium' : '') : 'primary'\"\n >\n {{ locale + (items.length !== max ? '.max_items' : '.max_items_reached') | translate : { '0': max } }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\" [class.dcf-not-collapsable]=\"!collapsable\" [class.dcf-empty]=\"!activePage\" [class.dcf-blank]=\"!borders\">\n @if (updatingItem) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button size=\"small\" fill=\"clear\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"refresh-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.update' | translate }}\n </ion-button>\n </div>\n } @else {\n @if (items.length < max || !max) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" [color]=\"isDarkMode ? 'light' : 'dark'\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.add' | translate }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n </fieldset>\n\n\n", styles: [".dcf-fieldset-item{border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);padding:var(--dcf-padding-small) var(--dcf-padding-xsmall);padding-bottom:0;margin-bottom:var(--dcf-margin-small)}.dcf-loading-container{height:50%;display:flex;justify-content:center;align-items:center}.dcf-loading-container ion-spinner{width:30px;height:30px}ion-accordion{background:transparent!important;--background: transparent !important}ion-accordion ion-item[slot=header] .dcf-delete{width:30px}ion-accordion ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}ion-accordion.dcf-disabled [slot=content]{padding-bottom:0rem!important}ion-accordion.dcf-empty,ion-accordion.dcf-disabled{opacity:1!important}ion-accordion.dcf-empty ::ng-deep .ion-accordion-toggle-icon,ion-accordion.dcf-disabled ::ng-deep .ion-accordion-toggle-icon{display:none!important}ion-accordion.dcf-empty .dcf-delete,ion-accordion.dcf-disabled .dcf-delete{display:none!important}ion-accordion.dcf-empty ion-item[slot=header],ion-accordion.dcf-disabled ion-item[slot=header]{pointer-events:none;cursor:default!important}.dcf-not-collapsable .dcf-max-message-container{margin:.75rem;margin-top:0rem!important}.dcf-not-collapsable .dcf-max-message-container+.dcf-buttons-container{margin-top:var(--dcf-margin-small)!important}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:0rem!important;margin:0!important}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-fieldset-component ion-accordion ion-item{--background-hover: transparent !important}.dcf-fieldset-component.read,.dcf-fieldset-component.delete{margin:var(--dcf-margin-small) 0rem!important}.dcf-fieldset-component.read [slot=header],.dcf-fieldset-component.delete [slot=header]{margin-bottom:0rem!important}.dcf-fieldset-component [slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: .65rem;--color: var(--ion-color-text) !important;margin:unset}.dcf-fieldset-component legend,.dcf-fieldset-component .dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-component .dcf-title{padding:.8rem!important}.dcf-fieldset-component [slot=content]{padding:var(--dcf-padding-small) .25rem!important;background:transparent!important;--background: transparent !important}.dcf-fieldset-component [slot=content]>div{padding-top:.25rem!important}.dcf-fieldset-component:not(.dcf-blank) ion-accordion [slot=header]{margin-top:.125rem}.dcf-fieldset-component .dcf-max-message-container{margin:var(--dcf-padding-small) .75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:var(--dcf-spacement);flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{padding:.25rem var(--dcf-margin-small);margin-bottom:var(--dcf-margin-small)!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.925rem;color:var(--ion-color-gray-4)}.dcf-buttons-container{margin-bottom:0!important;margin-top:-.5rem;padding:0rem .125rem}.dcf-buttons-container:not(.dcf-blank){padding-bottom:var(--dcf-padding-small)!important}.dcf-buttons-container.dcf-not-collapsable.dcf-empty{position:relative;top:-1rem!important}@media (max-width: 480px){.dcf-buttons-container{flex-direction:column-reverse;gap:.5rem;align-items:stretch}.dcf-buttons-container ion-button{width:100%;justify-content:center;height:40px}}\n"], dependencies: [{ kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: IonAccordionGroup, selector: "ion-accordion-group", inputs: ["animated", "disabled", "expand", "mode", "multiple", "readonly", "value"] }, { kind: "component", type: IonAccordion, selector: "ion-accordion", inputs: ["disabled", "mode", "readonly", "toggleIcon", "toggleIconSlot", "value"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonReorder, selector: "ion-reorder" }, { kind: "component", type: IonReorderGroup, selector: "ion-reorder-group", inputs: ["disabled"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: LayoutComponent, selector: "ngx-decaf-layout", inputs: ["gap", "grid", "flexMode", "rowCard", "maxColsLength"] }, { kind: "component", type: IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
7647
7749
  };
7648
7750
  FieldsetComponent = __decorate([
7649
7751
  Dynamic(),
@@ -7665,7 +7767,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
7665
7767
  IonButton,
7666
7768
  IonIcon,
7667
7769
  LayoutComponent,
7668
- ], template: "\n\n<fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.open]=\"isOpen\"\n [class.dcf-not-collapsable]=\"!collapsable\"\n #component>\n <div class=\"dcf-width-1-1\">\n @if (!collapsable || required) {\n <legend class=\"dcf-title\">{{ (title ? title : name) | translate }}</legend>\n }\n <ion-accordion-group class=\"dcf-width-1-1\" [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" [value]=\"(operation === 'read' || !collapsable) ? 'open' : ''\" #accordionComponent>\n <ion-accordion\n value=\"open\"\n [class.dcf-disabled]=\"!activePage\"\n [class.dcf-empty]=\"!items?.length\"\n >\n @if (collapsable && !required) {\n <ion-item slot=\"header\" [button]=\"collapsable\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create', 'update'].includes(operation) && collapsable && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleClear($event)\">\n <ion-icon aria-hidden=\"true\" name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n }\n\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if (activePage) {\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested'\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n </div>\n </ion-accordion>\n </ion-accordion-group>\n\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon aria-hidden=\"true\" name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon aria-hidden=\"true\" class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n }\n\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n\n @if(editable) {\n @if (!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"create-outline\" color=\"dark\" ></ion-icon>\n </ion-button>\n }\n }\n\n\n @if (!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleRemoveItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"close-outline\" color=\"dark\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon aria-hidden=\"true\" name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n @if(max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text class=\"dcf-text-small\"\n [color]=\"items.length !== max ? (!isDarkMode ? 'medium' : '') : 'primary'\"\n >\n {{ locale + (items.length !== max ? '.max_items' : '.max_items_reached') | translate : { '0': max } }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\" [class.dcf-not-collapsable]=\"!collapsable\" [class.dcf-empty]=\"!activePage\" [class.dcf-blank]=\"!borders\">\n @if (updatingItem) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button size=\"small\" fill=\"clear\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"refresh-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.update' | translate }}\n </ion-button>\n </div>\n } @else {\n\n @if (items.length < max || !max) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" [color]=\"isDarkMode ? 'light' : 'dark'\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.add' | translate }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n</fieldset>\n\n", styles: ["ion-accordion ion-item[slot=header] .dcf-delete{width:30px}ion-accordion ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}ion-accordion.dcf-disabled [slot=content]{padding-bottom:0rem!important}ion-accordion.dcf-empty,ion-accordion.dcf-disabled{opacity:1!important}ion-accordion.dcf-empty ::ng-deep .ion-accordion-toggle-icon,ion-accordion.dcf-disabled ::ng-deep .ion-accordion-toggle-icon{display:none!important}ion-accordion.dcf-empty .dcf-delete,ion-accordion.dcf-disabled .dcf-delete{display:none!important}ion-accordion.dcf-empty ion-item[slot=header],ion-accordion.dcf-disabled ion-item[slot=header]{pointer-events:none;cursor:default!important}.dcf-not-collapsable .dcf-max-message-container{margin:.75rem;margin-top:0rem!important}.dcf-not-collapsable .dcf-max-message-container+.dcf-buttons-container{margin-top:var(--dcf-margin-small)!important}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:0rem!important;margin:0!important}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-fieldset-component ion-accordion:not(.dcf-empty){background:var(--dcf-card-background)!important}.dcf-fieldset-component ion-accordion ion-item{--background-hover: transparent !important}.dcf-fieldset-component.read,.dcf-fieldset-component.delete{margin:var(--dcf-margin-small) 0rem!important}.dcf-fieldset-component.read [slot=header],.dcf-fieldset-component.delete [slot=header]{margin-bottom:0rem!important}.dcf-fieldset-component [slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: .65rem;--color: var(--ion-color-text) !important;margin:unset}.dcf-fieldset-component legend,.dcf-fieldset-component .dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-component .dcf-title{padding:.8rem!important}.dcf-fieldset-component [slot=content]{padding:var(--dcf-padding-small) .25rem!important}.dcf-fieldset-component [slot=content]>div{padding-top:.25rem!important}.dcf-fieldset-component:not(.dcf-blank) ion-accordion [slot=header]{margin-top:.125rem}.dcf-fieldset-component .dcf-max-message-container{margin:var(--dcf-padding-small) .75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:var(--dcf-spacement);flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{padding:.25rem var(--dcf-margin-small);margin-bottom:var(--dcf-margin-small)!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.925rem;color:var(--ion-color-gray-4)}.dcf-buttons-container{margin-bottom:0!important;margin-top:-.5rem;padding:0rem .125rem}.dcf-buttons-container:not(.dcf-blank){padding-bottom:var(--dcf-padding-small)!important}.dcf-buttons-container.dcf-not-collapsable.dcf-empty{position:relative;top:-1rem!important}@media (max-width: 480px){.dcf-buttons-container{flex-direction:column-reverse;gap:.5rem;align-items:stretch}.dcf-buttons-container ion-button{width:100%;justify-content:center;height:40px}}\n"] }]
7770
+ IonSpinner
7771
+ ], template: "\n\n <fieldset\n (fieldsetAddGroupEvent)=\"handleCreateItem($event)\"\n [class]=\"'dcf-fieldset-component ' + operation\"\n [class.dcf-blank]=\"!borders\"\n [class.open]=\"isOpen\"\n [class.dcf-not-collapsable]=\"!collapsable\"\n #component>\n <div class=\"dcf-width-1-1\">\n @if (!collapsable || required) {\n <legend class=\"dcf-title\">{{ (title ? title : name) | translate }}</legend>\n }\n <ion-accordion-group class=\"dcf-width-1-1\" [class.open]=\"isOpen\" [class.hasValidationErrors]=\"hasValidationErrors\" [value]=\"(operation === 'read' || !collapsable) ? 'open' : ''\" #accordionComponent>\n <ion-accordion\n value=\"open\"\n [class.dcf-disabled]=\"!activePage\"\n [class.dcf-empty]=\"!items?.length\"\n >\n @if (collapsable && !required) {\n <ion-item slot=\"header\" [button]=\"collapsable\" (click)=\"handleAccordionToggle($event)\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-width-1-1\">\n <div class=\"dcf-width-expand\">\n <legend>{{ (title ? title : name) | translate }}</legend>\n </div>\n @if (!isRequired && ['create', 'update'].includes(operation) && collapsable && multiple) {\n <div class=\"dcf-width-auto dcf-delete\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleClear($event)\">\n <ion-icon aria-hidden=\"true\" name=\"trash-outline\" color=\"dark\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n </div>\n </ion-item>\n }\n\n <div slot=\"content\" [attr.aria-hidden]=\"!isOpen\">\n @if (['create', 'update'].includes(operation) || !multiple) {\n @if(activePage) {\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested'\"\n [flexMode]=\"props.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'small'\"\n [children]=\"activePage || []\"\n [parentForm]=\"formGroup || parentForm\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"activePage?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n [hidden]=\"items.length === max && !updatingItem\"\n />\n </div>\n }\n } @else {\n @if(refreshing) {\n <div class=\"dcf-loading-container\">\n <ion-spinner name=\"crescent\" color=\"primary\"></ion-spinner>\n </div>\n } @else {\n @if(!items.length) {\n <div class=\"dcf-padding-xsmall\">\n <ion-text class=\"dcf-text-small\">{{ locale + '.empty' | translate }}</ion-text>\n </div>\n } @else {\n @for(item of items; track trackItemFn($index, item)) {\n <div class=\"dcf-fieldset-item\">\n <div>\n <ngx-decaf-layout\n [className]=\"'dcf-fieldset-grid dcf-grid-nested ' + operation\"\n [flexMode]=\"item?.props?.flexMode ?? false\"\n [match]=\"false\"\n [gap]=\"'collapse'\"\n [children]=\"item || []\"\n [rows]=\"rows\"\n [cols]=\"cols\"\n [borders]=\"item?.props?.borders ?? false\"\n [breakpoint]=\"breakpoint ?? 'large'\"\n />\n </div>\n </div>\n }\n }\n }\n }\n </div>\n </ion-accordion>\n </ion-accordion-group>\n @if (multiple && ['create', 'update'].includes(operation)) {\n @if (multiple && items.length) {\n <ion-list class=\"dcf-fields-list\">\n <ion-reorder-group [formGroup]=\"formGroup.parent\" [disabled]=\"updatingItem\" (ionItemReorder)=\"handleReorderItems($any($event))\" #accordionComponent>\n @for(item of items; track item.index) {\n <ion-item [class.not-unique]=\"item.title === isUniqueError\" [class.updating]=\"updatingItem?.[pk] === item.title\" lines=\"full\" [button]=\"false\">\n @if(ordenable) {\n @if (items?.length > 1 && !updatingItem) {\n <ion-reorder slot=\"start\">\n <ion-icon aria-hidden=\"true\" name=\"swap-vertical-outline\"></ion-icon>\n </ion-reorder>\n } @else {\n <div slot=\"start\">\n <ion-icon aria-hidden=\"true\" class=\"dcf-reorder-disabled\" size=\"small\" name=\"swap-vertical-outline\" disabled></ion-icon>\n </div>\n }\n }\n\n <ion-label [color]=\"(item.title === isUniqueError && !updatingItem?.[pk] === item.title) ? 'danger' : ''\">{{ item.index }}. {{ item.title }}\n @if (item.description?.length > 0) {\n <br />\n <ion-text class=\"dcf-subtitle\">{{item.description}}</ion-text>\n }\n </ion-label>\n\n @if(editable) {\n @if (!updatingItem || updatingItem?.[pk] !== item.title) {\n <ion-button fill=\"clear\" size=\"small\" (click)=\"handleUpdateItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"create-outline\" color=\"dark\" ></ion-icon>\n </ion-button>\n }\n }\n\n\n @if (!updatingItem) {\n <ion-button fill=\"clear\" size=\"small\" color=\"danger\" (click)=\"handleRemoveItem($index)\">\n <ion-icon aria-hidden=\"true\" name=\"close-outline\" color=\"dark\"></ion-icon>\n </ion-button>\n }\n </ion-item>\n }\n </ion-reorder-group>\n </ion-list>\n }\n\n @if (isUniqueError) {\n <div class=\"dcf-not-unique-container dcf-animation dcf-animation-bottom-small dcf-animation-fast\">\n <div class=\" dcf-grid dcf-grid-collapse dcf-width-1-1 \">\n <div class=\"dcf-auto\" [attr.style]=\"'max-width: 50px'\">\n <ion-icon aria-hidden=\"true\" name=\"alert-circle-outline\"></ion-icon>\n </div>\n <div class=\"dcf-width-expand\">\n <ion-text color=\"danger\" class=\"dcf-text-small\">{{ locale + '.not_unique' | translate : { value: isUniqueError } }}</ion-text>\n </div>\n </div>\n </div>\n }\n\n @if(max) {\n <div class=\"dcf-width-1-1 dcf-max-message-container\">\n <ion-text class=\"dcf-text-small\"\n [color]=\"items.length !== max ? (!isDarkMode ? 'medium' : '') : 'primary'\"\n >\n {{ locale + (items.length !== max ? '.max_items' : '.max_items_reached') | translate : { '0': max } }}\n </ion-text>\n </div>\n }\n\n <div class=\"dcf-grid dcf-grid-small dcf-flex dcf-buttons-container\" [class.dcf-not-collapsable]=\"!collapsable\" [class.dcf-empty]=\"!activePage\" [class.dcf-blank]=\"!borders\">\n @if (updatingItem) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" color=\"danger\" (click)=\"handleCancelUpdateItem()\">\n {{ locale + '.cancel' | translate }}\n </ion-button>\n </div>\n <div>\n <ion-button size=\"small\" fill=\"clear\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"refresh-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.update' | translate }}\n </ion-button>\n </div>\n } @else {\n @if (items.length < max || !max) {\n <div>\n <ion-button size=\"small\" fill=\"clear\" class=\"dcf-button-add\" [color]=\"isDarkMode ? 'light' : 'dark'\" (click)=\"handleCreateItem()\">\n <ion-icon aria-hidden=\"true\" name=\"add-outline\" slot=\"start\"></ion-icon>\n {{ locale + '.add' | translate }}\n </ion-button>\n </div>\n }\n }\n </div>\n }\n </div>\n </fieldset>\n\n\n", styles: [".dcf-fieldset-item{border:1px solid var(--dcf-color-gray-3);border-radius:var(--dcf-border-radius-small);padding:var(--dcf-padding-small) var(--dcf-padding-xsmall);padding-bottom:0;margin-bottom:var(--dcf-margin-small)}.dcf-loading-container{height:50%;display:flex;justify-content:center;align-items:center}.dcf-loading-container ion-spinner{width:30px;height:30px}ion-accordion{background:transparent!important;--background: transparent !important}ion-accordion ion-item[slot=header] .dcf-delete{width:30px}ion-accordion ion-item[slot=header] .dcf-delete ion-button{transform:translateY(-2px)}ion-accordion ion-item[slot=header] .dcf-delete ion-icon{font-size:1.15rem}ion-accordion.dcf-disabled [slot=content]{padding-bottom:0rem!important}ion-accordion.dcf-empty,ion-accordion.dcf-disabled{opacity:1!important}ion-accordion.dcf-empty ::ng-deep .ion-accordion-toggle-icon,ion-accordion.dcf-disabled ::ng-deep .ion-accordion-toggle-icon{display:none!important}ion-accordion.dcf-empty .dcf-delete,ion-accordion.dcf-disabled .dcf-delete{display:none!important}ion-accordion.dcf-empty ion-item[slot=header],ion-accordion.dcf-disabled ion-item[slot=header]{pointer-events:none;cursor:default!important}.dcf-not-collapsable .dcf-max-message-container{margin:.75rem;margin-top:0rem!important}.dcf-not-collapsable .dcf-max-message-container+.dcf-buttons-container{margin-top:var(--dcf-margin-small)!important}.dcf-fieldset-component{border-radius:var(--dcf-border-radius-small);border:1px solid var(--dcf-color-gray-3)}.dcf-fieldset-component.dcf-blank{border-color:transparent;padding:0rem!important;margin:0!important}.dcf-fieldset-component *{overflow-x:hidden!important}.dcf-fieldset-component ion-accordion ion-item{--background-hover: transparent !important}.dcf-fieldset-component.read,.dcf-fieldset-component.delete{margin:var(--dcf-margin-small) 0rem!important}.dcf-fieldset-component.read [slot=header],.dcf-fieldset-component.delete [slot=header]{margin-bottom:0rem!important}.dcf-fieldset-component [slot=header]{--border-color: transparent;--border-radius: 6px;--inner-border-width: 0;--padding-start: .65rem;--color: var(--ion-color-text) !important;margin:unset}.dcf-fieldset-component legend,.dcf-fieldset-component .dcf-title{font-weight:500;font-size:1rem;line-height:1.5rem;font-weight:600;margin:0;color:var(--ion-color-text)!important}.dcf-fieldset-component .dcf-title{padding:.8rem!important}.dcf-fieldset-component [slot=content]{padding:var(--dcf-padding-small) .25rem!important;background:transparent!important;--background: transparent !important}.dcf-fieldset-component [slot=content]>div{padding-top:.25rem!important}.dcf-fieldset-component:not(.dcf-blank) ion-accordion [slot=header]{margin-top:.125rem}.dcf-fieldset-component .dcf-max-message-container{margin:var(--dcf-padding-small) .75rem}.dcf-not-unique-container{display:flex;justify-content:center;align-items:center;margin-bottom:var(--dcf-spacement);flex:1 1 auto}.dcf-not-unique-container>div{display:flex;justify-content:center;align-items:center}.dcf-not-unique-container ion-icon{transform:translatey(2px);margin-right:5px}.dcf-fields-list{padding:.25rem var(--dcf-margin-small);margin-bottom:var(--dcf-margin-small)!important}.dcf-fields-list ion-item{--min-height: 50px;--padding-top: .25rem;--padding-bottom: .25rem;--padding-start: .75rem;--padding-end: .75rem;--inner-padding-start: 0px !important;--inner-padding-end: 0px !important;--border-color: var(--dcf-color-gray-2) !important}.dcf-fields-list ion-item ion-icon.dcf-reorder-disabled{width:var(--dcf-spacement);transform:translatey(2px);color:var(--dcf-color-gray-4)}.dcf-fields-list ion-item.updating{--background: rgba(var(--dcf-color-primary-rgb), .1) !important}.dcf-fields-list ion-item.not-unique{--background: rgba(var(--dcf-color-danger-rgb), .05) !important}.dcf-fields-list ion-item .dcf-subtitle{font-size:.925rem;color:var(--ion-color-gray-4)}.dcf-buttons-container{margin-bottom:0!important;margin-top:-.5rem;padding:0rem .125rem}.dcf-buttons-container:not(.dcf-blank){padding-bottom:var(--dcf-padding-small)!important}.dcf-buttons-container.dcf-not-collapsable.dcf-empty{position:relative;top:-1rem!important}@media (max-width: 480px){.dcf-buttons-container{flex-direction:column-reverse;gap:.5rem;align-items:stretch}.dcf-buttons-container ion-button{width:100%;justify-content:center;height:40px}}\n"] }]
7669
7772
  }], ctorParameters: () => [], propDecorators: { accordionComponent: [{
7670
7773
  type: ViewChild,
7671
7774
  args: ['accordionComponent', { static: false }]
@@ -8238,7 +8341,7 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8238
8341
  * @memberOf FilterComponent
8239
8342
  */
8240
8343
  constructor() {
8241
- super("FilterComponent");
8344
+ super('FilterComponent');
8242
8345
  /**
8243
8346
  * @description Available field indexes for filtering operations.
8244
8347
  * @summary Defines the list of field names that users can filter by. These represent
@@ -8261,7 +8364,14 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8261
8364
  * @default []
8262
8365
  * @memberOf FilterComponent
8263
8366
  */
8264
- this.conditions = ['Equal', 'Contains', 'Not Contains', 'Greater Than', 'Less Than', 'Not Equal'];
8367
+ this.conditions = [
8368
+ 'Equal',
8369
+ 'Contains',
8370
+ 'Not Contains',
8371
+ 'Greater Than',
8372
+ 'Less Than',
8373
+ 'Not Equal',
8374
+ ];
8265
8375
  /**
8266
8376
  * @description Available sorting options for the filtered data.
8267
8377
  * @summary Defines the list of field names that can be used for sorting the filtered results.
@@ -8394,7 +8504,15 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8394
8504
  * @memberOf FilterComponent
8395
8505
  */
8396
8506
  this.searchEvent = new EventEmitter();
8397
- addIcons({ chevronDownOutline, trashOutline, closeOutline, searchOutline, arrowDownOutline, arrowUpOutline, chevronUpOutline });
8507
+ addIcons({
8508
+ chevronDownOutline,
8509
+ trashOutline,
8510
+ closeOutline,
8511
+ searchOutline,
8512
+ arrowDownOutline,
8513
+ arrowUpOutline,
8514
+ chevronUpOutline,
8515
+ });
8398
8516
  }
8399
8517
  /**
8400
8518
  * @description Initializes the component after Angular first displays the data-bound properties.
@@ -8443,11 +8561,13 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8443
8561
  */
8444
8562
  getIndexes() {
8445
8563
  if (this.model)
8446
- this.indexes = Object.keys(Repository.indexes(this.model) || {});
8564
+ this.indexes = Object.keys(Model.indexes(this.model) || {});
8447
8565
  if (!this.disableSort) {
8448
8566
  this.sortBy = [...this.sortBy, ...this.indexes];
8449
- if (this.repository)
8450
- this.sortValue = this.repository.pk || this.sortValue;
8567
+ if (this.repository) {
8568
+ const pk = Model.pk(this.repository.class);
8569
+ this.sortValue = pk || this.sortValue;
8570
+ }
8451
8571
  }
8452
8572
  }
8453
8573
  /**
@@ -8579,13 +8699,13 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8579
8699
  *
8580
8700
  * @memberOf FilterComponent
8581
8701
  */
8582
- addFilter(value, event) {
8702
+ async addFilter(value, event) {
8583
8703
  value = value.trim();
8584
8704
  if (event instanceof KeyboardEvent && !value) {
8585
8705
  this.submit();
8586
8706
  }
8587
8707
  else {
8588
- if ((value && (!(event instanceof KeyboardEvent)) || this.step === 3)) {
8708
+ if ((value && !(event instanceof KeyboardEvent)) || this.step === 3) {
8589
8709
  const filter = this.lastFilter;
8590
8710
  switch (this.step) {
8591
8711
  case 1:
@@ -8613,7 +8733,7 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8613
8733
  this.filterValue[this.filterValue.length - 1] = filter;
8614
8734
  this.lastFilter = {};
8615
8735
  if (!this.multiple)
8616
- return this.submit();
8736
+ return await this.submit();
8617
8737
  }
8618
8738
  this.step++;
8619
8739
  this.value = '';
@@ -8647,7 +8767,8 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8647
8767
  * @memberOf FilterComponent
8648
8768
  */
8649
8769
  allowClear(option) {
8650
- return this.indexes.indexOf(option) === -1 && this.conditions.indexOf(option) === -1;
8770
+ return (this.indexes.indexOf(option) === -1 &&
8771
+ this.conditions.indexOf(option) === -1);
8651
8772
  }
8652
8773
  /**
8653
8774
  * @description Removes a complete filter from the collection based on filter value.
@@ -8676,11 +8797,11 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8676
8797
  function cleanString(filter) {
8677
8798
  return filter
8678
8799
  .toLowerCase() // convert all characters to lowercase
8679
- .normalize("NFD") // separate accent marks from characters
8680
- .replace(/[\u0300-\u036f]/g, "") // remove accent marks
8681
- .replace(/\s+/g, ""); // remove all whitespace
8800
+ .normalize('NFD') // separate accent marks from characters
8801
+ .replace(/[\u0300-\u036f]/g, '') // remove accent marks
8802
+ .replace(/\s+/g, ''); // remove all whitespace
8682
8803
  }
8683
- this.value = "";
8804
+ this.value = '';
8684
8805
  this.filterValue = this.filterValue.filter((item) => item?.['value'] && cleanString(item?.['value']) !== cleanString(filter));
8685
8806
  if (this.filterValue.length === 0) {
8686
8807
  this.step = 1;
@@ -8725,16 +8846,16 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8725
8846
  * @summary Emits the current filter array to parent components when filters are ready
8726
8847
  * to be applied. Only emits if there are active filters. Clears options after submission.
8727
8848
  *
8728
- * @returns {void}
8849
+ * @returns {Promise<void>}
8729
8850
  * @memberOf FilterComponent
8730
8851
  */
8731
- submit() {
8852
+ async submit() {
8732
8853
  this.filterEvent.emit({
8733
8854
  query: this.filterValue.length > 0 ? this.filterValue : undefined,
8734
8855
  sort: {
8735
8856
  value: this.sortValue,
8736
- direction: this.sortDirection
8737
- }
8857
+ direction: this.sortDirection,
8858
+ },
8738
8859
  });
8739
8860
  if (this.filterValue.length === 0)
8740
8861
  this.options = [];
@@ -8749,7 +8870,9 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8749
8870
  * @memberOf FilterComponent
8750
8871
  */
8751
8872
  handleSortDirectionChange() {
8752
- const direction = this.sortDirection === OrderDirection.ASC ? OrderDirection.DSC : OrderDirection.ASC;
8873
+ const direction = this.sortDirection === OrderDirection.ASC
8874
+ ? OrderDirection.DSC
8875
+ : OrderDirection.ASC;
8753
8876
  if (direction !== this.sortDirection) {
8754
8877
  this.sortDirection = direction;
8755
8878
  this.submit();
@@ -8811,7 +8934,9 @@ let FilterComponent = class FilterComponent extends NgxComponentDirective {
8811
8934
  }
8812
8935
  const options = optionsElement.querySelectorAll('.dcf-item');
8813
8936
  for (const option of options) {
8814
- const isActive = option.textContent?.toLowerCase().includes(value.toLowerCase());
8937
+ const isActive = option.textContent
8938
+ ?.toLowerCase()
8939
+ .includes(value.toLowerCase());
8815
8940
  if (isActive) {
8816
8941
  option.classList.add('dcf-filtering-item');
8817
8942
  break;
@@ -8850,7 +8975,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
8850
8975
  IonSelect,
8851
8976
  IonSelectOption,
8852
8977
  IonIcon,
8853
- SearchbarComponent
8978
+ SearchbarComponent,
8854
8979
  ], standalone: true, host: { '[attr.id]': 'uid' }, template: "\n@if (!indexes.length) {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n}\n\n<div [id]=\"uid\" class=\"dcf-grid dcf-grid-small dcf-grid-match dcf-filter-component\" [class.dcf-hidden]=\"!indexes.length\" #component>\n <div class=\"dcf-width-expand\">\n <div class=\"dcf-filter\">\n <div class=\"dcf-input\">\n @for(filter of filterValue; track trackItemFn($index, filter?.['index'])) {\n @if (filter?.['index']) {\n <ion-chip [outline]=\"true\">{{ filter?.['index'] }}</ion-chip>\n }\n @if (filter?.['condition']) {\n <ion-chip [outline]=\"true\">{{ filter?.['condition'] }}</ion-chip>\n }\n @if (filter?.['value']) {\n <ion-chip [outline]=\"true\" class=\"dcf-filter-value\">\n {{ filter?.['value'] }}\n <ion-icon tabindex=\"0\" name=\"close-outline\" (click)=\"removeFilter(filter?.['value'])\" size=\"small\"></ion-icon>\n </ion-chip>\n }\n }\n <div class=\"dcf-width-1-1\">\n <!-- [readonly]=\"step !== 3\" -->\n <input\n fill=\"none\"\n [(ngModel)]=\"value\"\n (keydown.enter)=\"addFilter(value, $event)\"\n (keydown.backspace)=\"clear(value)\"\n (input)=\"handleInput($event)\"\n (click)=\"handleFocus()\"\n (blur)=\"handleBlur()\"\n type=\"text\"\n id=\"dcf-filter-field\"\n placeholder=\"{{ locale + (step === 3 ? '.type' : '.select') | translate }}\"\n\n />\n @if (windowWidth >= 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if (filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n </div>\n @if (filterValue.length > 0) {\n <div class=\"dcf-icon-clear\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"clear()\">\n <ion-icon aria-hidden=\"true\" name=\"trash-outline\" [color]=\"!isDarkMode ? 'dark' : 'light'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n }\n <div class=\"dcf-icon-search\">\n <ion-button fill=\"clear\" size=\"small\" (click)=\"submit()\">\n <ion-icon aria-hidden=\"true\" name=\"search-outline\" [color]=\"!isDarkMode ? 'dark' : 'light'\" slot=\"icon-only\"></ion-icon>\n </ion-button>\n </div>\n </div>\n @if (windowWidth < 768) {\n <div [class]=\"'dcf-dropdown ' + (options.length > 0 ? ' dcf-active' : '')\" #optionsFilterElement>\n <div>\n @if (filteredOptions.length > 0) {\n @for(key of filteredOptions; track key) {\n <div\n class=\"dcf-item\"\n tabindex=\"0\"\n (keydown.enter)=\"selectOption(key)\"\n (click)=\"selectOption(key)\">\n {{ key }}\n </div>\n }\n } @else {\n <div class=\"dcf-empty\"\n (click)=\"filteredOptions = options; value = ''\"\n tabindex=\"0\"\n (keydown.enter)=\"filteredOptions = options; value = ''\"\n >\n {{ locale + '.no_suggestions' | translate }}\n </div>\n }\n </div>\n </div>\n }\n </div>\n @if (!disableSort) {\n <div class=\"dcf-width-1-5@m dcf-width-1-1 dcf-sort-container\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-flex dcf-flex-middle dcf-grid-match\">\n <div class=\"dcf-width-expand\">\n <ion-select\n toggleIcon=\"chevron-down-outline\"\n expandedIcon=\"chevron-up-outline\"\n class=\"dcf-sort-select\"\n (ionChange)=\"handleSortChange($event)\"\n interface=\"popover\"\n [value]=\"sortValue\"\n label-placement=\"floating\"\n fill=\"outline\"\n [label]=\"locale + '.sort' | translate\"\n >\n @for(sort of sortBy; track sort) {\n\n <ion-select-option [value]=\"sort\">{{ sort | translate }}</ion-select-option>\n }\n </ion-select>\n </div>\n <div class=\"dcf-width-auto\">\n <ion-button (click)=\"handleSortDirectionChange()\" fill=\"clear\">\n <ion-icon aria-hidden=\"true\" slot=\"icon-only\" [color]=\"!isDarkMode ? 'primary' : 'light'\" [name]=\"sortDirection === 'desc' ? 'arrow-down-outline' : 'arrow-up-outline'\"></ion-icon>\n </ion-button>\n </div>\n </div>\n </div>\n }\n</div>\n\n\n", styles: [":host{position:relative;z-index:1000!important}:host *{z-index:1000!important}.dcf-filter-component{padding:0 .5rem;margin-top:.75rem;margin-bottom:.75rem}.dcf-filter-component:not(.dcf-palette-dark) .dcf-filter{border:1px solid var(--dcf-color-gray-3);background-color:#fff}.dcf-filter-component:not(.dcf-palette-dark) .dcf-filter:focus-within{border-color:var(--dcf-color-primary);background-color:#fff}.dcf-filter-component:not(.dcf-palette-dark) ion-chip{border:1px solid var(--dcf-color-gray-3);color:var(--dcf-color-gray-7)}.dcf-filter-component:not(.dcf-palette-dark) ion-chip.dcf-filter-value{background:var(--dcf-color-gray-2);border-color:var(--dcf-color-gray-4)!important;color:var(--dcf-color-gray-8)!important}.dcf-filter-component:not(.dcf-palette-dark) .dcf-input input{color:var(--dcf-color-gray-7)}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown{background-color:#fff}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-gray-2)}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-8)}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-3)}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{pointer-events:none;touch-action:none;cursor:text!important;border-color:transparent!important}.dcf-filter-component:not(.dcf-palette-dark) .dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-1)}.dcf-filter-component.dcf-palette-dark .dcf-filter{border:1px solid var(--dcf-color-step-500)}.dcf-filter-component.dcf-palette-dark .dcf-filter ::-webkit-input-placeholder,.dcf-filter-component.dcf-palette-dark .dcf-filter ::placeholder{color:var(--dcf-color-gray-4)!important}.dcf-filter-component.dcf-palette-dark .dcf-filter:hover{border-color:var(--dcf-color-gray-2)}.dcf-filter-component.dcf-palette-dark .dcf-filter:focus-within{border-color:var(--dcf-color-gray-2)}.dcf-filter-component.dcf-palette-dark ion-chip{border-color:var(--dcf-color-step-300);background:rgba(var(--dcf-color-medium-rgb),.1)}.dcf-filter-component.dcf-palette-dark ion-chip.dcf-filter-value{background:rgba(var(--dcf-color-medium-rgb),.3)!important;border-color:var(--dcf-color-step-500)}.dcf-filter-component.dcf-palette-dark .dcf-input input{color:var(--dcf-color-gray-1)}.dcf-filter-component.dcf-palette-dark .dcf-dropdown{background-color:var(--dcf-item-background)}.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active{border:1px solid var(--dcf-color-step-600)}.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div{color:var(--dcf-color-gray-1)}.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div.dcf-filtering-item,.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div:only-child{border-color:var(--dcf-color-gray-5)}.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div.dcf-filtering-item.dcf-empty,.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div:only-child.dcf-empty{cursor:text!important;pointer-events:none;touch-action:none;border-color:transparent!important}.dcf-filter-component.dcf-palette-dark .dcf-dropdown.dcf-active>div>div:hover{background-color:var(--dcf-color-gray-8)}ion-select{min-height:44px!important}.dcf-hidden{display:none!important}.dcf-filter{display:flex;width:100%;min-height:40px;box-shadow:0 1px 2px #0a0d120d;border-radius:var(--dcf-border-radius);box-sizing:border-box}.dcf-filter ion-chip{border-radius:6px;padding:0 8px!important;height:24px;min-height:24px;font-size:.75rem;font-style:normal;font-weight:500;flex-shrink:0;margin-right:2px;white-space:nowrap}.dcf-filter ion-chip.sc-ion-chip-md-h,.dcf-filter ion-chip.sc-ion-chip-ios-h{height:24px;min-height:24px}.dcf-filter ion-chip.sc-ion-chip-md-h .chip-native,.dcf-filter ion-chip.sc-ion-chip-ios-h .chip-native{padding:0 8px!important;height:24px;min-height:24px}.dcf-filter ion-chip ion-label{padding:0 4px;margin:0;font-size:.75rem;white-space:nowrap}.dcf-filter ion-chip ion-icon{margin:0 2px;font-size:.75rem}.dcf-filter .dcf-input{width:100%;display:flex;align-items:center;overflow-x:auto;overflow-y:hidden;white-space:nowrap;padding-left:.5rem}.dcf-filter .dcf-input input{min-height:40px;min-width:100px;width:100%;font-size:1rem;border:none;outline:none;background:transparent;border:0px!important;outline:none!important}.dcf-filter .dcf-input input:focus{border:0px!important;outline:none!important}.dcf-filter .dcf-icon-clear,.dcf-filter .dcf-icon-search{display:flex;justify-content:center;text-align:center;align-items:center;min-width:40px}.dcf-filter .dcf-icon-search ion-icon{font-size:1.25rem}.dcf-sort-container{min-width:200px!important;width:auto}@media (min-width: 990px){.dcf-sort-container{max-width:20%!important}}@media (max-width: 680px){.dcf-sort-container{min-width:100%!important;margin:.75rem 0rem}}.dcf-dropdown{position:absolute;max-height:200px;overflow-y:auto;border-radius:4px;z-index:1000!important;min-width:200px;max-width:300px;display:none}.dcf-dropdown.dcf-active{display:block;margin-top:-3px;box-shadow:0 12px 16px -4px #0a0d1214,0 4px 6px -2px #0a0d1208,0 2px 2px -1px #0a0d120a!important;border-radius:var(--dcf-border-radius);padding:.5rem .25rem}@media (max-width: 768px){.dcf-dropdown.dcf-active{margin-top:55px}}.dcf-dropdown.dcf-active>div>div{cursor:pointer;height:35px;padding:.5rem 1rem;border:1px solid transparent;font-size:1rem;display:flex;align-items:center;border-radius:6px}\n"] }]
8855
8980
  }], ctorParameters: () => [], propDecorators: { optionsFilterElement: [{
8856
8981
  type: ViewChild,
@@ -9269,7 +9394,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9269
9394
  * @memberOf ListComponent
9270
9395
  */
9271
9396
  constructor() {
9272
- super("ListComponent");
9397
+ super('ListComponent');
9273
9398
  /**
9274
9399
  * @description The display mode for the list component.
9275
9400
  * @summary Determines how the list data is loaded and displayed. Options include:
@@ -9345,7 +9470,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9345
9470
  * @default "full"
9346
9471
  * @memberOf ListComponent
9347
9472
  */
9348
- this.lines = "full";
9473
+ this.lines = 'full';
9349
9474
  /**
9350
9475
  * @description Controls whether the list has inset styling.
9351
9476
  * @summary When set to true, the list will have inset styling with rounded corners
@@ -9366,7 +9491,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9366
9491
  * @default "15%"
9367
9492
  * @memberOf ListComponent
9368
9493
  */
9369
- this.scrollThreshold = "15%";
9494
+ this.scrollThreshold = '15%';
9370
9495
  /**
9371
9496
  * @description The position where new items are added during infinite scrolling.
9372
9497
  * @summary Determines whether new items are added to the top or bottom of the list
@@ -9376,7 +9501,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9376
9501
  * @default "bottom"
9377
9502
  * @memberOf ListComponent
9378
9503
  */
9379
- this.scrollPosition = "bottom";
9504
+ this.scrollPosition = 'bottom';
9380
9505
  /**
9381
9506
  * @description Controls the visibility of the pull-to-refresh feature.
9382
9507
  * @summary When set to true, enables the pull-to-refresh functionality that allows
@@ -9405,7 +9530,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9405
9530
  * @default "circular"
9406
9531
  * @memberOf ListComponent
9407
9532
  */
9408
- this.loadingSpinner = "circular";
9533
+ this.loadingSpinner = 'circular';
9409
9534
  // /**
9410
9535
  // * @description Query parameters for data fetching.
9411
9536
  // * @summary Specifies additional query parameters to use when fetching data from
@@ -9474,17 +9599,6 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9474
9599
  * @memberOf ListComponent
9475
9600
  */
9476
9601
  this.page = 1;
9477
- /**
9478
- * @description Indicates whether a refresh operation is in progress.
9479
- * @summary When true, the component is currently fetching new data. This is used
9480
- * to control loading indicators and prevent duplicate refresh operations from
9481
- * being triggered simultaneously.
9482
- *
9483
- * @type {boolean}
9484
- * @default false
9485
- * @memberOf ListComponent
9486
- */
9487
- this.refreshing = false;
9488
9602
  /**
9489
9603
  * @description Array used for rendering skeleton loading placeholders.
9490
9604
  * @summary Contains placeholder items that are displayed during data loading.
@@ -9506,15 +9620,6 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9506
9620
  * @memberOf ListComponent
9507
9621
  */
9508
9622
  this.lastPage = 1;
9509
- /**
9510
- * @description Event emitter for refresh operations.
9511
- * @summary Emits an event when the list data is refreshed, either through pull-to-refresh
9512
- * or programmatic refresh. The event includes the refreshed data and component information.
9513
- *
9514
- * @type {EventEmitter<IBaseCustomEvent>}
9515
- * @memberOf ListComponent
9516
- */
9517
- this.refreshEvent = new EventEmitter();
9518
9623
  /**
9519
9624
  * @description Event emitter for item click interactions.
9520
9625
  * @summary Emits an event when a list item is clicked. The event includes the data
@@ -9575,9 +9680,15 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9575
9680
  * @memberOf ListComponent
9576
9681
  */
9577
9682
  async ngOnInit() {
9578
- this.observer = { refresh: async (...args) => this.observeRepository(...args) };
9579
- this.clickItemSubject.pipe(debounceTime(100)).subscribe(event => this.clickEventEmit(event));
9580
- this.observerSubjet.pipe(debounceTime(100)).subscribe(args => this.handleObserveEvent(args[0], args[1], args[2]));
9683
+ this.observer = {
9684
+ refresh: async (...args) => this.observeRepository(...args),
9685
+ };
9686
+ this.clickItemSubject
9687
+ .pipe(debounceTime(100))
9688
+ .subscribe((event) => this.clickEventEmit(event));
9689
+ this.observerSubjet
9690
+ .pipe(debounceTime(100))
9691
+ .subscribe((args) => this.handleObserveEvent(args[0], args[1], args[2]));
9581
9692
  this.limit = Number(this.limit);
9582
9693
  this.start = Number(this.start);
9583
9694
  this.enableFilter = stringToBoolean(this.enableFilter);
@@ -9685,7 +9796,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9685
9796
  async handleCreate(uid) {
9686
9797
  const result = await this._repository?.read(uid);
9687
9798
  const item = this.mapResults([result])[0];
9688
- this.items = this.data = [item, ...this.items || []];
9799
+ this.items = this.data = [item, ...(this.items || [])];
9689
9800
  }
9690
9801
  /**
9691
9802
  * @description Handles the update event from the repository.
@@ -9697,7 +9808,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9697
9808
  * @memberOf ListComponent
9698
9809
  */
9699
9810
  async handleUpdate(uid) {
9700
- const item = this.itemMapper(await this._repository?.read(uid) || {}, this.mapper);
9811
+ const item = this.itemMapper((await this._repository?.read(uid)) || {}, this.mapper);
9701
9812
  this.data = [];
9702
9813
  for (const key in this.items) {
9703
9814
  const child = this.items[key];
@@ -9724,7 +9835,8 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9724
9835
  handleDelete(uid, pk) {
9725
9836
  if (!pk)
9726
9837
  pk = this.pk;
9727
- this.items = this.data?.filter((item) => item['uid'] !== uid) || [];
9838
+ this.items =
9839
+ this.data?.filter((item) => item['uid'] !== uid) || [];
9728
9840
  }
9729
9841
  /**
9730
9842
  * @description Handles click events from list items.
@@ -9828,7 +9940,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9828
9940
  this.refreshEvent.emit({
9829
9941
  name: ComponentEventNames.REFRESH,
9830
9942
  data: data || [],
9831
- component: this.componentName
9943
+ component: this.componentName,
9832
9944
  });
9833
9945
  }
9834
9946
  /**
@@ -9904,10 +10016,10 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9904
10016
  // }
9905
10017
  this.refreshing = true;
9906
10018
  const start = this.page > 1 ? (this.page - 1) * this.limit : this.start;
9907
- const limit = (this.page * (this.limit > 12 ? 12 : this.limit));
9908
- this.data = !this.model ?
9909
- await this.getFromRequest(!!event, start, limit)
9910
- : await this.getFromModel(!!event);
10019
+ const limit = this.page * (this.limit > 12 ? 12 : this.limit);
10020
+ this.data = !this.model
10021
+ ? await this.getFromRequest(!!event, start, limit)
10022
+ : (await this.getFromModel(!!event));
9911
10023
  if (this.type === ListComponentsTypes.INFINITE) {
9912
10024
  if (this.page === this.pages) {
9913
10025
  if (event?.target)
@@ -9918,7 +10030,9 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9918
10030
  this.page += 1;
9919
10031
  this.refreshing = false;
9920
10032
  setTimeout(() => {
9921
- if (event?.target && event?.type !== ComponentEventNames.BACK_BUTTON_NAVIGATION)
10033
+ if (event?.target &&
10034
+ event?.type !==
10035
+ ComponentEventNames.BACK_BUTTON_NAVIGATION)
9922
10036
  event.target.complete();
9923
10037
  }, 200);
9924
10038
  }
@@ -9930,16 +10044,16 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9930
10044
  }
9931
10045
  }
9932
10046
  /**
9933
- * @description Handles pagination events from the pagination component.
9934
- * @summary Processes pagination events by updating the current page number and
9935
- * refreshing the list data to display the selected page. This method is called
9936
- * when a user interacts with the pagination controls to navigate between pages.
9937
- *
9938
- * @param {IPaginationCustomEvent} event - The pagination event containing page information
9939
- * @returns {void}
9940
- *
9941
- * @memberOf ListComponent
9942
- */
10047
+ * @description Handles pagination events from the pagination component.
10048
+ * @summary Processes pagination events by updating the current page number and
10049
+ * refreshing the list data to display the selected page. This method is called
10050
+ * when a user interacts with the pagination controls to navigate between pages.
10051
+ *
10052
+ * @param {IPaginationCustomEvent} event - The pagination event containing page information
10053
+ * @returns {void}
10054
+ *
10055
+ * @memberOf ListComponent
10056
+ */
9943
10057
  handlePaginate(event) {
9944
10058
  const { page } = event.data;
9945
10059
  this.page = page;
@@ -9977,8 +10091,11 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9977
10091
  * @memberOf ListComponent
9978
10092
  */
9979
10093
  parseSearchResults(results, search) {
9980
- const filtered = results.filter((item) => Object.values(item).some(v => {
9981
- if (v.toString().toLowerCase().includes(search?.toLowerCase()))
10094
+ const filtered = results.filter((item) => Object.values(item).some((v) => {
10095
+ if (v
10096
+ .toString()
10097
+ .toLowerCase()
10098
+ .includes(search?.toLowerCase()))
9982
10099
  return v;
9983
10100
  }));
9984
10101
  return filtered;
@@ -9997,25 +10114,31 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
9997
10114
  * @memberOf ListComponent
9998
10115
  */
9999
10116
  async getFromRequest(force = false, start, limit) {
10000
- let data = [...this.data || []];
10001
- if (!this.data?.length || force || this.searchValue?.length || !!this.searchValue) {
10117
+ let data = [...(this.data || [])];
10118
+ if (!this.data?.length ||
10119
+ force ||
10120
+ this.searchValue?.length ||
10121
+ !!this.searchValue) {
10002
10122
  // (self.data as ListItem[]) = [];
10003
- if (!this.searchValue?.length && !this.searchValue) {
10123
+ if (!this.searchValue?.length &&
10124
+ !this.searchValue) {
10004
10125
  if (!this.source && !this.data?.length) {
10005
10126
  this.log.info('No data and source passed to infinite list');
10006
10127
  return [];
10007
10128
  }
10008
10129
  if (this.source instanceof Function) {
10009
- data = await this.source();
10130
+ data = (await this.source());
10010
10131
  if (!Array.isArray(data))
10011
10132
  data = data?.['response']?.['data'] || data?.['results'] || [];
10012
10133
  }
10013
10134
  if (!data?.length && this.data?.length)
10014
10135
  data = this.data;
10015
- this.data = [...await this.parseResult(data)];
10136
+ this.data = [...(await this.parseResult(data))];
10016
10137
  if (this.data?.length)
10017
- this.items = this.type === ListComponentsTypes.INFINITE ?
10018
- (this.items || []).concat([...this.data.slice(start, limit)]) : [...data.slice(start, limit)];
10138
+ this.items =
10139
+ this.type === ListComponentsTypes.INFINITE
10140
+ ? (this.items || []).concat([...this.data.slice(start, limit)])
10141
+ : [...data.slice(start, limit)];
10019
10142
  }
10020
10143
  else {
10021
10144
  const data = await this.parseResult(this.parseSearchResults(this.data, this.searchValue));
@@ -10025,8 +10148,11 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
10025
10148
  }
10026
10149
  }
10027
10150
  else {
10028
- const data = [...await this.parseResult(this.data)];
10029
- this.items = this.type === ListComponentsTypes.INFINITE ? [...(this.items || []), ...(data || [])] : [...(data || [])];
10151
+ const data = [...(await this.parseResult(this.data))];
10152
+ this.items =
10153
+ this.type === ListComponentsTypes.INFINITE
10154
+ ? [...(this.items || []), ...(data || [])]
10155
+ : [...(data || [])];
10030
10156
  if (this.isModalChild)
10031
10157
  this.changeDetectorRef.detectChanges();
10032
10158
  }
@@ -10048,7 +10174,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
10048
10174
  * @memberOf ListComponent
10049
10175
  */
10050
10176
  async getFromModel(force = false) {
10051
- let data = [...this.data || []];
10177
+ let data = [...(this.data || [])];
10052
10178
  let request = [];
10053
10179
  // getting model repository
10054
10180
  if (!this._repository) {
@@ -10057,9 +10183,13 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
10057
10183
  this._repository.observe(this.observer);
10058
10184
  }
10059
10185
  const repo = this._repository;
10060
- if (!this.data?.length || force || this.searchValue?.length || !!this.searchValue) {
10186
+ if (!this.data?.length ||
10187
+ force ||
10188
+ this.searchValue?.length ||
10189
+ !!this.searchValue) {
10061
10190
  try {
10062
- if (!this.searchValue?.length && !this.searchValue) {
10191
+ if (!this.searchValue?.length &&
10192
+ !this.searchValue) {
10063
10193
  this.data = [];
10064
10194
  // const rawQuery = this.parseQuery(self.model as Repository<Model>, start, limit);
10065
10195
  // request = this.parseResult(await (this.model as any)?.paginate(start, limit));
@@ -10073,17 +10203,21 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
10073
10203
  }
10074
10204
  else {
10075
10205
  if (!this.indexes)
10076
- this.indexes = (Object.values(this.mapper) || [this.pk]);
10206
+ this.indexes = Object.values(this.mapper) || [this.pk];
10077
10207
  const condition = this.parseConditions(this.searchValue);
10078
10208
  this.changeDetectorRef.detectChanges();
10079
10209
  request = await this.parseResult(await repo.query(condition, (this.sortBy || this.pk), this.sortDirection));
10080
10210
  data = [];
10081
10211
  this.changeDetectorRef.detectChanges();
10082
10212
  }
10083
- data = this.type === ListComponentsTypes.INFINITE ? [...(data).concat(request)] : [...request];
10213
+ data =
10214
+ this.type === ListComponentsTypes.INFINITE
10215
+ ? [...data.concat(request)]
10216
+ : [...request];
10084
10217
  }
10085
10218
  catch (error) {
10086
- this.log.error(error?.message || `Unable to find ${this.model} on registry. Return empty array from component`);
10219
+ this.log.error(error?.message ||
10220
+ `Unable to find ${this.model} on registry. Return empty array from component`);
10087
10221
  }
10088
10222
  }
10089
10223
  if (data?.length) {
@@ -10123,7 +10257,8 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
10123
10257
  */
10124
10258
  parseConditions(value) {
10125
10259
  let _condition;
10126
- if (typeof value === Primitives.STRING || typeof value === Primitives.NUMBER) {
10260
+ if (typeof value === Primitives.STRING ||
10261
+ typeof value === Primitives.NUMBER) {
10127
10262
  _condition = Condition.attribute(this.pk).eq(!isNaN(value) ? Number(value) : value);
10128
10263
  for (const index of this.indexes) {
10129
10264
  if (index === this.pk)
@@ -10150,27 +10285,28 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
10150
10285
  val = Number(val);
10151
10286
  let orCondition;
10152
10287
  switch (condition) {
10153
- case "Equal":
10288
+ case 'Equal':
10154
10289
  orCondition = Condition.attribute(index).eq(val);
10155
10290
  break;
10156
- case "Not Equal":
10291
+ case 'Not Equal':
10157
10292
  orCondition = Condition.attribute(index).dif(val);
10158
10293
  break;
10159
- case "Not Contains":
10294
+ case 'Not Contains':
10160
10295
  orCondition = !Condition.attribute(index).regexp(new RegExp(`^(?!.*${val}).*$`));
10161
10296
  break;
10162
- case "Contains":
10297
+ case 'Contains':
10163
10298
  orCondition = Condition.attribute(index).regexp(val);
10164
10299
  break;
10165
- case "Greater Than":
10300
+ case 'Greater Than':
10166
10301
  orCondition = Condition.attribute(index).gte(val);
10167
10302
  break;
10168
- case "Less Than":
10303
+ case 'Less Than':
10169
10304
  orCondition = Condition.attribute(index).lte(val);
10170
10305
  break;
10171
10306
  }
10172
- _condition = (!_condition ?
10173
- orCondition : _condition.and(orCondition));
10307
+ _condition = (!_condition
10308
+ ? orCondition
10309
+ : _condition.and(orCondition));
10174
10310
  });
10175
10311
  this.sortBy = sort?.value || this.pk;
10176
10312
  this.sortDirection = sort?.direction || this.sortDirection;
@@ -10190,22 +10326,24 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
10190
10326
  * @memberOf ListComponent
10191
10327
  */
10192
10328
  async parseResult(result) {
10193
- if (!Array.isArray(result) && ('page' in result && 'total' in result)) {
10329
+ if (!Array.isArray(result) && 'page' in result && 'total' in result) {
10194
10330
  const paginator = result;
10195
10331
  try {
10196
10332
  result = await paginator.page(this.page);
10197
10333
  this.getMoreData(paginator.total);
10198
10334
  }
10199
10335
  catch (error) {
10200
- this.log.info(error?.message || 'Unable to get page from paginator. Return empty array from component');
10336
+ this.log.info(error?.message ||
10337
+ 'Unable to get page from paginator. Return empty array from component');
10201
10338
  result = [];
10202
10339
  }
10203
10340
  }
10204
10341
  else {
10205
10342
  this.getMoreData(result?.length || 0);
10206
10343
  }
10207
- return (Object.keys(this.mapper || {}).length) ?
10208
- this.mapResults(result) : result;
10344
+ return Object.keys(this.mapper || {}).length
10345
+ ? this.mapResults(result)
10346
+ : result;
10209
10347
  }
10210
10348
  /**
10211
10349
  * @description Updates pagination state based on data length.
@@ -10227,7 +10365,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
10227
10365
  }
10228
10366
  else {
10229
10367
  this.pages = Math.floor(length / this.limit);
10230
- if ((this.pages * this.limit) < length)
10368
+ if (this.pages * this.limit < length)
10231
10369
  this.pages += 1;
10232
10370
  if (this.pages === 1)
10233
10371
  this.loadMoreData = false;
@@ -10261,7 +10399,7 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
10261
10399
  }
10262
10400
  else {
10263
10401
  if (arrayValue.length === 1) {
10264
- value = item?.[value] ? item[value] : "";
10402
+ value = item?.[value] ? item[value] : '';
10265
10403
  // value = item?.[value] ? item[value] : value !== key ? value : "";
10266
10404
  if (isValidDate(value))
10267
10405
  value = `${formatDate(value)}`;
@@ -10310,18 +10448,23 @@ let ListComponent = class ListComponent extends NgxComponentDirective {
10310
10448
  // }, {}))
10311
10449
  });
10312
10450
  return data.reduce((accum, curr) => {
10313
- accum.push({ ...this.itemMapper(curr, this.mapper, props), ...{ pk: this.pk } });
10451
+ accum.push({
10452
+ ...this.itemMapper(curr, this.mapper, props),
10453
+ ...{ pk: this.pk },
10454
+ });
10314
10455
  return accum;
10315
10456
  }, []);
10316
10457
  }
10317
10458
  parseSearchValue() {
10318
10459
  if (typeof this.searchValue === Primitives.STRING)
10319
- return this.searchValue || "";
10460
+ return this.searchValue || '';
10320
10461
  const searchValue = this.searchValue;
10321
- return (searchValue?.query).map(item => `${item.index} ${item.condition} ${item.value}`).join(", ");
10462
+ return (searchValue?.query)
10463
+ .map((item) => `${item.index} ${item.condition} ${item.value}`)
10464
+ .join(', ');
10322
10465
  }
10323
10466
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: ListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
10324
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: ListComponent, isStandalone: true, selector: "ngx-decaf-list", inputs: { type: "type", showSearchbar: "showSearchbar", data: "data", source: "source", start: "start", limit: "limit", loadMoreData: "loadMoreData", lines: "lines", inset: "inset", scrollThreshold: "scrollThreshold", scrollPosition: "scrollPosition", loadingText: "loadingText", showRefresher: "showRefresher", createButton: "createButton", loadingSpinner: "loadingSpinner", enableFilter: "enableFilter", sortDirection: "sortDirection", sortBy: "sortBy", disableSort: "disableSort", empty: "empty" }, outputs: { refreshEvent: "refreshEvent", clickEvent: "clickEvent" }, host: { listeners: { "window:ListItemClickEvent": "handleClick($event)", "window:searchbarEvent": "handleSearch($event)", "window:BackButtonNavigationEndEvent": "refresh($event)" }, properties: { "attr.id": "uid" } }, usesInheritance: true, ngImport: i0, template: "\n@if (showRefresher) {\n <ion-refresher slot=\"fixed\" [pullFactor]=\"1\" [pullMin]=\"100\" [pullMax]=\"200\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content />\n </ion-refresher>\n}\n\n\n@if (showSearchbar) {\n <div [hidden]=\"!data?.length\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-grid-actions\">\n <div class=\"dcf-width-expand@m dcf-width-1-1\">\n @if (model && enableFilter) {\n @if (data?.length || searching) {\n <ngx-decaf-filter\n [model]=\"model\"\n [sortDirection]=\"sortDirection\"\n [disableSort]=\"disableSort\"\n (filterEvent)=\"handleFilter($event)\"\n (searchEvent)=\"handleSearch($event)\"\n />\n }\n } @else {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n }\n </div>\n @if(createButton) {\n <div class=\"dcf-width-auto@m dcf-button-container dcf-width-1-1 dcf-flex-middle dcf-flex dcf-flex-center dcf-flex-right@m\">\n <div>\n <ion-button expand=\"block\" (click)=\"changeOperation(OperationKeys.CREATE)\">Create</ion-button>\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n@if (initialized && data?.length) {\n <ion-list [id]=\"uid\" [inset]=\"inset\" [lines]=\"lines\">\n @if (item?.tag) {\n @for(child of items; track trackItemFn($index, child)) {\n <ngx-decaf-component-renderer\n [tag]=\"item.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]='{\n item: child,\n mapper: mapper,\n route: route\n }'>\n </ngx-decaf-component-renderer>\n }\n } @else {\n <ng-content></ng-content>\n }\n </ion-list>\n\n @if (loadMoreData) {\n @if (pages > 0 && type === 'paginated' && !searchValue?.length) {\n <ngx-decaf-pagination\n [totalPages]=\"pages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n\n } @else {\n <ion-infinite-scroll\n [class]=\"searchValue?.length ? 'dcf-hidden' : ''\"\n\n [position]=\"scrollPosition\"\n [threshold]=\"scrollThreshold\"\n (ionInfinite)=\"handleRefresh($event)\">\n <ion-infinite-scroll-content [loadingSpinner]=\"loadingSpinner\" [loadingText]=\"loadingText\" />\n </ion-infinite-scroll>\n }\n }\n} @else {\n @if (refreshing) {\n @for(skl of skeletonData; track $index) {\n <ion-item>\n <ion-thumbnail slot=\"start\">\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n </ion-thumbnail>\n <ion-label>\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n </ion-label>\n </ion-item>\n }\n\n } @else {\n @if (!searching) {\n <ngx-decaf-empty-state\n [title]=\"(locale + '.'+ empty.title) | translate\"\n [model]=\"model\"\n [route]=\"route\"\n [borders]=\"borders\"\n [icon]=\"empty.icon\"\n className=\"dcf-empty-data\"\n [subtitle]=\"(locale + '.'+ empty.subtitle) | translate\" />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n [model]=\"model\"\n [route]=\"route\"\n [borders]=\"borders\"\n className=\"empty-search\"\n [translatable]=\"true\"\n className=\"dcf-empty-data\"\n [title]=\"locale + '.search.title' | translate\"\n [subtitle]=\"locale + '.search.subtitle' | translate: {'0': parseSearchValue()}\"\n [searchValue]=\"searchValue\"\n />\n }\n }\n}\n\n", styles: ["ion-infinite-scroll{max-height:50px}ion-infinite-scroll:not(.infinite-scroll-loading) ::ng-deep{max-height:1.5rem}ion-infinite-scroll ::ng-deep ion-spinner{--color: var(--dcf-color-primary);padding-top:1rem}@media (max-width: 768px){#end,[slot=end]{display:none!important}}.dcf-grid-actions{padding:var(--dcf-padding-small);padding-bottom:0}@media (max-width: 768px){.dcf-grid-actions .dcf-button-container{width:100%!important}.dcf-grid-actions .dcf-button-container *{width:calc(100% - 5px)!important;display:inline-block;margin-top:0!important;margin-bottom:var(--dcf-margin-xsmall)!important}}.dcf-grid-actions>div:only-child{width:100%}\n"], dependencies: [{ kind: "component", type: IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: PaginationComponent, selector: "ngx-decaf-pagination", inputs: ["totalPages", "current"], outputs: ["clickEvent"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonThumbnail, selector: "ion-thumbnail" }, { kind: "component", type: IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: SearchbarComponent, selector: "ngx-decaf-searchbar", inputs: ["autocomplete", "autocorrect", "animated", "buttonCancelText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value", "queryKeys", "isVisible", "wrapper", "wrapperColor", "emitEventToWindow"], outputs: ["searchEvent"] }, { kind: "component", type: EmptyStateComponent, selector: "ngx-decaf-empty-state", inputs: ["title", "titleColor", "subtitle", "subtitleColor", "showIcon", "icon", "iconSize", "iconColor", "buttonLink", "buttonText", "buttonFill", "buttonColor", "buttonSize", "searchValue"] }, { kind: "component", type: FilterComponent, selector: "ngx-decaf-filter", inputs: ["indexes", "multiple", "conditions", "sortBy", "disableSort"], outputs: ["filterEvent", "searchEvent"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "children", "projectable", "parent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
10467
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.9", type: ListComponent, isStandalone: true, selector: "ngx-decaf-list", inputs: { type: "type", showSearchbar: "showSearchbar", data: "data", source: "source", start: "start", limit: "limit", loadMoreData: "loadMoreData", lines: "lines", inset: "inset", scrollThreshold: "scrollThreshold", scrollPosition: "scrollPosition", loadingText: "loadingText", showRefresher: "showRefresher", createButton: "createButton", loadingSpinner: "loadingSpinner", enableFilter: "enableFilter", sortDirection: "sortDirection", sortBy: "sortBy", disableSort: "disableSort", empty: "empty" }, outputs: { clickEvent: "clickEvent" }, host: { listeners: { "window:ListItemClickEvent": "handleClick($event)", "window:searchbarEvent": "handleSearch($event)", "window:BackButtonNavigationEndEvent": "refresh($event)" }, properties: { "attr.id": "uid" } }, usesInheritance: true, ngImport: i0, template: "\n@if (showRefresher) {\n <ion-refresher slot=\"fixed\" [pullFactor]=\"1\" [pullMin]=\"100\" [pullMax]=\"200\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content />\n </ion-refresher>\n}\n\n\n@if (showSearchbar) {\n <div [hidden]=\"!data?.length\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-grid-actions\">\n <div class=\"dcf-width-expand@m dcf-width-1-1\">\n @if (model && enableFilter) {\n @if (data?.length || searching) {\n <ngx-decaf-filter\n [model]=\"model\"\n [sortDirection]=\"sortDirection\"\n [disableSort]=\"disableSort\"\n (filterEvent)=\"handleFilter($event)\"\n (searchEvent)=\"handleSearch($event)\"\n />\n }\n } @else {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n }\n </div>\n @if(createButton) {\n <div class=\"dcf-width-auto@m dcf-button-container dcf-width-1-1 dcf-flex-middle dcf-flex dcf-flex-center dcf-flex-right@m\">\n <div>\n <ion-button expand=\"block\" (click)=\"changeOperation(OperationKeys.CREATE)\">Create</ion-button>\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n@if (initialized && data?.length) {\n <ion-list [id]=\"uid\" [inset]=\"inset\" [lines]=\"lines\">\n @if (item?.tag) {\n @for(child of items; track trackItemFn($index, child)) {\n <ngx-decaf-component-renderer\n [tag]=\"item.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]='{\n item: child,\n mapper: mapper,\n route: route\n }'>\n </ngx-decaf-component-renderer>\n }\n } @else {\n <ng-content></ng-content>\n }\n </ion-list>\n\n @if (loadMoreData) {\n @if (pages > 0 && type === 'paginated' && !searchValue?.length) {\n <ngx-decaf-pagination\n [totalPages]=\"pages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n\n } @else {\n <ion-infinite-scroll\n [class]=\"searchValue?.length ? 'dcf-hidden' : ''\"\n\n [position]=\"scrollPosition\"\n [threshold]=\"scrollThreshold\"\n (ionInfinite)=\"handleRefresh($event)\">\n <ion-infinite-scroll-content [loadingSpinner]=\"loadingSpinner\" [loadingText]=\"loadingText\" />\n </ion-infinite-scroll>\n }\n }\n} @else {\n @if (refreshing) {\n @for(skl of skeletonData; track $index) {\n <ion-item>\n <ion-thumbnail slot=\"start\">\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n </ion-thumbnail>\n <ion-label>\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n </ion-label>\n </ion-item>\n }\n\n } @else {\n @if (!searching) {\n <ngx-decaf-empty-state\n [title]=\"(locale + '.'+ empty.title) | translate\"\n [model]=\"model\"\n [route]=\"route\"\n [borders]=\"borders\"\n [icon]=\"empty.icon\"\n className=\"dcf-empty-data\"\n [subtitle]=\"(locale + '.'+ empty.subtitle) | translate\" />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n [model]=\"model\"\n [route]=\"route\"\n [borders]=\"borders\"\n className=\"empty-search\"\n [translatable]=\"true\"\n className=\"dcf-empty-data\"\n [title]=\"locale + '.search.title' | translate\"\n [subtitle]=\"locale + '.search.subtitle' | translate: {'0': parseSearchValue()}\"\n [searchValue]=\"searchValue\"\n />\n }\n }\n}\n\n", styles: ["ion-infinite-scroll{max-height:50px}ion-infinite-scroll:not(.infinite-scroll-loading) ::ng-deep{max-height:1.5rem}ion-infinite-scroll ::ng-deep ion-spinner{--color: var(--dcf-color-primary);padding-top:1rem}@media (max-width: 768px){#end,[slot=end]{display:none!important}}.dcf-grid-actions{padding:var(--dcf-padding-small);padding-bottom:0}@media (max-width: 768px){.dcf-grid-actions .dcf-button-container{width:100%!important}.dcf-grid-actions .dcf-button-container *{width:calc(100% - 5px)!important;display:inline-block;margin-top:0!important;margin-bottom:var(--dcf-margin-xsmall)!important}}.dcf-grid-actions>div:only-child{width:100%}\n"], dependencies: [{ kind: "component", type: IonRefresher, selector: "ion-refresher", inputs: ["closeDuration", "disabled", "mode", "pullFactor", "pullMax", "pullMin", "snapbackDuration"] }, { kind: "component", type: IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: PaginationComponent, selector: "ngx-decaf-pagination", inputs: ["totalPages", "current"], outputs: ["clickEvent"] }, { kind: "component", type: IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: IonItem, selector: "ion-item", inputs: ["button", "color", "detail", "detailIcon", "disabled", "download", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "target", "type"] }, { kind: "component", type: IonThumbnail, selector: "ion-thumbnail" }, { kind: "component", type: IonSkeletonText, selector: "ion-skeleton-text", inputs: ["animated"] }, { kind: "component", type: IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "component", type: IonRefresherContent, selector: "ion-refresher-content", inputs: ["pullingIcon", "pullingText", "refreshingSpinner", "refreshingText"] }, { kind: "component", type: IonInfiniteScroll, selector: "ion-infinite-scroll", inputs: ["disabled", "position", "threshold"] }, { kind: "component", type: IonInfiniteScrollContent, selector: "ion-infinite-scroll-content", inputs: ["loadingSpinner", "loadingText"] }, { kind: "component", type: SearchbarComponent, selector: "ngx-decaf-searchbar", inputs: ["autocomplete", "autocorrect", "animated", "buttonCancelText", "clearIcon", "color", "debounce", "disabled", "enterkeyhint", "inputmode", "placeholder", "searchIcon", "showCancelButton", "showClearButton", "spellcheck", "type", "value", "queryKeys", "isVisible", "wrapper", "wrapperColor", "emitEventToWindow"], outputs: ["searchEvent"] }, { kind: "component", type: EmptyStateComponent, selector: "ngx-decaf-empty-state", inputs: ["title", "titleColor", "subtitle", "subtitleColor", "showIcon", "icon", "iconSize", "iconColor", "buttonLink", "buttonText", "buttonFill", "buttonColor", "buttonSize", "searchValue"] }, { kind: "component", type: FilterComponent, selector: "ngx-decaf-filter", inputs: ["indexes", "multiple", "conditions", "sortBy", "disableSort"], outputs: ["filterEvent", "searchEvent"] }, { kind: "component", type: ComponentRendererComponent, selector: "ngx-decaf-component-renderer", inputs: ["tag", "children", "projectable", "parent"] }, { kind: "pipe", type: TranslatePipe, name: "translate" }] }); }
10325
10468
  };
10326
10469
  ListComponent = __decorate([
10327
10470
  Dynamic(),
@@ -10348,7 +10491,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
10348
10491
  SearchbarComponent,
10349
10492
  EmptyStateComponent,
10350
10493
  FilterComponent,
10351
- ComponentRendererComponent
10494
+ ComponentRendererComponent,
10352
10495
  ], host: { '[attr.id]': 'uid' }, template: "\n@if (showRefresher) {\n <ion-refresher slot=\"fixed\" [pullFactor]=\"1\" [pullMin]=\"100\" [pullMax]=\"200\" (ionRefresh)=\"handleRefresh($event)\">\n <ion-refresher-content />\n </ion-refresher>\n}\n\n\n@if (showSearchbar) {\n <div [hidden]=\"!data?.length\">\n <div class=\"dcf-grid dcf-grid-collapse dcf-grid-actions\">\n <div class=\"dcf-width-expand@m dcf-width-1-1\">\n @if (model && enableFilter) {\n @if (data?.length || searching) {\n <ngx-decaf-filter\n [model]=\"model\"\n [sortDirection]=\"sortDirection\"\n [disableSort]=\"disableSort\"\n (filterEvent)=\"handleFilter($event)\"\n (searchEvent)=\"handleSearch($event)\"\n />\n }\n } @else {\n <ngx-decaf-searchbar [emitEventToWindow]=\"false\" [debounce]=\"500\" (searchEvent)=\"handleSearch($event)\" />\n }\n </div>\n @if(createButton) {\n <div class=\"dcf-width-auto@m dcf-button-container dcf-width-1-1 dcf-flex-middle dcf-flex dcf-flex-center dcf-flex-right@m\">\n <div>\n <ion-button expand=\"block\" (click)=\"changeOperation(OperationKeys.CREATE)\">Create</ion-button>\n </div>\n </div>\n }\n </div>\n </div>\n}\n\n@if (initialized && data?.length) {\n <ion-list [id]=\"uid\" [inset]=\"inset\" [lines]=\"lines\">\n @if (item?.tag) {\n @for(child of items; track trackItemFn($index, child)) {\n <ngx-decaf-component-renderer\n [tag]=\"item.tag\"\n (listenEvent)=\"handleEvent($event)\"\n [globals]='{\n item: child,\n mapper: mapper,\n route: route\n }'>\n </ngx-decaf-component-renderer>\n }\n } @else {\n <ng-content></ng-content>\n }\n </ion-list>\n\n @if (loadMoreData) {\n @if (pages > 0 && type === 'paginated' && !searchValue?.length) {\n <ngx-decaf-pagination\n [totalPages]=\"pages\"\n [current]=\"page\"\n (clickEvent)=\"handlePaginate($event)\"\n />\n\n } @else {\n <ion-infinite-scroll\n [class]=\"searchValue?.length ? 'dcf-hidden' : ''\"\n\n [position]=\"scrollPosition\"\n [threshold]=\"scrollThreshold\"\n (ionInfinite)=\"handleRefresh($event)\">\n <ion-infinite-scroll-content [loadingSpinner]=\"loadingSpinner\" [loadingText]=\"loadingText\" />\n </ion-infinite-scroll>\n }\n }\n} @else {\n @if (refreshing) {\n @for(skl of skeletonData; track $index) {\n <ion-item>\n <ion-thumbnail slot=\"start\">\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n </ion-thumbnail>\n <ion-label>\n <ion-skeleton-text [animated]=\"true\"></ion-skeleton-text>\n <ion-text class=\"date\" style=\"width: 20%;\"><ion-skeleton-text [animated]=\"true\"></ion-skeleton-text></ion-text>\n </ion-label>\n </ion-item>\n }\n\n } @else {\n @if (!searching) {\n <ngx-decaf-empty-state\n [title]=\"(locale + '.'+ empty.title) | translate\"\n [model]=\"model\"\n [route]=\"route\"\n [borders]=\"borders\"\n [icon]=\"empty.icon\"\n className=\"dcf-empty-data\"\n [subtitle]=\"(locale + '.'+ empty.subtitle) | translate\" />\n } @else {\n <ngx-decaf-empty-state\n icon=\"search-outline\"\n [model]=\"model\"\n [route]=\"route\"\n [borders]=\"borders\"\n className=\"empty-search\"\n [translatable]=\"true\"\n className=\"dcf-empty-data\"\n [title]=\"locale + '.search.title' | translate\"\n [subtitle]=\"locale + '.search.subtitle' | translate: {'0': parseSearchValue()}\"\n [searchValue]=\"searchValue\"\n />\n }\n }\n}\n\n", styles: ["ion-infinite-scroll{max-height:50px}ion-infinite-scroll:not(.infinite-scroll-loading) ::ng-deep{max-height:1.5rem}ion-infinite-scroll ::ng-deep ion-spinner{--color: var(--dcf-color-primary);padding-top:1rem}@media (max-width: 768px){#end,[slot=end]{display:none!important}}.dcf-grid-actions{padding:var(--dcf-padding-small);padding-bottom:0}@media (max-width: 768px){.dcf-grid-actions .dcf-button-container{width:100%!important}.dcf-grid-actions .dcf-button-container *{width:calc(100% - 5px)!important;display:inline-block;margin-top:0!important;margin-bottom:var(--dcf-margin-xsmall)!important}}.dcf-grid-actions>div:only-child{width:100%}\n"] }]
10353
10496
  }], ctorParameters: () => [], propDecorators: { type: [{
10354
10497
  type: Input
@@ -10390,8 +10533,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
10390
10533
  type: Input
10391
10534
  }], empty: [{
10392
10535
  type: Input
10393
- }], refreshEvent: [{
10394
- type: Output
10395
10536
  }], clickEvent: [{
10396
10537
  type: Output
10397
10538
  }], handleClick: [{
@@ -11771,15 +11912,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.9", ngImpor
11771
11912
  class DynamicModule {
11772
11913
  }
11773
11914
 
11774
- /**
11775
- * @module module:lib/engine/NgxEventHandler
11776
- * @description Event handler base class used by Decaf components.
11777
- * @summary Defines NgxEventHandler which standardizes event handling logic and provides
11778
- * logging support for handlers that process custom events emitted by components.
11779
- *
11780
- * @link {@link NgxEventHandler}
11781
- */
11782
- class NgxEventHandler extends LoggedClass {
11915
+ class NgxEventHandler extends DecafEventHandler {
11916
+ async refresh(args) {
11917
+ this.log.for(this.refresh).debug(`Refresh called with args: ${args}`);
11918
+ }
11783
11919
  }
11784
11920
 
11785
11921
  /**
@@ -11885,7 +12021,6 @@ class NgxPageDirective extends NgxComponentDirective {
11885
12021
  this.mediaService.colorSchemeObserver(this.component);
11886
12022
  this.currentRoute = this.router.url.replace('/', '');
11887
12023
  this.setPageTitle(this.currentRoute);
11888
- this.initialized = true;
11889
12024
  }
11890
12025
  /**
11891
12026
  * @description Ionic lifecycle hook called when the page is about to enter view.
@@ -11975,17 +12110,20 @@ class NgxModelPageDirective extends NgxPageDirective {
11975
12110
  * @default [OperationKeys.CREATE, OperationKeys.READ]
11976
12111
  * @memberOf ModelPage
11977
12112
  */
11978
- this.allowedOperations = [OperationKeys.CREATE, OperationKeys.READ];
11979
- /**
11980
- * @description Current model data loaded from the repository.
11981
- * @summary Stores the raw data object representing the current model instance retrieved
11982
- * from the repository. This property holds the actual data values for the model being
11983
- * displayed or edited, and is set to undefined when no data is available or when an
11984
- * error occurs during data loading.
11985
- * @type {KeyValue | undefined}
11986
- * @default undefined
11987
- * @memberOf NgxModelPageDirective
11988
- */
12113
+ this.allowedOperations = [
12114
+ OperationKeys.CREATE,
12115
+ OperationKeys.READ,
12116
+ ];
12117
+ /**
12118
+ * @description Current model data loaded from the repository.
12119
+ * @summary Stores the raw data object representing the current model instance retrieved
12120
+ * from the repository. This property holds the actual data values for the model being
12121
+ * displayed or edited, and is set to undefined when no data is available or when an
12122
+ * error occurs during data loading.
12123
+ * @type {KeyValue | undefined}
12124
+ * @default undefined
12125
+ * @memberOf NgxModelPageDirective
12126
+ */
11989
12127
  this.modelData = undefined;
11990
12128
  /**
11991
12129
  * @description Error message from failed operations.
@@ -12003,12 +12141,12 @@ class NgxModelPageDirective extends NgxPageDirective {
12003
12141
  // }
12004
12142
  get pageTitle() {
12005
12143
  if (!this.modelName && this.model instanceof Model)
12006
- this.modelName = this.model?.constructor?.name || "";
12144
+ this.modelName = this.model?.constructor?.name || '';
12007
12145
  if (!this.operation)
12008
12146
  return this.title ? this.title : `Listing ${this.modelName}`;
12009
- const operation = this.operation.charAt(0).toUpperCase() + this.operation.slice(1).toLowerCase();
12010
- return this.modelName ?
12011
- `${operation} ${this.modelName}` : this.title;
12147
+ const operation = this.operation.charAt(0).toUpperCase() +
12148
+ this.operation.slice(1).toLowerCase();
12149
+ return this.modelName ? `${operation} ${this.modelName}` : this.title;
12012
12150
  }
12013
12151
  /**
12014
12152
  * @description Lazy-initialized repository getter with model resolution.
@@ -12029,7 +12167,7 @@ class NgxModelPageDirective extends NgxPageDirective {
12029
12167
  throw new InternalError('Cannot find model. was it registered with @model?');
12030
12168
  this._repository = Repository.forModel(constructor);
12031
12169
  if (!this.pk)
12032
- this.pk = this._repository.pk;
12170
+ this.pk = Model.pk(constructor);
12033
12171
  this.model = new constructor();
12034
12172
  }
12035
12173
  }
@@ -12049,7 +12187,10 @@ class NgxModelPageDirective extends NgxPageDirective {
12049
12187
  async ionViewWillEnter() {
12050
12188
  // await super.ionViewWillEnter();
12051
12189
  if (this.modelId)
12052
- this.allowedOperations = this.allowedOperations.concat([OperationKeys.UPDATE, OperationKeys.DELETE]);
12190
+ this.allowedOperations = this.allowedOperations.concat([
12191
+ OperationKeys.UPDATE,
12192
+ OperationKeys.DELETE,
12193
+ ]);
12053
12194
  this.getLocale(this.modelName);
12054
12195
  await this.refresh(this.modelId);
12055
12196
  this.initialized = true;
@@ -12066,29 +12207,37 @@ class NgxModelPageDirective extends NgxPageDirective {
12066
12207
  async refresh(uid) {
12067
12208
  if (!uid)
12068
12209
  uid = this.modelId;
12069
- this._repository = this.repository;
12070
- switch (this.operation) {
12071
- case OperationKeys.READ:
12072
- case OperationKeys.UPDATE:
12073
- case OperationKeys.DELETE:
12074
- this.model = await this.handleGet(uid || this.modelId, this._repository, this.modelName);
12075
- break;
12210
+ try {
12211
+ this._repository = this.repository;
12212
+ switch (this.operation) {
12213
+ case OperationKeys.READ:
12214
+ case OperationKeys.UPDATE:
12215
+ case OperationKeys.DELETE:
12216
+ this.model = (await this.handleGet(uid || this.modelId));
12217
+ break;
12218
+ }
12219
+ }
12220
+ catch (error) {
12221
+ if (error instanceof NotFoundError) {
12222
+ this.errorMessage = error.message;
12223
+ }
12224
+ this.log.error(error);
12076
12225
  }
12077
12226
  }
12078
12227
  /**
12079
12228
  * @description Generic event handler for component events.
12080
12229
  * @summary Processes incoming events from child components and routes them to appropriate
12081
12230
  * handlers based on the event name. Currently handles SUBMIT events by delegating to
12082
- * the handleSubmit method. This centralized event handling approach allows for easy
12231
+ * the submit method. This centralized event handling approach allows for easy
12083
12232
  * extension and consistent event processing.
12084
12233
  *
12085
12234
  * @param {IBaseCustomEvent} event - The event object containing event data and metadata
12086
12235
  */
12087
- async handleEvent(event) {
12236
+ async handleEvent(event, repository) {
12088
12237
  const { name } = event;
12089
12238
  switch (name) {
12090
12239
  case ComponentEventNames.SUBMIT:
12091
- await this.handleSubmit(event);
12240
+ await this.submit(event, repository);
12092
12241
  break;
12093
12242
  }
12094
12243
  }
@@ -12103,38 +12252,61 @@ class NgxModelPageDirective extends NgxPageDirective {
12103
12252
  * @param {IBaseCustomEvent} event - The submit event containing form data
12104
12253
  * @return {Promise<IModelPageCustomEvent|void>} Promise that resolves on success or throws on error
12105
12254
  */
12106
- async handleSubmit(event, redirect = false) {
12255
+ async submit(event, repository, redirect = false) {
12107
12256
  try {
12108
- const repo = this._repository;
12109
- const operation = this.operation === OperationKeys.READ ? 'delete' : this.operation.toLowerCase();
12110
- const data = this.parseData(event.data, operation);
12111
- const result = this.operation === OperationKeys.CREATE ?
12112
- await repo.create(data) : this.operation === OperationKeys.UPDATE ?
12113
- await repo.update(data) : repo.delete(data);
12114
- const message = await this.translate(`operations.${operation}.${result ? 'success' : 'error'}`, {
12115
- "0": this.pk,
12116
- "1": this.modelId || result[this.pk],
12117
- });
12118
- if (result) {
12119
- repo.refresh(this.modelName, this.operation, this.modelId);
12120
- if (redirect)
12121
- this.location.back();
12257
+ if (!repository)
12258
+ repository = this._repository;
12259
+ // const pk = this.pk || Model.pk(repository.class as Constructor<Model>);
12260
+ const operation = this.operation;
12261
+ const { data } = event;
12262
+ if (data) {
12263
+ const model = this.parseData(data || {}, operation, repository);
12264
+ let result;
12265
+ switch (operation) {
12266
+ case OperationKeys.CREATE:
12267
+ result = await (!Array.isArray(model)
12268
+ ? repository.create(model)
12269
+ : repository.createAll(model));
12270
+ break;
12271
+ case OperationKeys.UPDATE:
12272
+ result = await (!Array.isArray(model)
12273
+ ? repository.update(model)
12274
+ : repository.updateAll(model));
12275
+ break;
12276
+ case OperationKeys.DELETE:
12277
+ result = await (!Array.isArray(model)
12278
+ ? repository.delete(model)
12279
+ : repository.deleteAll(model));
12280
+ break;
12281
+ }
12282
+ const message = await this.translate(!Array.isArray(result)
12283
+ ? `operations.${operation}.${result ? 'success' : 'error'}`
12284
+ : `operations.multiple`);
12285
+ if (result) {
12286
+ // repository.refresh(this.modelName, this.operation, this.modelId as EventIds);
12287
+ if (redirect)
12288
+ this.location.back();
12289
+ }
12290
+ return {
12291
+ ...event,
12292
+ success: result ? true : false,
12293
+ message,
12294
+ };
12122
12295
  }
12123
- return {
12124
- ...event,
12125
- success: result ? true : false,
12126
- message
12127
- };
12128
12296
  }
12129
12297
  catch (error) {
12130
- this.log.error(error);
12131
12298
  return {
12132
12299
  ...event,
12133
12300
  success: false,
12134
- message: error instanceof Error ? error.message : error
12301
+ message: error instanceof Error ? error.message : error,
12135
12302
  };
12136
12303
  }
12137
12304
  }
12305
+ async create(data, repository) {
12306
+ alert('create');
12307
+ console.log(repository);
12308
+ console.log(data);
12309
+ }
12138
12310
  /**
12139
12311
  * @description Retrieves a model instance from the repository by unique identifier.
12140
12312
  * @summary Fetches a specific model instance using the repository's read method.
@@ -12151,14 +12323,15 @@ class NgxModelPageDirective extends NgxPageDirective {
12151
12323
  this.location.back();
12152
12324
  return undefined;
12153
12325
  }
12326
+ if (!modelName)
12327
+ modelName = this.modelName;
12154
12328
  const getRepository = async (modelName, parent, model) => {
12155
12329
  if (this._repository)
12156
12330
  return this._repository;
12157
12331
  const constructor = Model.get(modelName);
12158
12332
  if (constructor) {
12159
12333
  const properties = Metadata.properties(constructor);
12160
- if (!model)
12161
- model = {};
12334
+ // if (!model) model = {} as KeyValue;
12162
12335
  for (const prop of properties) {
12163
12336
  const type = Metadata.type(constructor, prop).name;
12164
12337
  const context = getModelAndRepository(type);
@@ -12169,23 +12342,31 @@ class NgxModelPageDirective extends NgxPageDirective {
12169
12342
  const data = await this.handleGet(uid, repository, modelName);
12170
12343
  this.model = Model.build({ [prop]: data }, modelName);
12171
12344
  }
12172
- else {
12173
- model[prop] = Model.build({}, type);
12174
- }
12345
+ // else {
12346
+ // model[prop as string] = Model.build({}, type);
12347
+ // }
12175
12348
  }
12176
- this.model[parent] = Model.build(model, modelName);
12349
+ // (this.model as KeyValue)[parent as string] = Model.build(
12350
+ // model,
12351
+ // modelName
12352
+ // );
12177
12353
  }
12178
12354
  };
12179
- repository = (repository || await getRepository(modelName));
12355
+ repository = (repository ||
12356
+ (await getRepository(modelName)));
12180
12357
  if (!repository)
12181
12358
  return this.model;
12182
- const type = Metadata.type(repository.class, repository.pk).name;
12359
+ const type = Metadata.type(repository.class, Model.pk(repository.class)).name;
12183
12360
  try {
12184
- const result = await repository.read(([Primitives.NUMBER, Primitives.BIGINT].includes(type.toLowerCase()) ? Number(uid) : uid));
12361
+ const result = await (repository).read(([Primitives.NUMBER, Primitives.BIGINT].includes(type.toLowerCase())
12362
+ ? Number(uid)
12363
+ : uid));
12185
12364
  return result;
12186
12365
  }
12187
12366
  catch (error) {
12188
- this.log.for(this.handleGet).info(`Error getting model instance with id ${uid}: ${error.message}`);
12367
+ this.log
12368
+ .for(this.handleGet)
12369
+ .info(`Error getting model instance with id ${uid}: ${error.message}`);
12189
12370
  return undefined;
12190
12371
  }
12191
12372
  }
@@ -12200,13 +12381,22 @@ class NgxModelPageDirective extends NgxPageDirective {
12200
12381
  * @return {Model | string | number} Processed data ready for repository operations
12201
12382
  * @private
12202
12383
  */
12203
- parseData(data, operation) {
12204
- const repo = this._repository;
12384
+ parseData(data, operation, repository) {
12385
+ operation = (operation === OperationKeys.READ
12386
+ ? OperationKeys.DELETE
12387
+ : operation.toLowerCase());
12388
+ if (Array.isArray(data)) {
12389
+ data = data.map((item) => this.parseData(item, operation, repository));
12390
+ return data;
12391
+ }
12205
12392
  let uid = this.modelId;
12206
- if (repo.pk === 'id')
12207
- uid = Number(uid);
12393
+ const pk = Model.pk(repository.class);
12394
+ const type = Metadata.type(repository.class, pk).name;
12395
+ uid = [Primitives.NUMBER, Primitives.BIGINT].includes(type.toLowerCase())
12396
+ ? Number(uid)
12397
+ : uid;
12208
12398
  if (operation !== OperationKeys.DELETE)
12209
- return Model.build(this.modelId ? Object.assign(data, { [repo.pk]: uid }) : data, this.modelName);
12399
+ return Model.build(this.modelId ? Object.assign(data, { [pk]: uid }) : data, repository.class.name);
12210
12400
  return uid;
12211
12401
  }
12212
12402
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.9", ngImport: i0, type: NgxModelPageDirective, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }