@agnos-ui/angular-headless 0.0.1-alpha.1 → 0.0.1-alpha.10

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.
Files changed (110) hide show
  1. package/components/accordion/accordion.d.ts +11 -0
  2. package/components/accordion/index.d.ts +1 -0
  3. package/components/alert/alert.d.ts +7 -0
  4. package/components/alert/index.d.ts +1 -0
  5. package/components/modal/index.d.ts +1 -0
  6. package/components/modal/modal.d.ts +7 -0
  7. package/components/pagination/index.d.ts +1 -0
  8. package/components/pagination/pagination.d.ts +8 -0
  9. package/components/progressbar/index.d.ts +1 -0
  10. package/components/progressbar/progressbar.d.ts +7 -0
  11. package/components/rating/index.d.ts +1 -0
  12. package/components/rating/rating.d.ts +6 -0
  13. package/components/select/index.d.ts +1 -0
  14. package/components/select/select.d.ts +8 -0
  15. package/components/slider/index.d.ts +1 -0
  16. package/components/slider/slider.d.ts +1 -0
  17. package/config.d.ts +44 -0
  18. package/esm2022/agnos-ui-angular-headless.mjs +2 -2
  19. package/esm2022/components/accordion/accordion.mjs +4 -0
  20. package/esm2022/components/accordion/index.mjs +2 -0
  21. package/esm2022/components/alert/alert.mjs +4 -0
  22. package/esm2022/components/alert/index.mjs +2 -0
  23. package/esm2022/components/modal/index.mjs +2 -0
  24. package/esm2022/components/modal/modal.mjs +4 -0
  25. package/esm2022/components/pagination/index.mjs +2 -0
  26. package/esm2022/components/pagination/pagination.mjs +4 -0
  27. package/esm2022/components/progressbar/index.mjs +2 -0
  28. package/esm2022/components/progressbar/progressbar.mjs +4 -0
  29. package/esm2022/components/rating/index.mjs +2 -0
  30. package/esm2022/components/rating/rating.mjs +4 -0
  31. package/esm2022/components/select/index.mjs +2 -0
  32. package/esm2022/components/select/select.mjs +4 -0
  33. package/esm2022/components/slider/index.mjs +2 -0
  34. package/esm2022/components/slider/slider.mjs +2 -0
  35. package/esm2022/config.mjs +112 -0
  36. package/esm2022/generated/config.mjs +2 -0
  37. package/esm2022/generated/index.mjs +23 -0
  38. package/esm2022/generated/services/extendWidget.mjs +2 -0
  39. package/esm2022/generated/services/floatingUI.mjs +2 -0
  40. package/esm2022/generated/services/focustrack.mjs +2 -0
  41. package/esm2022/generated/services/intersection.mjs +2 -0
  42. package/esm2022/generated/services/navManager.mjs +2 -0
  43. package/esm2022/generated/services/portal.mjs +2 -0
  44. package/esm2022/generated/services/siblingsInert.mjs +2 -0
  45. package/esm2022/generated/services/transitions/baseTransitions.mjs +2 -0
  46. package/esm2022/generated/services/transitions/bootstrap.mjs +2 -0
  47. package/esm2022/generated/services/transitions/collapse.mjs +2 -0
  48. package/esm2022/generated/services/transitions/cssTransitions.mjs +2 -0
  49. package/esm2022/generated/services/transitions/simpleClassTransition.mjs +2 -0
  50. package/esm2022/generated/slot.directive.mjs +2 -0
  51. package/esm2022/generated/slotDefault.directive.mjs +2 -0
  52. package/esm2022/generated/types.mjs +2 -0
  53. package/esm2022/generated/utils/coercion.mjs +2 -0
  54. package/esm2022/generated/utils/directive.mjs +2 -0
  55. package/esm2022/generated/utils/stores.mjs +2 -0
  56. package/esm2022/generated/utils/widget.mjs +2 -0
  57. package/esm2022/generated/utils/writables.mjs +2 -0
  58. package/esm2022/generated/utils/zone.mjs +2 -0
  59. package/esm2022/index.mjs +13 -0
  60. package/esm2022/slot.directive.mjs +201 -0
  61. package/esm2022/slotDefault.directive.mjs +21 -0
  62. package/esm2022/types.mjs +21 -0
  63. package/esm2022/utils/coercion.mjs +32 -0
  64. package/esm2022/utils/directive.mjs +72 -0
  65. package/esm2022/utils/stores.mjs +23 -0
  66. package/esm2022/utils/widget.mjs +131 -0
  67. package/esm2022/utils/zone.mjs +73 -0
  68. package/fesm2022/agnos-ui-angular-headless.mjs +486 -174
  69. package/fesm2022/agnos-ui-angular-headless.mjs.map +1 -1
  70. package/generated/config.d.ts +1 -0
  71. package/generated/index.d.ts +22 -0
  72. package/generated/services/extendWidget.d.ts +1 -0
  73. package/generated/services/floatingUI.d.ts +1 -0
  74. package/generated/services/focustrack.d.ts +1 -0
  75. package/generated/services/intersection.d.ts +1 -0
  76. package/generated/services/navManager.d.ts +1 -0
  77. package/generated/services/portal.d.ts +1 -0
  78. package/generated/services/siblingsInert.d.ts +1 -0
  79. package/generated/services/transitions/baseTransitions.d.ts +1 -0
  80. package/generated/services/transitions/bootstrap.d.ts +1 -0
  81. package/generated/services/transitions/collapse.d.ts +1 -0
  82. package/generated/services/transitions/cssTransitions.d.ts +1 -0
  83. package/generated/services/transitions/simpleClassTransition.d.ts +1 -0
  84. package/generated/slot.directive.d.ts +1 -0
  85. package/generated/slotDefault.directive.d.ts +1 -0
  86. package/generated/types.d.ts +1 -0
  87. package/generated/utils/coercion.d.ts +1 -0
  88. package/generated/utils/directive.d.ts +1 -0
  89. package/generated/utils/stores.d.ts +1 -0
  90. package/generated/utils/widget.d.ts +1 -0
  91. package/generated/utils/writables.d.ts +1 -0
  92. package/generated/utils/zone.d.ts +1 -0
  93. package/index.d.ts +9 -5
  94. package/package.json +14 -17
  95. package/{lib/slot.directive.d.ts → slot.directive.d.ts} +3 -1
  96. package/{lib/slotDefault.directive.d.ts → slotDefault.directive.d.ts} +2 -1
  97. package/types.d.ts +35 -0
  98. package/utils/coercion.d.ts +20 -0
  99. package/utils/directive.d.ts +23 -0
  100. package/utils/stores.d.ts +13 -0
  101. package/utils/widget.d.ts +44 -0
  102. package/utils/zone.d.ts +22 -0
  103. package/esm2022/lib/slot.directive.mjs +0 -199
  104. package/esm2022/lib/slotDefault.directive.mjs +0 -20
  105. package/esm2022/lib/use.directive.mjs +0 -57
  106. package/esm2022/lib/utils.mjs +0 -127
  107. package/esm2022/public-api.mjs +0 -9
  108. package/lib/use.directive.d.ts +0 -12
  109. package/lib/utils.d.ts +0 -95
  110. package/public-api.d.ts +0 -34
@@ -1,94 +1,235 @@
1
- import { createWidgetsConfig } from '@agnos-ui/core';
2
- export * from '@agnos-ui/core';
3
- import { DOCUMENT } from '@angular/common';
1
+ import { createAccordion as createAccordion$1 } from '@agnos-ui/core/components/accordion';
2
+ export * from '@agnos-ui/core/components/accordion';
3
+ import { createAlert as createAlert$1 } from '@agnos-ui/core/components/alert';
4
+ export * from '@agnos-ui/core/components/alert';
5
+ import { createModal as createModal$1 } from '@agnos-ui/core/components/modal';
6
+ export * from '@agnos-ui/core/components/modal';
7
+ import { createPagination as createPagination$1 } from '@agnos-ui/core/components/pagination';
8
+ export * from '@agnos-ui/core/components/pagination';
9
+ import { createProgressbar as createProgressbar$1 } from '@agnos-ui/core/components/progressbar';
10
+ export * from '@agnos-ui/core/components/progressbar';
11
+ import { createRating as createRating$1 } from '@agnos-ui/core/components/rating';
12
+ export * from '@agnos-ui/core/components/rating';
13
+ import { createSelect as createSelect$1 } from '@agnos-ui/core/components/select';
14
+ export * from '@agnos-ui/core/components/select';
15
+ export * from '@agnos-ui/core/components/slider';
16
+ export * from '@agnos-ui/core/services/siblingsInert';
17
+ export * from '@agnos-ui/core/services/portal';
18
+ export * from '@agnos-ui/core/services/navManager';
19
+ export * from '@agnos-ui/core/services/intersection';
20
+ export * from '@agnos-ui/core/services/focustrack';
21
+ export * from '@agnos-ui/core/services/floatingUI';
22
+ export * from '@agnos-ui/core/services/extendWidget';
23
+ export * from '@agnos-ui/core/services/transitions/simpleClassTransition';
24
+ export * from '@agnos-ui/core/services/transitions/cssTransitions';
25
+ export * from '@agnos-ui/core/services/transitions/collapse';
26
+ export * from '@agnos-ui/core/services/transitions/bootstrap';
27
+ export * from '@agnos-ui/core/services/transitions/baseTransitions';
28
+ export * from '@agnos-ui/core/utils/writables';
4
29
  import * as i0 from '@angular/core';
5
- import { InjectionToken, inject, Injector, runInInjectionContext, SkipSelf, Optional, createComponent, EnvironmentInjector, TemplateRef, reflectComponentType, ViewContainerRef, Directive, Input, ElementRef } from '@angular/core';
6
- import { readable, writable, computed } from '@amadeus-it-group/tansu';
30
+ import { inject, NgZone, Injectable, signal, DestroyRef, Injector, ElementRef, runInInjectionContext, afterNextRender, Directive, Input, SkipSelf, Optional, InjectionToken, booleanAttribute, numberAttribute, TemplateRef, createComponent, EnvironmentInjector, reflectComponentType, ViewContainerRef } from '@angular/core';
31
+ import { toReadableStore } from '@agnos-ui/core/utils/stores';
32
+ export * from '@agnos-ui/core/utils/stores';
33
+ export * from '@agnos-ui/core/utils/directive';
34
+ import { toSlotContextWidget } from '@agnos-ui/core/types';
35
+ export * from '@agnos-ui/core/types';
36
+ import { createWidgetsConfig } from '@agnos-ui/core/config';
37
+ export * from '@agnos-ui/core/config';
38
+ import { writable, computed } from '@amadeus-it-group/tansu';
39
+ import { DOCUMENT } from '@angular/common';
7
40
 
8
- class ComponentTemplate {
9
- constructor(component, templateProp) {
10
- this.component = component;
11
- this.templateProp = templateProp;
41
+ const createAccordion = createAccordion$1;
42
+
43
+ const createAlert = createAlert$1;
44
+
45
+ const createModal = createModal$1;
46
+
47
+ const createPagination = createPagination$1;
48
+
49
+ const createProgressbar = createProgressbar$1;
50
+
51
+ const createRating = createRating$1;
52
+
53
+ const createSelect = createSelect$1;
54
+
55
+ const noop = () => { };
56
+ const identity = (a) => a;
57
+ const createObjectWrapper = (wrap) => (object) => {
58
+ if (!object || typeof object !== 'object') {
59
+ return object;
60
+ }
61
+ const res = {};
62
+ for (const key of Object.keys(object)) {
63
+ res[key] = wrap(object[key]);
64
+ }
65
+ return res;
66
+ };
67
+ const createReturnValueWrapper = (wrapReturnValue, wrapResult) => (fn) => wrapResult(typeof fn === 'function' ? ((...args) => wrapReturnValue(fn(...args))) : fn);
68
+ class ZoneWrapper {
69
+ constructor() {
70
+ this.#zone = inject(NgZone);
71
+ this.#hasZone = this.#zone.run(() => NgZone.isInAngularZone()); // check if zone is enabled (can be NoopZone, cf https://angular.io/guide/zone#noopzone)
72
+ this.#runNeeded = false;
73
+ this.#runPlanned = false;
74
+ this.planNgZoneRun = this.#hasZone
75
+ ? () => {
76
+ if (this.#zone.isStable) {
77
+ this.#runNeeded = true;
78
+ if (!this.#runPlanned) {
79
+ this.#runPlanned = true;
80
+ void (async () => {
81
+ await 0;
82
+ this.#runPlanned = false;
83
+ if (this.#runNeeded) {
84
+ this.ngZoneRun(noop);
85
+ }
86
+ })();
87
+ }
88
+ }
89
+ }
90
+ : noop;
91
+ this.insideNgZone = this.#hasZone
92
+ ? (fn) => (typeof fn === 'function' ? ((...args) => this.ngZoneRun(() => fn(...args))) : fn)
93
+ : identity;
94
+ this.insideNgZoneWrapFunctionsObject = createObjectWrapper(this.insideNgZone);
95
+ this.outsideNgZone = this.#hasZone
96
+ ? (fn) => (typeof fn === 'function' ? ((...args) => this.#zone.runOutsideAngular(() => fn(...args))) : fn)
97
+ : identity;
98
+ this.outsideNgZoneWrapFunctionsObject = createObjectWrapper(this.outsideNgZone);
99
+ this.outsideNgZoneWrapDirective = createReturnValueWrapper(this.outsideNgZoneWrapFunctionsObject, this.outsideNgZone);
100
+ this.outsideNgZoneWrapDirectivesObject = createObjectWrapper(this.outsideNgZoneWrapDirective);
101
+ }
102
+ #zone;
103
+ #hasZone; // check if zone is enabled (can be NoopZone, cf https://angular.io/guide/zone#noopzone)
104
+ #runNeeded;
105
+ #runPlanned;
106
+ /**
107
+ * Run the input function synchronously within the Angular zone
108
+ *
109
+ * @param fn - a function to run
110
+ * @returns the value returned by the function
111
+ */
112
+ ngZoneRun(fn) {
113
+ this.#runNeeded = false;
114
+ return this.#zone.run(fn);
12
115
  }
116
+ static { this.ɵfac = function ZoneWrapper_Factory(t) { return new (t || ZoneWrapper)(); }; }
117
+ static { this.ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: ZoneWrapper, factory: ZoneWrapper.ɵfac, providedIn: 'root' }); }
13
118
  }
119
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(ZoneWrapper, [{
120
+ type: Injectable,
121
+ args: [{
122
+ providedIn: 'root',
123
+ }]
124
+ }], null, null); })();
125
+
14
126
  /**
15
- * Dependency Injection token which can be used to provide or inject the widgets default configuration store.
16
- */
17
- const widgetsConfigInjectionToken = new InjectionToken('widgetsConfig');
18
- /**
19
- * Creates a provider of widgets default configuration that inherits from any widgets default configuration already defined at an upper level
20
- * in the Angular dependency injection system. It contains its own set of widgets configuration properties that override the same properties form
21
- * the parent configuration.
22
- *
23
- * @remarks
24
- * The configuration is computed from the parent configuration in two steps:
25
- * - first step: the parent configuration is transformed by the adaptParentConfig function (if specified).
26
- * If adaptParentConfig is not specified, this step is skipped.
27
- * - second step: the configuration from step 1 is merged (2-levels deep) with the own$ store. The own$ store initially contains
28
- * an empty object (i.e. no property from the parent is overridden). It can be changed by calling set on the store returned by
29
- * {@link injectWidgetsConfig}.
127
+ * Convert a tansu readable signal into an Angular signal.
30
128
  *
31
- * @param adaptParentConfig - optional function that receives a 2-levels copy of the widgets default configuration
32
- * defined at an upper level in the Angular dependency injection system (or an empty object if there is none) and returns the widgets
33
- * default configuration to be used.
34
- * It is called only if the configuration is needed, and was not yet computed for the current value of the parent configuration.
35
- * It is called in a tansu reactive context, so it can use any tansu store and will be called again if those stores change.
36
- * It is also called in an Angular injection context, so it can call the Angular inject function to get and use dependencies from the
37
- * Angular dependency injection system.
38
-
39
- * @returns DI provider to be included a list of `providers` (for example at a component level or
40
- * any other level of the Angular dependency injection system)
129
+ * @param tansuSignal - a tansu readable signal
130
+ * @returns an angular signal
41
131
  *
42
- * @example
43
- * ```typescript
44
- * @Component({
45
- * // ...
46
- * providers: [
47
- * provideWidgetsConfig((parentConfig) => {
48
- * // first step configuration: transforms the parent configuration
49
- * parentConfig.rating = parentConfig.rating ?? {};
50
- * parentConfig.rating.className = `${parentConfig.rating.className ?? ''} my-rating-extra-class`
51
- * return parentConfig;
52
- * })
53
- * ]
54
- * })
55
- * class MyComponent {
56
- * widgetsConfig = injectWidgetsConfig();
57
- * constructor() {
58
- * this.widgetsConfig.set({
59
- * // second step configuration: overrides the parent configuration
60
- * rating: {
61
- * slotStar: MyCustomSlotStar
62
- * }
63
- * });
64
- * }
65
- * // ...
66
- * }
67
- * ```
132
+ * @remarks
133
+ * Note that as it uses Angular's `inject`, this can only be called at component construction time.
68
134
  */
69
- const provideWidgetsConfig = (adaptParentConfig) => ({
70
- provide: widgetsConfigInjectionToken,
71
- useFactory: (parent) => {
72
- if (adaptParentConfig) {
73
- const injector = inject(Injector);
74
- const originalAdaptParentConfig = adaptParentConfig;
75
- adaptParentConfig = (value) => runInInjectionContext(injector, () => originalAdaptParentConfig(value));
76
- }
77
- return createWidgetsConfig(parent ?? undefined, adaptParentConfig);
78
- },
79
- deps: [[new SkipSelf(), new Optional(), widgetsConfigInjectionToken]],
80
- });
135
+ const toAngularSignal = (tansuSignal) => {
136
+ const zoneWrapper = inject(ZoneWrapper);
137
+ const res = signal(undefined);
138
+ const subscription = zoneWrapper.outsideNgZone(tansuSignal.subscribe)((value) => {
139
+ res.set(value);
140
+ zoneWrapper.planNgZoneRun();
141
+ });
142
+ inject(DestroyRef).onDestroy(zoneWrapper.outsideNgZone(subscription));
143
+ return res;
144
+ };
145
+
81
146
  /**
82
- * Returns the widgets default configuration store that was provided in the current injection context.
83
- * Throws if the no widgets default configuration store was provided.
84
- *
85
- * @remarks
86
- * This function must be called from an injection context, such as a constructor, a factory function, a field initializer or
87
- * a function used with {@link https://angular.io/api/core/runInInjectionContext | runInInjectionContext}.
147
+ * Set up an agnos-ui directive as an angular host directive.
88
148
  *
89
- * @returns the widgets default configuration store.
149
+ * @param directive - the directive
150
+ * @param params - the params to pass to the directive
151
+ * @returns the update function to change the directive or params
90
152
  */
91
- const injectWidgetsConfig = () => inject(widgetsConfigInjectionToken);
153
+ const useDirectiveForHost = (directive, params) => {
154
+ const injector = inject(Injector);
155
+ const ref = inject(ElementRef);
156
+ let instance;
157
+ let plannedCallDirective = false;
158
+ const callDirective = () => {
159
+ if (plannedCallDirective || !directive) {
160
+ return;
161
+ }
162
+ plannedCallDirective = true;
163
+ runInInjectionContext(injector, () => {
164
+ afterNextRender(() => {
165
+ plannedCallDirective = false;
166
+ instance = directive?.(ref.nativeElement, params);
167
+ });
168
+ });
169
+ };
170
+ function destroyDirectiveInstance() {
171
+ const oldInstance = instance;
172
+ instance = undefined;
173
+ directive = undefined;
174
+ oldInstance?.destroy?.();
175
+ }
176
+ inject(DestroyRef).onDestroy(destroyDirectiveInstance);
177
+ function update(newDirective, newParams) {
178
+ if (newDirective !== directive) {
179
+ void destroyDirectiveInstance();
180
+ directive = newDirective;
181
+ params = newParams;
182
+ callDirective();
183
+ }
184
+ else if (newParams != params) {
185
+ params = newParams;
186
+ instance?.update?.(params);
187
+ }
188
+ }
189
+ callDirective();
190
+ return { update };
191
+ };
192
+ class UseDirective {
193
+ #useDirective = useDirectiveForHost();
194
+ /** @inheritdoc */
195
+ ngOnChanges() {
196
+ this.#useDirective.update(this.use, this.params);
197
+ }
198
+ static { this.ɵfac = function UseDirective_Factory(t) { return new (t || UseDirective)(); }; }
199
+ static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: UseDirective, selectors: [["", "auUse", ""]], inputs: { use: [i0.ɵɵInputFlags.None, "auUse", "use"], params: [i0.ɵɵInputFlags.None, "auUseParams", "params"] }, standalone: true, features: [i0.ɵɵNgOnChangesFeature] }); }
200
+ }
201
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(UseDirective, [{
202
+ type: Directive,
203
+ args: [{
204
+ standalone: true,
205
+ selector: '[auUse]',
206
+ }]
207
+ }], null, { use: [{
208
+ type: Input,
209
+ args: ['auUse']
210
+ }], params: [{
211
+ type: Input,
212
+ args: ['auUseParams']
213
+ }] }); })();
214
+
215
+ class ComponentTemplate {
216
+ constructor(component, templateProp) {
217
+ this.component = component;
218
+ this.templateProp = templateProp;
219
+ }
220
+ }
221
+ class SlotComponent {
222
+ static { this.ɵfac = function SlotComponent_Factory(t) { return new (t || SlotComponent)(); }; }
223
+ static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: SlotComponent, inputs: { state: "state", widget: "widget" } }); }
224
+ }
225
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SlotComponent, [{
226
+ type: Directive
227
+ }], null, { state: [{
228
+ type: Input
229
+ }], widget: [{
230
+ type: Input
231
+ }] }); })();
232
+
92
233
  const createPatchSlots = (set) => {
93
234
  let lastValue = {};
94
235
  return (object) => {
@@ -110,14 +251,58 @@ const createPatchSlots = (set) => {
110
251
  }
111
252
  };
112
253
  };
113
- const callWidgetFactory = (factory, widgetName, defaultConfig = {}) => {
114
- const defaultConfigStore = typeof defaultConfig !== 'function' ? readable(defaultConfig) : defaultConfig;
254
+ /**
255
+ * Call a widget factory using provided configs.
256
+ *
257
+ * @param parameter - the parameter
258
+ * @param parameter.factory - the widget factory to call
259
+ * @param parameter.defaultConfig - the default config of the widget
260
+ * @param parameter.widgetConfig - the config of the widget, overriding the defaultConfig
261
+ * @param parameter.events - the events of the widget
262
+ * @param parameter.afterInit - a callback to call after successful setup of the widget
263
+ * @returns the widget
264
+ */
265
+ const callWidgetFactoryWithConfig = ({ factory, defaultConfig, widgetConfig, events, afterInit, }) => {
266
+ const injector = inject(Injector);
115
267
  const slots$ = writable({});
116
- const widgetsConfig = widgetName ? inject(widgetsConfigInjectionToken, { optional: true }) : undefined;
117
- return {
118
- ...factory(computed(() => ({ ...defaultConfigStore(), ...(widgetName ? widgetsConfig?.()[widgetName] : undefined), ...slots$() }))),
268
+ const props = {};
269
+ let initDone;
270
+ const res = {
271
+ initialized: new Promise((resolve) => {
272
+ initDone = resolve;
273
+ }),
119
274
  patchSlots: createPatchSlots(slots$.set),
275
+ patch(newProps) {
276
+ // temporary function replaced in ngInit
277
+ Object.assign(props, newProps);
278
+ },
279
+ ngInit() {
280
+ runInInjectionContext(injector, () => {
281
+ const zoneWrapper = inject(ZoneWrapper);
282
+ factory = zoneWrapper.outsideNgZone(factory);
283
+ const defaultConfig$ = toReadableStore(defaultConfig);
284
+ events = zoneWrapper.insideNgZoneWrapFunctionsObject(events);
285
+ const widget = factory({
286
+ config: computed(() => ({ ...defaultConfig$(), ...widgetConfig?.(), ...slots$(), ...events })),
287
+ props,
288
+ });
289
+ const wrappedWidget = {
290
+ ...widget,
291
+ patch: zoneWrapper.outsideNgZone(widget.patch),
292
+ directives: zoneWrapper.outsideNgZoneWrapDirectivesObject(widget.directives),
293
+ actions: zoneWrapper.outsideNgZoneWrapFunctionsObject(widget.actions),
294
+ api: zoneWrapper.outsideNgZoneWrapFunctionsObject(widget.api),
295
+ };
296
+ Object.assign(res, wrappedWidget, {
297
+ widget: toSlotContextWidget(wrappedWidget),
298
+ ngState: toAngularSignal(wrappedWidget.state$),
299
+ });
300
+ afterInit?.();
301
+ initDone();
302
+ });
303
+ },
120
304
  };
305
+ return res;
121
306
  };
122
307
  function patchSimpleChanges(patchFn, changes) {
123
308
  const obj = {};
@@ -128,6 +313,204 @@ function patchSimpleChanges(patchFn, changes) {
128
313
  }
129
314
  patchFn(obj);
130
315
  }
316
+ /**
317
+ * Stores the result of the first call to the getter and returns that result directly for subsequent calls
318
+ *
319
+ * Applies to: class getters
320
+ *
321
+ * @param target - the target
322
+ * @param property - the property
323
+ * @param descriptor - the property descriptor
324
+ */
325
+ const CachedProperty = (target, property, descriptor) => {
326
+ const originalGet = descriptor.get;
327
+ descriptor.get = function () {
328
+ const value = originalGet?.call(this);
329
+ Object.defineProperty(this, property, { value, writable: false });
330
+ return value;
331
+ };
332
+ };
333
+ class BaseWidgetDirective {
334
+ get api() {
335
+ return this._widget.api;
336
+ }
337
+ get state() {
338
+ return this._widget.ngState;
339
+ }
340
+ get widget() {
341
+ return this._widget.widget;
342
+ }
343
+ /** @inheritdoc */
344
+ ngOnChanges(changes) {
345
+ patchSimpleChanges(this._widget.patch, changes);
346
+ }
347
+ /** @inheritdoc */
348
+ ngOnInit() {
349
+ this._widget.ngInit();
350
+ }
351
+ static { this.ɵfac = function BaseWidgetDirective_Factory(t) { return new (t || BaseWidgetDirective)(); }; }
352
+ static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: BaseWidgetDirective, features: [i0.ɵɵNgOnChangesFeature] }); }
353
+ }
354
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(BaseWidgetDirective, [{
355
+ type: Directive
356
+ }], null, null); })();
357
+
358
+ /**
359
+ * A factory to create the utilities to allow widgets to be context-aware.
360
+ *
361
+ * It can be used when extending the core and creating new widgets.
362
+ *
363
+ * @param widgetsConfigInjectionToken - the widgets config injection token
364
+ * @returns the utilities to create / manage widgets and contexts
365
+ */
366
+ const widgetsConfigFactory = (widgetsConfigInjectionToken = new InjectionToken('widgetsConfig')) => {
367
+ /**
368
+ * Creates a provider of widgets default configuration that inherits from any widgets default configuration already defined at an upper level
369
+ * in the Angular dependency injection system. It contains its own set of widgets configuration properties that override the same properties form
370
+ * the parent configuration.
371
+ *
372
+ * @remarks
373
+ * The configuration is computed from the parent configuration in two steps:
374
+ * - first step: the parent configuration is transformed by the adaptParentConfig function (if specified).
375
+ * If adaptParentConfig is not specified, this step is skipped.
376
+ * - second step: the configuration from step 1 is merged (2-levels deep) with the own$ store. The own$ store initially contains
377
+ * an empty object (i.e. no property from the parent is overridden). It can be changed by calling set on the store returned by
378
+ * {@link injectWidgetsConfig}.
379
+ *
380
+ * @param adaptParentConfig - optional function that receives a 2-levels copy of the widgets default configuration
381
+ * defined at an upper level in the Angular dependency injection system (or an empty object if there is none) and returns the widgets
382
+ * default configuration to be used.
383
+ * It is called only if the configuration is needed, and was not yet computed for the current value of the parent configuration.
384
+ * It is called in a tansu reactive context, so it can use any tansu store and will be called again if those stores change.
385
+ * It is also called in an Angular injection context, so it can call the Angular inject function to get and use dependencies from the
386
+ * Angular dependency injection system.
387
+ *
388
+ * @returns DI provider to be included a list of `providers` (for example at a component level or
389
+ * any other level of the Angular dependency injection system)
390
+ *
391
+ * @example
392
+ * ```typescript
393
+ * @Component({
394
+ * // ...
395
+ * providers: [
396
+ * provideWidgetsConfig((parentConfig) => {
397
+ * // first step configuration: transforms the parent configuration
398
+ * parentConfig.rating = parentConfig.rating ?? {};
399
+ * parentConfig.rating.className = `${parentConfig.rating.className ?? ''} my-rating-extra-class`
400
+ * return parentConfig;
401
+ * })
402
+ * ]
403
+ * })
404
+ * class MyComponent {
405
+ * widgetsConfig = injectWidgetsConfig();
406
+ * constructor() {
407
+ * this.widgetsConfig.set({
408
+ * // second step configuration: overrides the parent configuration
409
+ * rating: {
410
+ * slotStar: MyCustomSlotStar
411
+ * }
412
+ * });
413
+ * }
414
+ * // ...
415
+ * }
416
+ * ```
417
+ */
418
+ const provideWidgetsConfig = (adaptParentConfig) => ({
419
+ provide: widgetsConfigInjectionToken,
420
+ useFactory: (parent) => {
421
+ if (adaptParentConfig) {
422
+ const injector = inject(Injector);
423
+ const originalAdaptParentConfig = adaptParentConfig;
424
+ adaptParentConfig = (value) => runInInjectionContext(injector, () => originalAdaptParentConfig(value));
425
+ }
426
+ return createWidgetsConfig(parent ?? undefined, adaptParentConfig);
427
+ },
428
+ deps: [[new SkipSelf(), new Optional(), widgetsConfigInjectionToken]],
429
+ });
430
+ /**
431
+ * Returns the widgets default configuration store that was provided in the current injection context.
432
+ * Throws if the no widgets default configuration store was provided.
433
+ *
434
+ * @remarks
435
+ * This function must be called from an injection context, such as a constructor, a factory function, a field initializer or
436
+ * a function used with {@link https://angular.io/api/core/runInInjectionContext | runInInjectionContext}.
437
+ *
438
+ * @returns the widgets default configuration store.
439
+ */
440
+ const injectWidgetsConfig = () => inject(widgetsConfigInjectionToken);
441
+ const injectWidgetConfig = (widgetName) => {
442
+ const widgetsConfig = inject(widgetsConfigInjectionToken, { optional: true });
443
+ return computed(() => widgetsConfig?.()[widgetName]);
444
+ };
445
+ const callWidgetFactory = ({ factory, widgetName = null, defaultConfig = {}, events, afterInit, }) => callWidgetFactoryWithConfig({
446
+ factory,
447
+ widgetConfig: widgetName ? injectWidgetConfig(widgetName) : null,
448
+ defaultConfig,
449
+ events,
450
+ afterInit,
451
+ });
452
+ return {
453
+ /**
454
+ * Dependency Injection token which can be used to provide or inject the widgets default configuration store.
455
+ */
456
+ widgetsConfigInjectionToken,
457
+ provideWidgetsConfig,
458
+ injectWidgetsConfig,
459
+ injectWidgetConfig,
460
+ callWidgetFactory,
461
+ };
462
+ };
463
+ const { widgetsConfigInjectionToken, provideWidgetsConfig, injectWidgetConfig, injectWidgetsConfig, callWidgetFactory } = widgetsConfigFactory();
464
+
465
+ /**
466
+ * Transforms a value (typically a string) to a boolean.
467
+ * Intended to be used as a transform function of an input.
468
+ *
469
+ * @example
470
+ * ```@Input({ transform: auBooleanAttribute }) status: boolean | undefined;```
471
+ * @param value - Value to be transformed.
472
+ * @returns the value transformed
473
+ */
474
+ function auBooleanAttribute(value) {
475
+ if (value === undefined) {
476
+ return undefined;
477
+ }
478
+ return booleanAttribute(value);
479
+ }
480
+ /**
481
+ * Transforms a value (typically a string) to a number.
482
+ * Intended to be used as a transform function of an input.
483
+ * @param value - Value to be transformed.
484
+ *
485
+ * @example
486
+ * ```@Input({ transform: auNumberAttribute }) id: number | undefined;```
487
+ * @returns the value transformed
488
+ */
489
+ function auNumberAttribute(value) {
490
+ if (value === undefined) {
491
+ return undefined;
492
+ }
493
+ return numberAttribute(value);
494
+ }
495
+
496
+ class SlotDefaultDirective {
497
+ constructor() {
498
+ this.templateRef = inject((TemplateRef));
499
+ }
500
+ /** @inheritdoc */
501
+ ngOnInit() {
502
+ this.auSlotDefault.update((value) => ({ ...value, slotDefault: this.templateRef }));
503
+ }
504
+ static { this.ɵfac = function SlotDefaultDirective_Factory(t) { return new (t || SlotDefaultDirective)(); }; }
505
+ static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: SlotDefaultDirective, selectors: [["", "auSlotDefault", ""]], inputs: { auSlotDefault: "auSlotDefault" }, standalone: true }); }
506
+ }
507
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SlotDefaultDirective, [{
508
+ type: Directive,
509
+ args: [{ selector: '[auSlotDefault]', standalone: true }]
510
+ }], null, { auSlotDefault: [{
511
+ type: Input,
512
+ args: ['auSlotDefault']
513
+ }] }); })();
131
514
 
132
515
  class SlotHandler {
133
516
  constructor(viewContainerRef, document) {
@@ -286,6 +669,7 @@ class SlotDirective {
286
669
  this._viewContainerRef = inject(ViewContainerRef);
287
670
  this._document = inject(DOCUMENT);
288
671
  }
672
+ /** @inheritdoc */
289
673
  ngOnChanges(changes) {
290
674
  const slotChange = changes['slot'];
291
675
  const propsChange = changes['props'];
@@ -303,99 +687,27 @@ class SlotDirective {
303
687
  this._slotHandler?.propsChange(slot, this.props);
304
688
  }
305
689
  }
690
+ /** @inheritdoc */
306
691
  ngOnDestroy() {
307
692
  this._slotHandler?.destroy();
308
693
  this._slotHandler = undefined;
309
694
  }
310
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: SlotDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
311
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.5", type: SlotDirective, isStandalone: true, selector: "[auSlot]", inputs: { slot: ["auSlot", "slot"], props: ["auSlotProps", "props"] }, usesOnChanges: true, ngImport: i0 }); }
312
- }
313
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: SlotDirective, decorators: [{
314
- type: Directive,
315
- args: [{
316
- selector: '[auSlot]',
317
- standalone: true,
318
- }]
319
- }], propDecorators: { slot: [{
320
- type: Input,
321
- args: ['auSlot']
322
- }], props: [{
323
- type: Input,
324
- args: ['auSlotProps']
325
- }] } });
326
-
327
- class SlotDefaultDirective {
328
- constructor() {
329
- this.templateRef = inject((TemplateRef));
330
- }
331
- ngOnInit() {
332
- this.auSlotDefault.update((value) => ({ ...value, slotDefault: this.templateRef }));
333
- }
334
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: SlotDefaultDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
335
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.5", type: SlotDefaultDirective, isStandalone: true, selector: "[auSlotDefault]", inputs: { auSlotDefault: "auSlotDefault" }, ngImport: i0 }); }
336
- }
337
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: SlotDefaultDirective, decorators: [{
338
- type: Directive,
339
- args: [{ selector: '[auSlotDefault]', standalone: true }]
340
- }], propDecorators: { auSlotDefault: [{
341
- type: Input,
342
- args: ['auSlotDefault']
343
- }] } });
344
-
345
- // All calls of the directive in this class are done asynchronously (with await 0)
346
- // in order to avoid ExpressionChangedAfterItHasBeenCheckedError
347
- // or the corresponding issue with signals (https://github.com/angular/angular/issues/50320)
348
- // This is relevant especially if calling the directive changes variables used in a template.
349
- class UseDirective {
350
- #ref = inject(ElementRef);
351
- #directive;
352
- #directiveInstance;
353
- async #destroyDirectiveInstance() {
354
- const directiveInstance = this.#directiveInstance;
355
- this.#directiveInstance = undefined;
356
- if (directiveInstance?.destroy) {
357
- await 0;
358
- directiveInstance.destroy?.();
359
- }
360
- }
361
- async ngOnChanges(changes) {
362
- if (this.use !== this.#directive) {
363
- this.#destroyDirectiveInstance();
364
- const directive = this.use;
365
- this.#directive = directive;
366
- if (directive) {
367
- await 0;
368
- // checks that the directive did not change while waiting:
369
- if (directive === this.#directive && !this.#directiveInstance) {
370
- this.#directiveInstance = directive(this.#ref.nativeElement, this.params);
371
- }
372
- }
373
- }
374
- else if (changes['params']) {
375
- await 0;
376
- this.#directiveInstance?.update?.(this.params);
377
- }
378
- }
379
- ngOnDestroy() {
380
- this.#destroyDirectiveInstance();
381
- this.#directive = undefined;
382
- }
383
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: UseDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); }
384
- static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.2.5", type: UseDirective, isStandalone: true, selector: "[auUse]", inputs: { use: ["auUse", "use"], params: ["auUseParams", "params"] }, usesOnChanges: true, ngImport: i0 }); }
695
+ static { this.ɵfac = function SlotDirective_Factory(t) { return new (t || SlotDirective)(); }; }
696
+ static { this.ɵdir = /*@__PURE__*/ i0.ɵɵdefineDirective({ type: SlotDirective, selectors: [["", "auSlot", ""]], inputs: { slot: [i0.ɵɵInputFlags.None, "auSlot", "slot"], props: [i0.ɵɵInputFlags.None, "auSlotProps", "props"] }, standalone: true, features: [i0.ɵɵNgOnChangesFeature] }); }
385
697
  }
386
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.5", ngImport: i0, type: UseDirective, decorators: [{
387
- type: Directive,
388
- args: [{
389
- standalone: true,
390
- selector: '[auUse]',
391
- }]
392
- }], propDecorators: { use: [{
393
- type: Input,
394
- args: ['auUse']
395
- }], params: [{
396
- type: Input,
397
- args: ['auUseParams']
398
- }] } });
698
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(SlotDirective, [{
699
+ type: Directive,
700
+ args: [{
701
+ selector: '[auSlot]',
702
+ standalone: true,
703
+ }]
704
+ }], null, { slot: [{
705
+ type: Input,
706
+ args: ['auSlot']
707
+ }], props: [{
708
+ type: Input,
709
+ args: ['auSlotProps']
710
+ }] }); })();
399
711
 
400
712
  /*
401
713
  * Public API Surface of @agnos-ui/angular-headless
@@ -405,5 +717,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.5", ngImpor
405
717
  * Generated bundle index. Do not edit.
406
718
  */
407
719
 
408
- export { ComponentTemplate, SlotDefaultDirective, SlotDirective, UseDirective, callWidgetFactory, injectWidgetsConfig, patchSimpleChanges, provideWidgetsConfig, widgetsConfigInjectionToken };
720
+ export { BaseWidgetDirective, CachedProperty, ComponentTemplate, SlotComponent, SlotDefaultDirective, SlotDirective, UseDirective, ZoneWrapper, auBooleanAttribute, auNumberAttribute, callWidgetFactory, callWidgetFactoryWithConfig, createAccordion, createAlert, createModal, createPagination, createProgressbar, createRating, createSelect, injectWidgetConfig, injectWidgetsConfig, provideWidgetsConfig, toAngularSignal, useDirectiveForHost, widgetsConfigFactory, widgetsConfigInjectionToken };
409
721
  //# sourceMappingURL=agnos-ui-angular-headless.mjs.map