xt-components 0.4.1 → 0.4.4

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,8 +1,10 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { computed, signal, InjectionToken, inject, Injectable, input, model, output, viewChild, Component } from '@angular/core';
3
- import * as i1 from '@angular/forms';
4
- import { FormControl, FormGroup, ReactiveFormsModule, FormBuilder, FormArray } from '@angular/forms';
3
+ import { xtTypeManager, ManagedDataHandler, isPrimitive } from 'xt-type';
4
+ import { loadRemoteModule } from '@angular-architects/native-federation';
5
5
  import { NgComponentOutlet, CommonModule } from '@angular/common';
6
+ import * as i1 from '@angular/forms';
7
+ import { ReactiveFormsModule, FormControl, FormGroup, FormBuilder, FormArray } from '@angular/forms';
6
8
 
7
9
  class XtBaseContext {
8
10
  /**
@@ -118,6 +120,18 @@ class XtBaseContext {
118
120
  //console.debug("formControlValue of "+this.subName+ " is ",ret);
119
121
  return ret;
120
122
  }
123
+ setFormValue(newValue) {
124
+ if (this.isInForm()) {
125
+ if (this.subName != null) {
126
+ const control = this.parentFormGroup?.get(this.subName);
127
+ if (control != null) {
128
+ control.setValue(newValue);
129
+ return true;
130
+ }
131
+ }
132
+ }
133
+ return false;
134
+ }
121
135
  /**
122
136
  * Returns the context associated with a specific element in a set.
123
137
  * Value must be an array.
@@ -165,7 +179,7 @@ class XtBaseContext {
165
179
  ret.valueType = subType;
166
180
  }
167
181
  else if ((this.valueType != null) && (typeResolver != null)) {
168
- ret.valueType = typeResolver.findType(this, subName, this.value()) ?? undefined;
182
+ ret.valueType = typeResolver.findTypeName(this.valueType, subName, this.value()) ?? undefined;
169
183
  }
170
184
  if (this.childContexts == null)
171
185
  this.childContexts = new Map();
@@ -208,6 +222,7 @@ class XtPluginRegistry {
208
222
  this.componentRegistry = new Map();
209
223
  this.componentByTypeCache = new Map();
210
224
  this.listComponents = signal(new Array());
225
+ this.listPlugins = signal(new Array());
211
226
  }
212
227
  /**
213
228
  * The component can manage any standard javascript primitives types. That's usually the default whenever we don't know any particular type
@@ -238,6 +253,18 @@ class XtPluginRegistry {
238
253
  if (updated)
239
254
  this.componentByTypeCache.clear(); // Force recalculation of type
240
255
  }
256
+ this.listPlugins.update((array) => {
257
+ let found = false;
258
+ for (let i = 0; i < array.length; i++) {
259
+ if (array[i].name == info.name) {
260
+ found = true;
261
+ array[i] = info;
262
+ }
263
+ }
264
+ if (!found)
265
+ array.push(info);
266
+ return [...array]; // You have to send another value, not just update the existing one.
267
+ });
241
268
  }
242
269
  registerComponent(info) {
243
270
  this.componentRegistry.set(info.componentName, info);
@@ -325,13 +352,28 @@ class XtPluginRegistry {
325
352
  return ret;
326
353
  }
327
354
  }
328
- const XT_REGISTRY = new XtPluginRegistry();
355
+
356
+ /**
357
+ * The global plugin registry.
358
+ * Plugins will register to this when loaded.
359
+ */
360
+ function initXtPluginRegistry() {
361
+ if (globalThis.XT_REGISTRY == null) {
362
+ globalThis.XT_REGISTRY = new XtPluginRegistry();
363
+ }
364
+ }
365
+ function xtPluginRegistry() {
366
+ if (globalThis.XT_REGISTRY == null) {
367
+ initXtPluginRegistry();
368
+ }
369
+ return globalThis.XT_REGISTRY;
370
+ }
329
371
 
330
372
  const XT_RESOLVER_TOKEN = new InjectionToken('Enable providing a custom component resolver.');
331
373
  const XT_TYPE_RESOLVER_TOKEN = new InjectionToken('Enable providing a custom type resolver.');
332
374
  const XT_REGISTRY_TOKEN = new InjectionToken("Injects the Plugin Registry right into your angular component", {
333
375
  factory: () => {
334
- return XT_REGISTRY;
376
+ return xtPluginRegistry();
335
377
  }
336
378
  });
337
379
 
@@ -341,7 +383,7 @@ class XtRegistryResolver {
341
383
  this.typeResolver = typeResolver;
342
384
  }
343
385
  resolve(baseContext, subName) {
344
- const ret = this.registry.findComponentsForType(this.typeResolver.findType(baseContext, subName), baseContext.subValue(subName));
386
+ const ret = this.registry.findComponentsForType(this.typeResolver.findTypeName(baseContext.valueType, subName), baseContext.subValue(subName));
345
387
  if (ret != null && ret.length > 0) {
346
388
  return XtResolvedComponent.from(ret[0]);
347
389
  }
@@ -349,158 +391,6 @@ class XtRegistryResolver {
349
391
  }
350
392
  }
351
393
 
352
- class XtTypeHierarchyResolver {
353
- constructor() {
354
- this.types = new Map();
355
- }
356
- addType(typeName, type) {
357
- this.types.set(typeName, fromDescription(type));
358
- }
359
- canUpdate() {
360
- return true;
361
- }
362
- findType(typeInfo, subName, value) {
363
- if (typeInfo == null)
364
- return typeInfo;
365
- if (typeInfo.valueType == null)
366
- return typeInfo.valueType;
367
- if (subName == null) {
368
- return typeInfo.valueType;
369
- }
370
- else {
371
- const selectedType = this.types.get(typeInfo.valueType);
372
- if ((selectedType != null) && (selectedType.children != null)) {
373
- const type = selectedType.children[subName].type;
374
- if (type == null) {
375
- throw new Error('SubType named ' + subName + ' of ' + typeInfo.valueType + ' doesn\'t have a type name.');
376
- }
377
- else {
378
- return type;
379
- }
380
- }
381
- }
382
- return undefined;
383
- }
384
- listSubNames(context, value) {
385
- let ret = [];
386
- if ((context != null) && (context.valueType != null)) {
387
- const typeInfo = this.types.get(context.valueType);
388
- if (typeInfo?.children != null) {
389
- ret = Object.keys(typeInfo.children);
390
- }
391
- }
392
- if (ret.length == 0) {
393
- // We will use the value to extract properties
394
- if (value != null) {
395
- if (Array.isArray(value)) {
396
- if (value.length > 0) {
397
- const setOfKeys = new Set();
398
- for (const element of value) {
399
- const elementKeys = Object.keys(element);
400
- for (const key of elementKeys) {
401
- setOfKeys.add(key);
402
- }
403
- }
404
- ret = Array.from(setOfKeys.values());
405
- }
406
- }
407
- else {
408
- ret = Object.keys(value);
409
- }
410
- }
411
- }
412
- return ret;
413
- }
414
- }
415
- class XtBaseTypeHierarchy {
416
- constructor(type, parent) {
417
- this.type = type;
418
- this.parent = parent;
419
- }
420
- addChild(key, child) {
421
- if (this.children == null)
422
- this.children = {};
423
- this.children[key] = child;
424
- }
425
- }
426
- function fromDescription(typeHierarchy, name, parent) {
427
- let ret = null;
428
- if (typeof typeHierarchy == 'string') {
429
- ret = new XtBaseTypeHierarchy(typeHierarchy, parent);
430
- }
431
- else {
432
- ret = new XtBaseTypeHierarchy(undefined, parent);
433
- for (const key of Object.keys(typeHierarchy)) {
434
- const value = typeHierarchy[key];
435
- fromDescription(value, key, ret);
436
- }
437
- }
438
- if ((parent != null) && (name != null))
439
- parent.addChild(name, ret);
440
- else if ((parent != null) && (name == null)) {
441
- throw new Error("Cannot add type to parent without a name.");
442
- }
443
- return ret;
444
- }
445
- function updateFormGroupWithValue(formGroup, value) {
446
- const toDelete = new Set(Object.keys(formGroup.controls));
447
- for (const valueKey in value) {
448
- const primitive = isPrimitive(value[valueKey]);
449
- if (toDelete.delete(valueKey)) {
450
- // Already a control
451
- const oldControl = formGroup.get(valueKey);
452
- // Is it the right type ?
453
- if (primitive) {
454
- // Must be an FormControl2
455
- if (oldControl.controls === undefined) {
456
- // It's ok, just set the value
457
- oldControl.setValue(value[valueKey]);
458
- }
459
- else {
460
- formGroup.setControl(valueKey, new FormControl(value[valueKey]));
461
- }
462
- }
463
- else {
464
- // Must be a FormGroup
465
- if (oldControl.controls === undefined) {
466
- const newFormGroup = new FormGroup({});
467
- formGroup.setControl(valueKey, newFormGroup);
468
- updateFormGroupWithValue(newFormGroup, value[valueKey]);
469
- }
470
- else {
471
- // It was already a formgroup, so just update it
472
- updateFormGroupWithValue(oldControl, value[valueKey]);
473
- }
474
- }
475
- }
476
- else {
477
- if (primitive) {
478
- formGroup.addControl(valueKey, new FormControl(value[valueKey]));
479
- }
480
- else {
481
- const newFormGroup = new FormGroup({});
482
- formGroup.addControl(valueKey, newFormGroup);
483
- updateFormGroupWithValue(newFormGroup, value[valueKey]);
484
- }
485
- }
486
- }
487
- // Delete controls that are no more used
488
- for (const delName of toDelete) {
489
- formGroup.removeControl(delName);
490
- }
491
- }
492
- function isPrimitive(valueElement) {
493
- if (typeof valueElement == 'object') {
494
- if (valueElement == null)
495
- return true;
496
- else {
497
- return valueElement instanceof Date;
498
- }
499
- }
500
- else
501
- return true;
502
- }
503
-
504
394
  class XtResolverService {
505
395
  constructor() {
506
396
  this.pluginRegistry = inject(XT_REGISTRY_TOKEN);
@@ -509,8 +399,11 @@ class XtResolverService {
509
399
  this.listComponents = computed(() => {
510
400
  return this.pluginRegistry.listComponents();
511
401
  });
402
+ this.listPlugins = computed(() => {
403
+ return this.pluginRegistry.listPlugins();
404
+ });
512
405
  if (this.baseTypeResolver == null) {
513
- this.typeResolver = new XtTypeHierarchyResolver();
406
+ this.typeResolver = xtTypeManager();
514
407
  }
515
408
  else
516
409
  this.typeResolver = this.baseTypeResolver;
@@ -528,23 +421,39 @@ class XtResolverService {
528
421
  throw new Error("No components found for this context " + baseContext.toString());
529
422
  }
530
423
  findTypeOf(baseContext, subName, value) {
531
- const ret = this.typeResolver.findType(baseContext, subName, value);
424
+ const ret = this.typeResolver.findTypeName(baseContext.valueType, subName, value);
425
+ return ret;
426
+ }
427
+ findTypeHandlerOf(baseContext, subName, value) {
428
+ const ret = this.typeResolver.findTypeHandler(baseContext.valueType, subName, value);
532
429
  return ret;
533
430
  }
534
431
  listSubNamesOf(baseContext, value) {
535
- return this.typeResolver.listSubNames(baseContext, value);
432
+ return this.typeResolver.listSubNames(baseContext.valueType, value);
536
433
  }
537
434
  registerPlugin(info) {
538
435
  this.pluginRegistry.registerPlugin(info);
539
- this.registerTypes(info.types);
436
+ this.registerTypes(info.types, info.typeHandlers);
540
437
  }
541
- registerTypes(types) {
438
+ registerTypes(types, handlers) {
542
439
  if ((types != null) && (this.typeResolver.canUpdate())) {
543
440
  for (const newType in types) {
544
- this.typeResolver.addType(newType, types[newType]);
441
+ let handler = this.handlerDefinedFor(newType, handlers);
442
+ if (handler == null) {
443
+ handler = new ManagedDataHandler();
444
+ }
445
+ this.typeResolver.addRootType(newType, types[newType], handler);
545
446
  }
546
447
  }
547
448
  }
449
+ handlerDefinedFor(newType, handlers) {
450
+ for (const handler of handlers ?? []) {
451
+ if (handler.typesHandled.includes(newType)) {
452
+ return new handler.handlerClass();
453
+ }
454
+ }
455
+ return null;
456
+ }
548
457
  getComponentInfo(type) {
549
458
  return XtResolvedComponent.from(this.pluginRegistry.getComponentInfo(type));
550
459
  }
@@ -555,16 +464,34 @@ class XtResolverService {
555
464
  else
556
465
  return XtResolvedComponent.from(ret);
557
466
  }
558
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtResolverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
559
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtResolverService, providedIn: 'root' }); }
467
+ /**
468
+ * Dynamically load a register a plugin from the given url
469
+ * The plugin must export at least a Register entrypoint that will be called right after loading..
470
+ * @param url
471
+ * @returns a Promise with the module loaded and already registered.
472
+ */
473
+ loadPlugin(url) {
474
+ return loadRemoteModule({
475
+ remoteEntry: url.toString(),
476
+ exposedModule: './Register'
477
+ }).then((module) => {
478
+ module.registerPlugin(this);
479
+ return module;
480
+ });
481
+ }
482
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtResolverService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
483
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtResolverService, providedIn: 'root' }); }
560
484
  }
561
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtResolverService, decorators: [{
485
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtResolverService, decorators: [{
562
486
  type: Injectable,
563
487
  args: [{
564
488
  providedIn: 'root'
565
489
  }]
566
490
  }], ctorParameters: () => [] });
567
491
 
492
+ class XtBaseOutput {
493
+ }
494
+
568
495
  /**
569
496
  * Offers a nice and easy to dynamically embed a component.
570
497
  * You set the type, the display mode, and either the value or the formgroup & subName to use.
@@ -581,8 +508,9 @@ class XtRenderComponent {
581
508
  // Or we are inside a Form
582
509
  this.formGroup = input();
583
510
  this.subName = input();
511
+ this.outputsObject = new XtBaseOutput();
512
+ this.inputs = input();
584
513
  this.outputs = output();
585
- this.hasOutputs = false;
586
514
  this.outlet = viewChild.required(NgComponentOutlet);
587
515
  this.context = computed(() => {
588
516
  let form = this.formGroup();
@@ -615,17 +543,32 @@ class XtRenderComponent {
615
543
  return type ?? null;
616
544
  });
617
545
  }
546
+ /**
547
+ * Transfers the input and outputs from the host to the rendered component
548
+ */
618
549
  ngAfterViewInit() {
619
550
  const instance = this.outlet().componentInstance;
620
- if ((instance != null) && (instance.hasOutputs) && (instance.outputs != null)) {
621
- instance.outputs.subscribe((out) => this.outputs.emit(out));
622
- this.hasOutputs = true;
551
+ if (instance?.outputsObject != null) {
552
+ let hasOneOutput = false;
553
+ for (const key of Object.keys(instance.outputsObject)) {
554
+ this.outputsObject[key] = instance.outputsObject[key];
555
+ hasOneOutput = true;
556
+ }
557
+ if (hasOneOutput) {
558
+ this.outputs.emit(this.outputsObject);
559
+ }
560
+ }
561
+ const inputs = this.inputs();
562
+ if ((inputs != null) && (instance?.inputsObject != null)) {
563
+ for (const key of Object.keys(inputs)) {
564
+ instance.inputsObject[key] = inputs[key];
565
+ }
623
566
  }
624
567
  }
625
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtRenderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
626
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.4", type: XtRenderComponent, isStandalone: true, selector: "xt-render", inputs: { componentType: { classPropertyName: "componentType", publicName: "componentType", isSignal: true, isRequired: false, transformFunction: null }, displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: true, transformFunction: null }, valueType: { classPropertyName: "valueType", publicName: "valueType", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: false, transformFunction: null }, subName: { classPropertyName: "subName", publicName: "subName", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", outputs: "outputs" }, viewQueries: [{ propertyName: "outlet", first: true, predicate: NgComponentOutlet, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *ngComponentOutlet=\"type(); inputs: {context:context ()}\" />\n", styles: [""], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: ReactiveFormsModule }] }); }
568
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtRenderComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
569
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.10", type: XtRenderComponent, isStandalone: true, selector: "xt-render", inputs: { componentType: { classPropertyName: "componentType", publicName: "componentType", isSignal: true, isRequired: false, transformFunction: null }, displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: true, transformFunction: null }, valueType: { classPropertyName: "valueType", publicName: "valueType", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: false, transformFunction: null }, subName: { classPropertyName: "subName", publicName: "subName", isSignal: true, isRequired: false, transformFunction: null }, inputs: { classPropertyName: "inputs", publicName: "inputs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", outputs: "outputs" }, viewQueries: [{ propertyName: "outlet", first: true, predicate: NgComponentOutlet, descendants: true, isSignal: true }], ngImport: i0, template: "<ng-container *ngComponentOutlet=\"type(); inputs: {context:context ()}\" />\n", styles: [""], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: ReactiveFormsModule }] }); }
627
570
  }
628
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtRenderComponent, decorators: [{
571
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtRenderComponent, decorators: [{
629
572
  type: Component,
630
573
  args: [{ selector: 'xt-render', standalone: true, imports: [
631
574
  NgComponentOutlet,
@@ -641,8 +584,9 @@ class XtRenderSubComponent {
641
584
  constructor() {
642
585
  this.context = input.required();
643
586
  this.componentType = input();
587
+ this.outputsObject = new XtBaseOutput();
588
+ this.inputs = input();
644
589
  this.outputs = output();
645
- this.hasOutputs = false;
646
590
  this.outlet = viewChild.required(NgComponentOutlet);
647
591
  this.resolverService = inject(XtResolverService);
648
592
  this.type = computed(() => {
@@ -660,17 +604,32 @@ class XtRenderSubComponent {
660
604
  return type ?? null;
661
605
  });
662
606
  }
607
+ /**
608
+ * Transfers the input and outputs from the host to the rendered component
609
+ */
663
610
  ngAfterViewInit() {
664
611
  const instance = this.outlet().componentInstance;
665
- if ((instance != null) && (instance.hasOutputs) && (instance.outputs != null)) {
666
- instance.outputs.subscribe((out) => this.outputs.emit(out));
667
- this.hasOutputs = true;
612
+ if (instance?.outputsObject != null) {
613
+ let hasOneOutput = false;
614
+ for (const key of Object.keys(instance.outputsObject)) {
615
+ this.outputsObject[key] = instance.outputsObject[key];
616
+ hasOneOutput = true;
617
+ }
618
+ if (hasOneOutput) {
619
+ this.outputs.emit(this.outputsObject);
620
+ }
621
+ }
622
+ const inputs = this.inputs();
623
+ if ((inputs != null) && (instance?.inputsObject != null)) {
624
+ for (const key of Object.keys(inputs)) {
625
+ instance.inputsObject[key] = inputs[key];
626
+ }
668
627
  }
669
628
  }
670
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtRenderSubComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
671
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.4", type: XtRenderSubComponent, isStandalone: true, selector: "xt-render-sub", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: true, transformFunction: null }, componentType: { classPropertyName: "componentType", publicName: "componentType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { outputs: "outputs" }, viewQueries: [{ propertyName: "outlet", first: true, predicate: NgComponentOutlet, descendants: true, isSignal: true }], ngImport: i0, template: "{{componentType()}}\n<ng-container *ngComponentOutlet=\"type(); inputs: {context:context ()}\" />\n", styles: [""], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: ReactiveFormsModule }] }); }
629
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtRenderSubComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
630
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "19.2.10", type: XtRenderSubComponent, isStandalone: true, selector: "xt-render-sub", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: true, transformFunction: null }, componentType: { classPropertyName: "componentType", publicName: "componentType", isSignal: true, isRequired: false, transformFunction: null }, inputs: { classPropertyName: "inputs", publicName: "inputs", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { outputs: "outputs" }, viewQueries: [{ propertyName: "outlet", first: true, predicate: NgComponentOutlet, descendants: true, isSignal: true }], ngImport: i0, template: "{{componentType()}}\n<ng-container *ngComponentOutlet=\"type(); inputs: {context:context ()}\" />\n", styles: [""], dependencies: [{ kind: "directive", type: NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }, { kind: "ngmodule", type: ReactiveFormsModule }] }); }
672
631
  }
673
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtRenderSubComponent, decorators: [{
632
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtRenderSubComponent, decorators: [{
674
633
  type: Component,
675
634
  args: [{ selector: 'xt-render-sub', standalone: true, imports: [
676
635
  NgComponentOutlet,
@@ -678,18 +637,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImpor
678
637
  ], template: "{{componentType()}}\n<ng-container *ngComponentOutlet=\"type(); inputs: {context:context ()}\" />\n" }]
679
638
  }] });
680
639
 
681
- class XtBaseOutput {
682
- setNewOutput(name, value) {
683
- let ret = false;
684
- if (this[name] == null) {
685
- this[name] = signal(value);
686
- ret = true;
687
- }
688
- else {
689
- this[name].set(value);
690
- }
691
- return ret;
692
- }
640
+ class XtBaseInput {
693
641
  }
694
642
 
695
643
  /**
@@ -699,12 +647,9 @@ class XtBaseOutput {
699
647
  class XtSimpleComponent {
700
648
  constructor() {
701
649
  this.context = input.required();
650
+ this.outputsObject = new XtBaseOutput();
651
+ this.inputsObject = new XtBaseInput();
702
652
  this.outputs = output();
703
- /**
704
- * Does the component provides Output or not ?
705
- * @protected
706
- */
707
- this.hasOutputs = false;
708
653
  this.isInForm = computed(() => {
709
654
  return this.context()?.isInForm() ?? false;
710
655
  });
@@ -753,10 +698,12 @@ class XtSimpleComponent {
753
698
  this.displayValue = computed(() => {
754
699
  return this.context().displayValue();
755
700
  });
756
- if (this.hasOutputs) {
757
- if (this.outputElement == null) {
758
- this.outputElement = new XtBaseOutput();
759
- }
701
+ }
702
+ ngOnInit() {
703
+ this.setupInputOutput();
704
+ if (Object.keys(this.outputsObject).length > 0) {
705
+ // At least one output has been defined
706
+ this.outputs.emit(this.outputsObject);
760
707
  }
761
708
  }
762
709
  manageFormControl(ctrlName) {
@@ -778,24 +725,17 @@ class XtSimpleComponent {
778
725
  componentDescriptor() {
779
726
  return "Component with type " + this.constructor.name + " with context " + this.context().toString();
780
727
  }
781
- emitOutput(outputName, newValue) {
782
- if (!this.hasOutputs) {
783
- throw new Error("Component without outputs cannot emit output");
784
- }
785
- let newOutput = false;
786
- if (this.outputElement == null) {
787
- this.outputElement = new XtBaseOutput();
788
- newOutput = true;
789
- }
790
- newOutput = this.outputElement.setNewOutput(outputName, newValue) || newOutput;
791
- if (newOutput) {
792
- this.outputs?.emit(this.outputElement);
793
- }
728
+ /**
729
+ * This is where components can assign their output() and input() into the XtComponent inputs and outputs member
730
+ * @protected
731
+ */
732
+ setupInputOutput() {
733
+ // Nothing to do here
794
734
  }
795
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtSimpleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
796
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.4", type: XtSimpleComponent, isStandalone: true, selector: "ng-component", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { outputs: "outputs" }, ngImport: i0, template: '', isInline: true }); }
735
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtSimpleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
736
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.10", type: XtSimpleComponent, isStandalone: true, selector: "ng-component", inputs: { context: { classPropertyName: "context", publicName: "context", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { outputs: "outputs" }, ngImport: i0, template: '', isInline: true }); }
797
737
  }
798
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtSimpleComponent, decorators: [{
738
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtSimpleComponent, decorators: [{
799
739
  type: Component,
800
740
  args: [{
801
741
  standalone: true,
@@ -844,14 +784,93 @@ class XtCompositeComponent extends XtSimpleComponent {
844
784
  this.formGroupIfAny(); // Ensure the context is properly initialized
845
785
  return this.context().subContext(subName, subType, this.resolverService.typeResolver);
846
786
  }
847
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtCompositeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
848
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.4", type: XtCompositeComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: '', isInline: true, styles: [""] }); }
787
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtCompositeComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
788
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.10", type: XtCompositeComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: '', isInline: true, styles: [""] }); }
849
789
  }
850
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: XtCompositeComponent, decorators: [{
790
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: XtCompositeComponent, decorators: [{
851
791
  type: Component,
852
792
  args: [{ standalone: true, imports: [], template: '' }]
853
793
  }] });
854
794
 
795
+ class MessageHandler {
796
+ errorOccurred(error, errorMsg) {
797
+ console.error(errorMsg, error);
798
+ }
799
+ warningOccurred(warningMsg) {
800
+ console.warn(warningMsg);
801
+ }
802
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: MessageHandler, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
803
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: MessageHandler, providedIn: 'root' }); }
804
+ }
805
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: MessageHandler, decorators: [{
806
+ type: Injectable,
807
+ args: [{
808
+ providedIn: 'root'
809
+ }]
810
+ }] });
811
+
812
+ class StoreSupport {
813
+ static isStoreManagerAvailable() {
814
+ if (this.testStoreManager != null)
815
+ return true;
816
+ return (globalThis.xtStoreManager != undefined);
817
+ }
818
+ static getStoreManager() {
819
+ return this.testStoreManager ?? (globalThis.xtStoreManager());
820
+ }
821
+ static setTestStoreManager(testStoreManager) {
822
+ StoreSupport.testStoreManager = testStoreManager;
823
+ }
824
+ }
825
+
826
+ function updateFormGroupWithValue(formGroup, value) {
827
+ const toDelete = new Set(Object.keys(formGroup.controls));
828
+ for (const valueKey in value) {
829
+ const primitive = isPrimitive(value[valueKey]);
830
+ if (toDelete.delete(valueKey)) {
831
+ // Already a control
832
+ const oldControl = formGroup.get(valueKey);
833
+ // Is it the right type ?
834
+ if (primitive) {
835
+ // Must be an FormControl2
836
+ if (oldControl.controls === undefined) {
837
+ // It's ok, just set the value
838
+ oldControl.setValue(value[valueKey]);
839
+ }
840
+ else {
841
+ formGroup.setControl(valueKey, new FormControl(value[valueKey]));
842
+ }
843
+ }
844
+ else {
845
+ // Must be a FormGroup
846
+ if (oldControl.controls === undefined) {
847
+ const newFormGroup = new FormGroup({});
848
+ formGroup.setControl(valueKey, newFormGroup);
849
+ updateFormGroupWithValue(newFormGroup, value[valueKey]);
850
+ }
851
+ else {
852
+ // It was already a formgroup, so just update it
853
+ updateFormGroupWithValue(oldControl, value[valueKey]);
854
+ }
855
+ }
856
+ }
857
+ else {
858
+ if (primitive) {
859
+ formGroup.addControl(valueKey, new FormControl(value[valueKey]));
860
+ }
861
+ else {
862
+ const newFormGroup = new FormGroup({});
863
+ formGroup.addControl(valueKey, newFormGroup);
864
+ updateFormGroupWithValue(newFormGroup, value[valueKey]);
865
+ }
866
+ }
867
+ }
868
+ // Delete controls that are no more used
869
+ for (const delName of toDelete) {
870
+ formGroup.removeControl(delName);
871
+ }
872
+ }
873
+
855
874
  class XtUnitTestHelper {
856
875
  }
857
876
 
@@ -865,10 +884,10 @@ class HostTestSimpleComponent {
865
884
  this.displayMode = input('FULL_VIEW');
866
885
  this.value = input(undefined);
867
886
  }
868
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: HostTestSimpleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
869
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.4", type: HostTestSimpleComponent, isStandalone: true, selector: "test-host", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<h1>Test Simple Component</h1> <xt-render [componentType]="type()" [displayMode]="displayMode()" [value]="value()" ></xt-render> ', isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: XtRenderComponent, selector: "xt-render", inputs: ["componentType", "displayMode", "valueType", "value", "formGroup", "subName"], outputs: ["valueChange", "outputs"] }] }); }
887
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: HostTestSimpleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
888
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.10", type: HostTestSimpleComponent, isStandalone: true, selector: "test-host", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<h1>Test Simple Component</h1> <xt-render [componentType]="type()" [displayMode]="displayMode()" [value]="value()" ></xt-render> ', isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: XtRenderComponent, selector: "xt-render", inputs: ["componentType", "displayMode", "valueType", "value", "formGroup", "subName", "inputs"], outputs: ["valueChange", "outputs"] }] }); }
870
889
  }
871
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: HostTestSimpleComponent, decorators: [{
890
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: HostTestSimpleComponent, decorators: [{
872
891
  type: Component,
873
892
  args: [{
874
893
  selector: 'test-host',
@@ -914,10 +933,10 @@ class HostTestFormComponent {
914
933
  else
915
934
  throw new Error("FormGroup not yet created. Did you set formGroup or formDescription property ?");
916
935
  }
917
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: HostTestFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
918
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.4", type: HostTestFormComponent, isStandalone: true, selector: "test-form-host", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, controlName: { classPropertyName: "controlName", publicName: "controlName", isSignal: true, isRequired: true, transformFunction: null }, formDescription: { classPropertyName: "formDescription", publicName: "formDescription", isSignal: true, isRequired: false, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<h1>Test Form Component</h1> <form [formGroup]="computedFormGroup()"> <xt-render [componentType]="type()" displayMode="FULL_EDITABLE" [subName]="controlName()" [formGroup]="computedFormGroup()"></xt-render></form>', isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: XtRenderComponent, selector: "xt-render", inputs: ["componentType", "displayMode", "valueType", "value", "formGroup", "subName"], outputs: ["valueChange", "outputs"] }, { 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"] }] }); }
936
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: HostTestFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
937
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.10", type: HostTestFormComponent, isStandalone: true, selector: "test-form-host", inputs: { type: { classPropertyName: "type", publicName: "type", isSignal: true, isRequired: true, transformFunction: null }, controlName: { classPropertyName: "controlName", publicName: "controlName", isSignal: true, isRequired: true, transformFunction: null }, formDescription: { classPropertyName: "formDescription", publicName: "formDescription", isSignal: true, isRequired: false, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<h1>Test Form Component</h1> <form [formGroup]="computedFormGroup()"> <xt-render [componentType]="type()" displayMode="FULL_EDITABLE" [subName]="controlName()" [formGroup]="computedFormGroup()"></xt-render></form>', isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: XtRenderComponent, selector: "xt-render", inputs: ["componentType", "displayMode", "valueType", "value", "formGroup", "subName", "inputs"], outputs: ["valueChange", "outputs"] }, { 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"] }] }); }
919
938
  }
920
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: HostTestFormComponent, decorators: [{
939
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: HostTestFormComponent, decorators: [{
921
940
  type: Component,
922
941
  args: [{
923
942
  selector: 'test-form-host',
@@ -942,10 +961,10 @@ class HostTestTypedComponent {
942
961
  return ret;
943
962
  });
944
963
  }
945
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: HostTestTypedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
946
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.4", type: HostTestTypedComponent, isStandalone: true, selector: "test-typed-host", inputs: { displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, valueType: { classPropertyName: "valueType", publicName: "valueType", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<h1>Test Typed Component</h1> <xt-render-sub [context]="context()" ></xt-render-sub> ', isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: XtRenderSubComponent, selector: "xt-render-sub", inputs: ["context", "componentType"], outputs: ["outputs"] }] }); }
964
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: HostTestTypedComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
965
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.10", type: HostTestTypedComponent, isStandalone: true, selector: "test-typed-host", inputs: { displayMode: { classPropertyName: "displayMode", publicName: "displayMode", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, valueType: { classPropertyName: "valueType", publicName: "valueType", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<h1>Test Typed Component</h1> <xt-render-sub [context]="context()" ></xt-render-sub> ', isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: XtRenderSubComponent, selector: "xt-render-sub", inputs: ["context", "componentType", "inputs"], outputs: ["outputs"] }] }); }
947
966
  }
948
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: HostTestTypedComponent, decorators: [{
967
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: HostTestTypedComponent, decorators: [{
949
968
  type: Component,
950
969
  args: [{
951
970
  selector: 'test-typed-host',
@@ -1002,10 +1021,10 @@ class HostTestTypedFormComponent {
1002
1021
  retrieveValue(controlName) {
1003
1022
  return this.computedFormGroup().value[controlName];
1004
1023
  }
1005
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: HostTestTypedFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1006
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.4", type: HostTestTypedFormComponent, isStandalone: true, selector: "test-typed-form-host", inputs: { valueType: { classPropertyName: "valueType", publicName: "valueType", isSignal: true, isRequired: false, transformFunction: null }, controlName: { classPropertyName: "controlName", publicName: "controlName", isSignal: true, isRequired: false, transformFunction: null }, formDescription: { classPropertyName: "formDescription", publicName: "formDescription", isSignal: true, isRequired: false, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<h1>Test Typed Form Component</h1> <form [formGroup]="parentFormGroup"> <xt-render-sub [context]="subContext()"></xt-render-sub></form>', isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: XtRenderSubComponent, selector: "xt-render-sub", inputs: ["context", "componentType"], outputs: ["outputs"] }] }); }
1024
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: HostTestTypedFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1025
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "19.2.10", type: HostTestTypedFormComponent, isStandalone: true, selector: "test-typed-form-host", inputs: { valueType: { classPropertyName: "valueType", publicName: "valueType", isSignal: true, isRequired: false, transformFunction: null }, controlName: { classPropertyName: "controlName", publicName: "controlName", isSignal: true, isRequired: false, transformFunction: null }, formDescription: { classPropertyName: "formDescription", publicName: "formDescription", isSignal: true, isRequired: false, transformFunction: null }, formGroup: { classPropertyName: "formGroup", publicName: "formGroup", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: '<h1>Test Typed Form Component</h1> <form [formGroup]="parentFormGroup"> <xt-render-sub [context]="subContext()"></xt-render-sub></form>', isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: XtRenderSubComponent, selector: "xt-render-sub", inputs: ["context", "componentType", "inputs"], outputs: ["outputs"] }] }); }
1007
1026
  }
1008
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.4", ngImport: i0, type: HostTestTypedFormComponent, decorators: [{
1027
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.10", ngImport: i0, type: HostTestTypedFormComponent, decorators: [{
1009
1028
  type: Component,
1010
1029
  args: [{
1011
1030
  selector: 'test-typed-form-host',
@@ -1041,6 +1060,94 @@ function generateFormControl(formDescription) {
1041
1060
  return new FormControl(formDescription);
1042
1061
  }
1043
1062
 
1063
+ /**
1064
+ * A very light and not 100% compatible storemanager in case you are not using xt-store.
1065
+ * It can emulate XtStoreManager to some extends for doing some tests
1066
+ */
1067
+ class StoreTestHelper {
1068
+ static ensureTestProviderOnly() {
1069
+ StoreSupport.setTestStoreManager(new TestStoreManager());
1070
+ }
1071
+ }
1072
+ class TestStoreManager {
1073
+ constructor() {
1074
+ this.defaultProvider = new TestStoreProvider();
1075
+ }
1076
+ getProvider(name) {
1077
+ return this.defaultProvider;
1078
+ }
1079
+ getProviderSafe(name) {
1080
+ return this.defaultProvider;
1081
+ }
1082
+ getDefaultProvider() {
1083
+ return this.defaultProvider;
1084
+ }
1085
+ getDefaultProviderSafe() {
1086
+ return this.defaultProvider;
1087
+ }
1088
+ }
1089
+ class TestStoreProvider {
1090
+ constructor() {
1091
+ this.data = new Map();
1092
+ }
1093
+ getOrCreateArray(name) {
1094
+ let ret = this.data.get(name);
1095
+ if (ret == null) {
1096
+ ret = new Map();
1097
+ this.data.set(name, ret);
1098
+ }
1099
+ return ret;
1100
+ }
1101
+ extractKey(value) {
1102
+ if (value.__id != null)
1103
+ return value.__id;
1104
+ else if (value.id != null)
1105
+ return value.id;
1106
+ else
1107
+ return value.toString();
1108
+ }
1109
+ storeEntity(name, entity) {
1110
+ this.getOrCreateArray(name).set(this.extractKey(entity), entity);
1111
+ return Promise.resolve(entity);
1112
+ }
1113
+ safeLoadEntity(name, key) {
1114
+ const ret = this.getOrCreateArray(name).get(key);
1115
+ if (ret == null) {
1116
+ throw new Error("No entity named " + name + " with key " + key);
1117
+ }
1118
+ return Promise.resolve(ret);
1119
+ }
1120
+ loadEntity(name, key) {
1121
+ return Promise.resolve(this.getOrCreateArray(name).get(key));
1122
+ }
1123
+ deleteEntity(name, key) {
1124
+ return Promise.resolve(this.getOrCreateArray(name).delete(key));
1125
+ }
1126
+ searchEntities(name, ...criteria) {
1127
+ throw new Error('Method not implemented.');
1128
+ }
1129
+ searchAndPrepareEntities(name, sort, groupBy, transformer, ...criteria) {
1130
+ throw new Error('Method not implemented.');
1131
+ }
1132
+ canStoreDocument() {
1133
+ return true;
1134
+ }
1135
+ storeDocument(toStore) {
1136
+ const ret = new TestDocumentInfo(URL.createObjectURL(toStore), true);
1137
+ return Promise.resolve(ret);
1138
+ }
1139
+ storeDocuments(toStore) {
1140
+ throw new Error('Method not implemented.');
1141
+ }
1142
+ }
1143
+ class TestDocumentInfo {
1144
+ constructor(documentName, isUrl, documentId) {
1145
+ this.documentId = documentId;
1146
+ this.documentName = documentName;
1147
+ this.isUrl = isUrl;
1148
+ }
1149
+ }
1150
+
1044
1151
  /*
1045
1152
  * Public API Surface of xt-components
1046
1153
  */
@@ -1049,5 +1156,5 @@ function generateFormControl(formDescription) {
1049
1156
  * Generated bundle index. Do not edit.
1050
1157
  */
1051
1158
 
1052
- export { HostTestFormComponent, HostTestSimpleComponent, HostTestTypedComponent, HostTestTypedFormComponent, XT_REGISTRY, XT_REGISTRY_TOKEN, XT_RESOLVER_TOKEN, XT_TYPE_RESOLVER_TOKEN, XtBaseContext, XtBaseTypeHierarchy, XtCompositeComponent, XtPluginRegistry, XtRenderComponent, XtRenderSubComponent, XtResolvedComponent, XtResolverService, XtSimpleComponent, XtTypeHierarchyResolver, XtUnitTestHelper, fromDescription, updateFormGroupWithValue };
1159
+ export { HostTestFormComponent, HostTestSimpleComponent, HostTestTypedComponent, HostTestTypedFormComponent, MessageHandler, StoreSupport, StoreTestHelper, TestDocumentInfo, TestStoreManager, TestStoreProvider, XT_REGISTRY_TOKEN, XT_RESOLVER_TOKEN, XT_TYPE_RESOLVER_TOKEN, XtBaseContext, XtCompositeComponent, XtPluginRegistry, XtRenderComponent, XtRenderSubComponent, XtResolvedComponent, XtResolverService, XtSimpleComponent, XtUnitTestHelper, initXtPluginRegistry, updateFormGroupWithValue, xtPluginRegistry };
1053
1160
  //# sourceMappingURL=xt-components.mjs.map