@acorex/platform 20.5.0-next.0 → 20.5.0-next.1

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,4 +1,4 @@
1
- import * as i1$1 from '@angular/common';
1
+ import * as i4 from '@angular/common';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import * as i0 from '@angular/core';
4
4
  import { inject, Injectable, input, model, signal, effect, output, viewChild, ChangeDetectionStrategy, Component, NgModule, EventEmitter, Output, Input } from '@angular/core';
@@ -10,11 +10,11 @@ import * as i1 from '@acorex/platform/layout/widget-core';
10
10
  import { AXPWidgetContainerComponent, AXPPageStatus, AXPWidgetCoreModule } from '@acorex/platform/layout/widget-core';
11
11
  import { isEqual, get, cloneDeep } from 'lodash-es';
12
12
  import { Subject, debounceTime, distinctUntilChanged, startWith } from 'rxjs';
13
- import * as i2$1 from '@acorex/components/button';
13
+ import * as i1$1 from '@acorex/components/button';
14
14
  import { AXButtonModule } from '@acorex/components/button';
15
- import * as i3 from '@acorex/components/decorators';
15
+ import * as i2$1 from '@acorex/components/decorators';
16
16
  import { AXDecoratorModule } from '@acorex/components/decorators';
17
- import * as i4 from '@acorex/components/loading';
17
+ import * as i3 from '@acorex/components/loading';
18
18
  import { AXLoadingModule } from '@acorex/components/loading';
19
19
  import { AXBasePageComponent } from '@acorex/components/page';
20
20
  import * as i5 from '@acorex/core/translation';
@@ -170,12 +170,24 @@ class LayoutBuilder {
170
170
  return this;
171
171
  }
172
172
  dialog(delegate) {
173
+ if (!this.popupService) {
174
+ throw new Error('LayoutBuilder requires AXPopupService to create dialogs. Please inject it in the service constructor.');
175
+ }
173
176
  const container = new DialogContainerBuilder(this.popupService);
174
177
  if (delegate) {
175
178
  delegate(container);
176
179
  }
177
180
  return container;
178
181
  }
182
+ stepWizard(delegate) {
183
+ const wizard = new StepWizardBuilder();
184
+ wizard.withInheritanceContext(this.inheritanceContext);
185
+ if (delegate) {
186
+ delegate(wizard);
187
+ }
188
+ this.root.children.push(wizard.build());
189
+ return this;
190
+ }
179
191
  formField(label, delegate) {
180
192
  const field = new FormFieldBuilder(label);
181
193
  field.withInheritanceContext(this.inheritanceContext);
@@ -448,6 +460,16 @@ class ChildContainerMixin extends LayoutContainerMixin {
448
460
  }
449
461
  return container;
450
462
  }
463
+ stepWizard(delegate) {
464
+ const wizard = new StepWizardBuilder();
465
+ wizard.withInheritanceContext(this.inheritanceContext);
466
+ if (delegate) {
467
+ delegate(wizard);
468
+ }
469
+ this.ensureChildren();
470
+ this.containerState.children.push(wizard.build());
471
+ return this;
472
+ }
451
473
  formField(label, delegate) {
452
474
  const field = new FormFieldBuilder(label);
453
475
  field.withInheritanceContext(this.inheritanceContext);
@@ -1031,6 +1053,23 @@ class DialogContainerBuilder {
1031
1053
  }
1032
1054
  return this;
1033
1055
  }
1056
+ addCustomAction(action) {
1057
+ // Add to actions based on position
1058
+ const position = action.position || 'suffix';
1059
+ if (position === 'prefix') {
1060
+ if (!this.dialogState.actions.footer.prefix) {
1061
+ this.dialogState.actions.footer.prefix = [];
1062
+ }
1063
+ this.dialogState.actions.footer.prefix.push(action);
1064
+ }
1065
+ else {
1066
+ if (!this.dialogState.actions.footer.suffix) {
1067
+ this.dialogState.actions.footer.suffix = [];
1068
+ }
1069
+ this.dialogState.actions.footer.suffix.push(action);
1070
+ }
1071
+ return this;
1072
+ }
1034
1073
  // Build method to create dialog node
1035
1074
  build() {
1036
1075
  // If we have content layout, use it directly to avoid extra wrapper
@@ -1255,6 +1294,138 @@ class ActionBuilder {
1255
1294
  return this;
1256
1295
  }
1257
1296
  }
1297
+ //#endregion
1298
+ //#region ---- Step Wizard Builder Implementation ----
1299
+ /**
1300
+ * Step Builder - Builds individual steps for step wizard
1301
+ */
1302
+ class StepBuilder {
1303
+ constructor(id, title) {
1304
+ this.id = id;
1305
+ this.title = title;
1306
+ this.skippable = false;
1307
+ this.inheritanceContext = {};
1308
+ }
1309
+ setIcon(icon) {
1310
+ this.icon = icon;
1311
+ return this;
1312
+ }
1313
+ setDescription(description) {
1314
+ this.description = description;
1315
+ return this;
1316
+ }
1317
+ setSkippable(skippable) {
1318
+ this.skippable = skippable;
1319
+ return this;
1320
+ }
1321
+ content(delegate) {
1322
+ if (delegate) {
1323
+ // Create LayoutBuilder in injection context (will be called from component)
1324
+ const layoutBuilder = new LayoutBuilder();
1325
+ // ✅ IMPORTANT: Propagate inheritance context to content
1326
+ layoutBuilder.inheritanceContext = { ...this.inheritanceContext };
1327
+ delegate(layoutBuilder);
1328
+ this.contentNode = layoutBuilder.build();
1329
+ }
1330
+ return this;
1331
+ }
1332
+ withInheritanceContext(context) {
1333
+ this.inheritanceContext = mergeInheritanceContext(context);
1334
+ return this;
1335
+ }
1336
+ build() {
1337
+ if (!this.contentNode) {
1338
+ throw new Error(`Step '${this.id}' must have content`);
1339
+ }
1340
+ return {
1341
+ id: this.id,
1342
+ title: this.title,
1343
+ icon: this.icon,
1344
+ description: this.description,
1345
+ skippable: this.skippable,
1346
+ content: this.contentNode,
1347
+ };
1348
+ }
1349
+ }
1350
+ /**
1351
+ * Step Wizard Builder - Builds step wizard widget
1352
+ */
1353
+ class StepWizardBuilder extends LayoutContainerMixin {
1354
+ constructor() {
1355
+ super('step-wizard');
1356
+ this.steps = [];
1357
+ this.linear = true;
1358
+ this.wizardDirection = 'horizontal';
1359
+ }
1360
+ setLinear(linear) {
1361
+ this.linear = linear;
1362
+ return this;
1363
+ }
1364
+ setDirection(direction) {
1365
+ this.wizardDirection = direction;
1366
+ return this;
1367
+ }
1368
+ setLook(look) {
1369
+ this.look = look;
1370
+ return this;
1371
+ }
1372
+ setShowActions(show) {
1373
+ this.showActions = show;
1374
+ return this;
1375
+ }
1376
+ setActions(actions) {
1377
+ this.wizardActions = actions;
1378
+ return this;
1379
+ }
1380
+ setGuards(guards) {
1381
+ this.guards = guards;
1382
+ return this;
1383
+ }
1384
+ setEvents(events) {
1385
+ this.events = events;
1386
+ return this;
1387
+ }
1388
+ step(id, title, delegate) {
1389
+ const stepBuilder = new StepBuilder(id, title);
1390
+ // ✅ IMPORTANT: Propagate inheritance context to step
1391
+ stepBuilder.withInheritanceContext(this.inheritanceContext);
1392
+ if (delegate) {
1393
+ delegate(stepBuilder);
1394
+ }
1395
+ this.steps.push(stepBuilder.build());
1396
+ return this;
1397
+ }
1398
+ build() {
1399
+ // ✅ Validation
1400
+ if (this.steps.length === 0) {
1401
+ throw new Error('StepWizard must have at least one step');
1402
+ }
1403
+ // ✅ Check duplicate IDs
1404
+ const ids = this.steps.map((s) => s.id);
1405
+ const duplicates = ids.filter((id, index) => ids.indexOf(id) !== index);
1406
+ if (duplicates.length > 0) {
1407
+ throw new Error(`Duplicate step IDs found: ${duplicates.join(', ')}`);
1408
+ }
1409
+ const definition = {
1410
+ steps: this.steps,
1411
+ linear: this.linear,
1412
+ direction: this.wizardDirection,
1413
+ look: this.look,
1414
+ // Do not auto-detect based on dialog context; keep explicit or undefined
1415
+ showActions: this.showActions,
1416
+ actions: this.wizardActions,
1417
+ guards: this.guards,
1418
+ events: this.events,
1419
+ };
1420
+ const node = {
1421
+ name: this.containerState.name,
1422
+ type: 'step-wizard',
1423
+ options: { definition },
1424
+ mode: this.containerState.mode,
1425
+ };
1426
+ return node;
1427
+ }
1428
+ }
1258
1429
 
1259
1430
  class AXPLayoutConversionService {
1260
1431
  constructor() {
@@ -1884,29 +2055,60 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
1884
2055
  constructor() {
1885
2056
  super(...arguments);
1886
2057
  this.result = new EventEmitter();
2058
+ this.expressionEvaluator = inject(AXPExpressionEvaluatorService);
1887
2059
  this.context = signal({}, ...(ngDevMode ? [{ debugName: "context" }] : []));
1888
2060
  // This will be set by the popup service automatically - same as dynamic-dialog
1889
2061
  this.callBack = () => { };
1890
2062
  this.isDialogLoading = signal(false, ...(ngDevMode ? [{ debugName: "isDialogLoading" }] : []));
2063
+ // Aggregated actions for footer rendering
2064
+ this.footerPrefix = signal([], ...(ngDevMode ? [{ debugName: "footerPrefix" }] : []));
2065
+ this.footerSuffix = signal([], ...(ngDevMode ? [{ debugName: "footerSuffix" }] : []));
2066
+ //#endregion
2067
+ //#region ---- View Accessors ----
2068
+ // Access the internal layout renderer to reach the widgets container injector
2069
+ this.layoutRenderer = viewChild(AXPLayoutRendererComponent, ...(ngDevMode ? [{ debugName: "layoutRenderer" }] : []));
2070
+ this.#eff = effect(() => {
2071
+ let count = 0;
2072
+ if (!this.widgetCoreService) {
2073
+ const renderer = this.layoutRenderer();
2074
+ const container = renderer?.getContainer();
2075
+ this.widgetCoreService = container?.builderService ?? null;
2076
+ count = this.widgetCoreService.registeredWidgetsCount();
2077
+ }
2078
+ else {
2079
+ count = this.widgetCoreService.registeredWidgetsCount();
2080
+ // Clear existing timer
2081
+ if (this.debounceTimer) {
2082
+ clearTimeout(this.debounceTimer);
2083
+ }
2084
+ // Set new timer to call after 200ms of no count changes
2085
+ this.debounceTimer = setTimeout(() => {
2086
+ this.aggregateAndEvaluateActions();
2087
+ }, 200);
2088
+ }
2089
+ }, ...(ngDevMode ? [{ debugName: "#eff" }] : []));
1891
2090
  }
2091
+ //#endregion
2092
+ //#region ---- Lifecycle ----
1892
2093
  ngOnInit() {
1893
2094
  // Initialize context with provided context
1894
2095
  this.context.set(this.config?.context || {});
1895
2096
  }
2097
+ #eff;
2098
+ //#endregion
1896
2099
  handleContextChanged(event) {
1897
2100
  this.context.set(event);
2101
+ this.aggregateAndEvaluateActions();
1898
2102
  }
1899
2103
  handleContextInitiated(event) {
1900
2104
  this.context.set(event);
2105
+ this.aggregateAndEvaluateActions();
1901
2106
  }
1902
- visibleFooterPrefixActions() {
1903
- return this.config?.actions?.footer?.prefix || [];
2107
+ footerPrefixActions() {
2108
+ return this.footerPrefix();
1904
2109
  }
1905
- visibleFooterSuffixActions() {
1906
- return (this.config?.actions?.footer?.suffix || [
1907
- { title: 'Cancel', color: 'secondary', command: { name: 'cancel' } },
1908
- { title: 'Confirm', color: 'primary', command: { name: 'confirm' } },
1909
- ]);
2110
+ footerSuffixActions() {
2111
+ return this.footerSuffix();
1910
2112
  }
1911
2113
  isFormLoading() {
1912
2114
  return this.isDialogLoading();
@@ -1915,43 +2117,166 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
1915
2117
  return this.isDialogLoading();
1916
2118
  }
1917
2119
  async executeAction(action) {
1918
- const actionName = action.command?.name || action.title?.toLowerCase();
1919
- // Store the action and context - same pattern as dynamic-dialog
1920
- const result = {
1921
- context: this.context(),
1922
- action: actionName,
1923
- };
1924
- // Store result in component property
2120
+ const cmd = action.command;
2121
+ if (cmd !== 'cancel') {
2122
+ const isValid = await this.layoutRenderer()?.validate();
2123
+ if (!isValid?.result) {
2124
+ return;
2125
+ }
2126
+ }
2127
+ if (typeof cmd === 'string' && cmd.startsWith('widget:')) {
2128
+ const parsed = this.parseWidgetCommand(cmd);
2129
+ if (parsed.widgetName && parsed.action) {
2130
+ await this.executeWidgetApi(parsed.widgetName, parsed.action);
2131
+ await this.aggregateAndEvaluateActions();
2132
+ return;
2133
+ }
2134
+ }
2135
+ // Fallback: treat as regular dialog action (cancel/confirm/custom)
2136
+ const result = { context: this.context(), action: cmd };
1925
2137
  this.dialogResult = result;
1926
- // Store in popup data for DialogRef access
1927
2138
  if (this.data) {
1928
2139
  this.data.context = result.context;
1929
2140
  this.data.action = result.action;
1930
2141
  }
1931
- // Call the callback with DialogRef - same pattern as dynamic-dialog
1932
2142
  this.callBack({
1933
2143
  close: (result) => {
1934
2144
  this.close(result);
1935
2145
  },
1936
- context: () => {
1937
- return this.context();
1938
- },
1939
- action: () => {
1940
- return result.action;
1941
- },
2146
+ context: () => this.context(),
2147
+ action: () => result.action,
1942
2148
  setLoading: (loading) => {
1943
2149
  this.isDialogLoading.set(loading);
1944
2150
  },
1945
2151
  });
1946
2152
  }
1947
- close(result) {
2153
+ parseWidgetCommand(cmd) {
2154
+ // Expected 'widget:<widgetName>.<action>'
2155
+ if (!cmd?.startsWith('widget:'))
2156
+ return {};
2157
+ const rest = cmd.slice('widget:'.length);
2158
+ const dot = rest.lastIndexOf('.');
2159
+ if (dot <= 0)
2160
+ return {};
2161
+ return { widgetName: rest.slice(0, dot), action: rest.slice(dot + 1) };
2162
+ }
2163
+ async executeWidgetApi(widgetName, apiMethod) {
2164
+ if (!this.widgetCoreService)
2165
+ return;
2166
+ try {
2167
+ const widget = this.widgetCoreService.getWidget(widgetName);
2168
+ const api = widget?.api?.();
2169
+ const fn = api?.[apiMethod];
2170
+ if (typeof fn === 'function') {
2171
+ await Promise.resolve(fn({
2172
+ close: (result) => {
2173
+ this.close(result);
2174
+ },
2175
+ context: () => this.context(),
2176
+ setLoading: (loading) => {
2177
+ this.isDialogLoading.set(loading);
2178
+ },
2179
+ }));
2180
+ }
2181
+ }
2182
+ catch { }
2183
+ }
2184
+ async close(result) {
1948
2185
  if (result) {
1949
- this.result.emit(result);
2186
+ const isValid = await this.layoutRenderer()?.validate();
2187
+ if (isValid?.result) {
2188
+ this.result.emit(result);
2189
+ }
1950
2190
  }
1951
2191
  super.close(result);
1952
2192
  }
2193
+ // --- Actions aggregation & evaluation ---
2194
+ async aggregateAndEvaluateActions() {
2195
+ const widgetActions = await this.collectWidgetActions();
2196
+ const dialogActions = this.collectDialogActionsFromConfig();
2197
+ const all = [...widgetActions, ...dialogActions];
2198
+ const evaluated = await this.evaluatePredicates(all);
2199
+ const visible = evaluated.filter((a) => a.hidden !== true);
2200
+ const prefix = visible.filter((a) => (a.zone ?? 'footer') === 'footer' && (a.placement ?? 'suffix') === 'prefix');
2201
+ const suffix = visible.filter((a) => (a.zone ?? 'footer') === 'footer' && (a.placement ?? 'suffix') === 'suffix');
2202
+ this.footerPrefix.set(prefix);
2203
+ this.footerSuffix.set(suffix);
2204
+ }
2205
+ async collectWidgetActions() {
2206
+ if (!this.widgetCoreService)
2207
+ return [];
2208
+ const names = this.widgetCoreService.listRegisteredWidgetNames();
2209
+ const actions = [];
2210
+ for (const name of names) {
2211
+ try {
2212
+ const widget = this.widgetCoreService.getWidget(name);
2213
+ const widgetActs = widget?.actions?.() ?? [];
2214
+ actions.push(...widgetActs);
2215
+ }
2216
+ catch { }
2217
+ }
2218
+ return actions;
2219
+ }
2220
+ collectDialogActionsFromConfig() {
2221
+ const footer = this.config?.actions?.footer;
2222
+ const mapOne = (a, placement) => ({
2223
+ title: a.title,
2224
+ command: typeof a.command === 'string' ? a.command : a.command?.name,
2225
+ icon: a.icon,
2226
+ color: a.color,
2227
+ disabled: a.disabled,
2228
+ hidden: a.hidden,
2229
+ zone: 'footer',
2230
+ placement,
2231
+ scope: a.scope,
2232
+ });
2233
+ const prefix = (footer?.prefix || []).map((a) => mapOne(a, 'prefix'));
2234
+ const suffix = (footer?.suffix || []).map((a) => mapOne(a, 'suffix'));
2235
+ return [...prefix, ...suffix];
2236
+ }
2237
+ async evaluatePredicates(actions) {
2238
+ const out = [];
2239
+ for (const a of actions) {
2240
+ const parsed = typeof a.command === 'string' ? this.parseWidgetCommand(a.command) : {};
2241
+ const api = parsed.widgetName ? await this.resolveApi(parsed.widgetName) : undefined;
2242
+ const scope = {
2243
+ api,
2244
+ widget: { name: parsed.widgetName },
2245
+ dialog: { context: this.context() },
2246
+ context: this.context(),
2247
+ };
2248
+ const disabled = await this.evalBool(a.disabled, scope);
2249
+ const hidden = await this.evalBool(a.hidden, scope);
2250
+ out.push({ ...a, disabled, hidden });
2251
+ }
2252
+ return out;
2253
+ }
2254
+ async evalBool(value, scope) {
2255
+ if (typeof value === 'boolean')
2256
+ return value;
2257
+ if (typeof value === 'string') {
2258
+ try {
2259
+ const result = await this.expressionEvaluator.evaluate(value, scope);
2260
+ return !!result;
2261
+ }
2262
+ catch {
2263
+ return false;
2264
+ }
2265
+ }
2266
+ return value;
2267
+ }
2268
+ async resolveApi(widgetName) {
2269
+ try {
2270
+ await this.widgetCoreService?.waitForWidget(widgetName, 2000);
2271
+ const widget = this.widgetCoreService?.getWidget(widgetName);
2272
+ return widget?.api?.();
2273
+ }
2274
+ catch {
2275
+ return undefined;
2276
+ }
2277
+ }
1953
2278
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXPDialogRendererComponent, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
1954
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: AXPDialogRendererComponent, isStandalone: true, selector: "axp-dialog-renderer", inputs: { config: "config" }, outputs: { result: "result" }, usesInheritance: true, ngImport: i0, template: `
2279
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.4", type: AXPDialogRendererComponent, isStandalone: true, selector: "axp-dialog-renderer", inputs: { config: "config" }, outputs: { result: "result" }, viewQueries: [{ propertyName: "layoutRenderer", first: true, predicate: AXPLayoutRendererComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `
1955
2280
  <div class="ax-p-4">
1956
2281
  <axp-layout-renderer
1957
2282
  [layout]="config.definition"
@@ -1964,52 +2289,42 @@ class AXPDialogRendererComponent extends AXBasePageComponent {
1964
2289
 
1965
2290
  <ax-footer>
1966
2291
  <ax-prefix>
1967
- <ng-container *ngTemplateOutlet="footerPrefixActions"></ng-container>
2292
+ @for (action of footerPrefixActions(); track $index) {
2293
+ <ax-button
2294
+ [disabled]="action.disabled || isFormLoading()"
2295
+ [text]="(action.title | translate | async)!"
2296
+ [look]="'outline'"
2297
+ [color]="action.color"
2298
+ (onClick)="executeAction(action)"
2299
+ >
2300
+ <ax-prefix>
2301
+ <i class="{{ action.icon }}"></i>
2302
+ </ax-prefix>
2303
+ </ax-button>
2304
+ }
1968
2305
  </ax-prefix>
1969
2306
  <ax-suffix>
1970
- <ng-container *ngTemplateOutlet="footerSuffixActions"></ng-container>
2307
+ @for (action of footerSuffixActions(); track $index) {
2308
+ <ax-button
2309
+ [disabled]="action.disabled || isSubmitting()"
2310
+ [text]="(action.title | translate | async)!"
2311
+ [look]="'solid'"
2312
+ [color]="action.color"
2313
+ (onClick)="executeAction(action)"
2314
+ >
2315
+ @if (isFormLoading()) {
2316
+ <ax-loading></ax-loading>
2317
+ }
2318
+ @if (action.icon) {
2319
+ <ax-prefix>
2320
+ <ax-icon icon="{{ action.icon }}"></ax-icon>
2321
+ </ax-prefix>
2322
+ }
2323
+ </ax-button>
2324
+ }
1971
2325
  </ax-suffix>
1972
2326
  </ax-footer>
1973
-
1974
- <!-- Footer Prefix Actions -->
1975
- <ng-template #footerPrefixActions>
1976
- @for (action of visibleFooterPrefixActions(); track $index) {
1977
- <ax-button
1978
- [disabled]="action.disabled || isFormLoading()"
1979
- [text]="(action.title | translate | async)!"
1980
- [look]="'outline'"
1981
- [color]="action.color"
1982
- (onClick)="executeAction(action)"
1983
- >
1984
- @if (isFormLoading() && action.command?.name != 'cancel') {
1985
- <ax-loading></ax-loading>
1986
- }
1987
- <ax-prefix>
1988
- <i class="{{ action.icon }}"></i>
1989
- </ax-prefix>
1990
- </ax-button>
1991
- }
1992
- </ng-template>
1993
-
1994
- <!-- Footer Suffix Actions -->
1995
- <ng-template #footerSuffixActions>
1996
- @for (action of visibleFooterSuffixActions(); track $index) {
1997
- <ax-button
1998
- [disabled]="action.disabled || isSubmitting()"
1999
- [text]="(action.title | translate | async)!"
2000
- [look]="'solid'"
2001
- [color]="action.color"
2002
- (onClick)="executeAction(action)"
2003
- >
2004
- @if (action.icon) {
2005
- <ax-prefix>
2006
- <ax-icon icon="{{ action.icon }}"></ax-icon>
2007
- </ax-prefix>
2008
- }
2009
- </ax-button>
2010
- }
2011
- </ng-template>
2012
- `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: AXPLayoutRendererComponent, selector: "axp-layout-renderer", inputs: ["layout", "context", "look", "mode"], outputs: ["contextChange", "contextInitiated", "validityChange"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i2$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i3.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i3.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i4.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }] }); }
2327
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "component", type: AXPLayoutRendererComponent, selector: "axp-layout-renderer", inputs: ["layout", "context", "look", "mode"], outputs: ["contextChange", "contextInitiated", "validityChange"] }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1$1.AXButtonComponent, selector: "ax-button", inputs: ["disabled", "size", "tabIndex", "color", "look", "text", "toggleable", "selected", "iconOnly", "type", "loadingText"], outputs: ["onBlur", "onFocus", "onClick", "selectedChange", "toggleableChange", "lookChange", "colorChange", "disabledChange", "loadingTextChange"] }, { kind: "ngmodule", type: AXDecoratorModule }, { kind: "component", type: i2$1.AXDecoratorIconComponent, selector: "ax-icon", inputs: ["icon"] }, { kind: "component", type: i2$1.AXDecoratorGenericComponent, selector: "ax-footer, ax-header, ax-content, ax-divider, ax-form-hint, ax-prefix, ax-suffix, ax-text, ax-title, ax-subtitle, ax-placeholder, ax-overlay" }, { kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i3.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i5.AXTranslatorPipe, name: "translate" }] }); }
2013
2328
  }
2014
2329
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImport: i0, type: AXPDialogRendererComponent, decorators: [{
2015
2330
  type: Component,
@@ -2037,51 +2352,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.4", ngImpor
2037
2352
 
2038
2353
  <ax-footer>
2039
2354
  <ax-prefix>
2040
- <ng-container *ngTemplateOutlet="footerPrefixActions"></ng-container>
2355
+ @for (action of footerPrefixActions(); track $index) {
2356
+ <ax-button
2357
+ [disabled]="action.disabled || isFormLoading()"
2358
+ [text]="(action.title | translate | async)!"
2359
+ [look]="'outline'"
2360
+ [color]="action.color"
2361
+ (onClick)="executeAction(action)"
2362
+ >
2363
+ <ax-prefix>
2364
+ <i class="{{ action.icon }}"></i>
2365
+ </ax-prefix>
2366
+ </ax-button>
2367
+ }
2041
2368
  </ax-prefix>
2042
2369
  <ax-suffix>
2043
- <ng-container *ngTemplateOutlet="footerSuffixActions"></ng-container>
2370
+ @for (action of footerSuffixActions(); track $index) {
2371
+ <ax-button
2372
+ [disabled]="action.disabled || isSubmitting()"
2373
+ [text]="(action.title | translate | async)!"
2374
+ [look]="'solid'"
2375
+ [color]="action.color"
2376
+ (onClick)="executeAction(action)"
2377
+ >
2378
+ @if (isFormLoading()) {
2379
+ <ax-loading></ax-loading>
2380
+ }
2381
+ @if (action.icon) {
2382
+ <ax-prefix>
2383
+ <ax-icon icon="{{ action.icon }}"></ax-icon>
2384
+ </ax-prefix>
2385
+ }
2386
+ </ax-button>
2387
+ }
2044
2388
  </ax-suffix>
2045
2389
  </ax-footer>
2046
-
2047
- <!-- Footer Prefix Actions -->
2048
- <ng-template #footerPrefixActions>
2049
- @for (action of visibleFooterPrefixActions(); track $index) {
2050
- <ax-button
2051
- [disabled]="action.disabled || isFormLoading()"
2052
- [text]="(action.title | translate | async)!"
2053
- [look]="'outline'"
2054
- [color]="action.color"
2055
- (onClick)="executeAction(action)"
2056
- >
2057
- @if (isFormLoading() && action.command?.name != 'cancel') {
2058
- <ax-loading></ax-loading>
2059
- }
2060
- <ax-prefix>
2061
- <i class="{{ action.icon }}"></i>
2062
- </ax-prefix>
2063
- </ax-button>
2064
- }
2065
- </ng-template>
2066
-
2067
- <!-- Footer Suffix Actions -->
2068
- <ng-template #footerSuffixActions>
2069
- @for (action of visibleFooterSuffixActions(); track $index) {
2070
- <ax-button
2071
- [disabled]="action.disabled || isSubmitting()"
2072
- [text]="(action.title | translate | async)!"
2073
- [look]="'solid'"
2074
- [color]="action.color"
2075
- (onClick)="executeAction(action)"
2076
- >
2077
- @if (action.icon) {
2078
- <ax-prefix>
2079
- <ax-icon icon="{{ action.icon }}"></ax-icon>
2080
- </ax-prefix>
2081
- }
2082
- </ax-button>
2083
- }
2084
- </ng-template>
2085
2390
  `,
2086
2391
  }]
2087
2392
  }], propDecorators: { config: [{