@acorex/platform 21.0.0-next.88 → 21.0.0-next.89

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 (52) hide show
  1. package/fesm2022/acorex-platform-auth.mjs +8 -2
  2. package/fesm2022/acorex-platform-auth.mjs.map +1 -1
  3. package/fesm2022/{acorex-platform-common-common-settings.provider-VfmZct9H.mjs → acorex-platform-common-common-settings.provider-DilV4dql.mjs} +15 -42
  4. package/fesm2022/acorex-platform-common-common-settings.provider-DilV4dql.mjs.map +1 -0
  5. package/fesm2022/acorex-platform-common.mjs +3299 -3200
  6. package/fesm2022/acorex-platform-common.mjs.map +1 -1
  7. package/fesm2022/acorex-platform-core.mjs +621 -26
  8. package/fesm2022/acorex-platform-core.mjs.map +1 -1
  9. package/fesm2022/acorex-platform-layout-builder.mjs +98 -189
  10. package/fesm2022/acorex-platform-layout-builder.mjs.map +1 -1
  11. package/fesm2022/{acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs → acorex-platform-layout-components-binding-expression-editor-popup.component-RttFwaw9.mjs} +17 -4
  12. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-RttFwaw9.mjs.map +1 -0
  13. package/fesm2022/acorex-platform-layout-components.mjs +125 -26
  14. package/fesm2022/acorex-platform-layout-components.mjs.map +1 -1
  15. package/fesm2022/acorex-platform-layout-designer.mjs +4 -4
  16. package/fesm2022/acorex-platform-layout-designer.mjs.map +1 -1
  17. package/fesm2022/acorex-platform-layout-entity-contracts.mjs +106 -12
  18. package/fesm2022/acorex-platform-layout-entity-contracts.mjs.map +1 -1
  19. package/fesm2022/acorex-platform-layout-entity.mjs +419 -147
  20. package/fesm2022/acorex-platform-layout-entity.mjs.map +1 -1
  21. package/fesm2022/acorex-platform-layout-views.mjs +851 -162
  22. package/fesm2022/acorex-platform-layout-views.mjs.map +1 -1
  23. package/fesm2022/acorex-platform-layout-widget-core.mjs +378 -103
  24. package/fesm2022/acorex-platform-layout-widget-core.mjs.map +1 -1
  25. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-D4MOHEpI.mjs → acorex-platform-layout-widgets-tabular-data-edit-popup.component-CZc2zFlg.mjs} +2 -2
  26. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-edit-popup.component-D4MOHEpI.mjs.map → acorex-platform-layout-widgets-tabular-data-edit-popup.component-CZc2zFlg.mjs.map} +1 -1
  27. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs → acorex-platform-layout-widgets-tabular-data-view-popup.component-XWRUVoL4.mjs} +2 -2
  28. package/fesm2022/{acorex-platform-layout-widgets-tabular-data-view-popup.component-gX-3Kx9I.mjs.map → acorex-platform-layout-widgets-tabular-data-view-popup.component-XWRUVoL4.mjs.map} +1 -1
  29. package/fesm2022/acorex-platform-layout-widgets.mjs +575 -239
  30. package/fesm2022/acorex-platform-layout-widgets.mjs.map +1 -1
  31. package/fesm2022/acorex-platform-themes-default.mjs +221 -24
  32. package/fesm2022/acorex-platform-themes-default.mjs.map +1 -1
  33. package/fesm2022/{acorex-platform-themes-shared-settings.provider-BUwPqwUS.mjs → acorex-platform-themes-shared-settings.provider-UyKdkeyk.mjs} +48 -1
  34. package/fesm2022/acorex-platform-themes-shared-settings.provider-UyKdkeyk.mjs.map +1 -0
  35. package/fesm2022/acorex-platform-themes-shared.mjs +103 -24
  36. package/fesm2022/acorex-platform-themes-shared.mjs.map +1 -1
  37. package/package.json +1 -1
  38. package/types/acorex-platform-auth.d.ts +1 -0
  39. package/types/acorex-platform-common.d.ts +202 -151
  40. package/types/acorex-platform-core.d.ts +161 -6
  41. package/types/acorex-platform-layout-builder.d.ts +10 -20
  42. package/types/acorex-platform-layout-components.d.ts +14 -1
  43. package/types/acorex-platform-layout-entity-contracts.d.ts +27 -2
  44. package/types/acorex-platform-layout-entity.d.ts +61 -12
  45. package/types/acorex-platform-layout-views.d.ts +101 -19
  46. package/types/acorex-platform-layout-widget-core.d.ts +65 -9
  47. package/types/acorex-platform-layout-widgets.d.ts +48 -26
  48. package/types/acorex-platform-themes-default.d.ts +56 -5
  49. package/types/acorex-platform-themes-shared.d.ts +4 -0
  50. package/fesm2022/acorex-platform-common-common-settings.provider-VfmZct9H.mjs.map +0 -1
  51. package/fesm2022/acorex-platform-layout-components-binding-expression-editor-popup.component-CXEdvDTf.mjs.map +0 -1
  52. package/fesm2022/acorex-platform-themes-shared-settings.provider-BUwPqwUS.mjs.map +0 -1
@@ -1,9 +1,9 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, Injectable, Directive, computed, Injector, ChangeDetectionStrategy, Component, input, ElementRef, ViewContainerRef, signal, effect, runInInjectionContext, Optional, Inject, NgModule, EventEmitter, HostListener, Output, provideAppInitializer, Pipe } from '@angular/core';
2
+ import { InjectionToken, inject, Injectable, Directive, computed, Injector, ChangeDetectionStrategy, Component, input, ElementRef, ViewContainerRef, signal, effect, runInInjectionContext, Optional, Inject, NgModule, EventEmitter, HostListener, Output, DestroyRef, untracked, provideAppInitializer, Pipe } from '@angular/core';
3
3
  import { AXTranslationService, resolveMultiLanguageString } from '@acorex/core/translation';
4
4
  import { AXDataSource } from '@acorex/cdk/common';
5
5
  import { AXPPlatformCoreDataSourceKeys, AXPSystemActionType } from '@acorex/platform/contracts';
6
- import { isPlainObject, get, set, isNil, isEmpty, isArray, merge, isObjectLike, transform, isEqual, differenceWith, union, cloneDeep, has, sortBy, isUndefined, endsWith, startsWith, includes, lte, gte, lt, gt, orderBy } from 'lodash-es';
6
+ import { isPlainObject, get, set, isNil, isEmpty, isArray, merge, isObjectLike, transform, isEqual, differenceWith, union, cloneDeep, has, unset, sortBy, isUndefined, endsWith, startsWith, includes, lte, gte, lt, gt, orderBy } from 'lodash-es';
7
7
  import { signalStore, withState, withComputed, withMethods, patchState } from '@ngrx/signals';
8
8
  import { AXFormatService } from '@acorex/core/format';
9
9
  import * as i1 from '@acorex/components/skeleton';
@@ -12,6 +12,7 @@ import { Subject, interval, fromEvent } from 'rxjs';
12
12
  import { toSignal } from '@angular/core/rxjs-interop';
13
13
  import { DOCUMENT } from '@angular/common';
14
14
  import { AXLocaleService } from '@acorex/core/locale';
15
+ import { delay } from '@acorex/core/utils';
15
16
  import { AXCalendarService } from '@acorex/core/date-time';
16
17
  import { startWith, map, debounceTime } from 'rxjs/operators';
17
18
 
@@ -706,6 +707,104 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
706
707
  type: Directive
707
708
  }] });
708
709
 
710
+ //#region ---- Imports ----
711
+ //#endregion
712
+ //#region ---- Debug Service ----
713
+ /**
714
+ * Platform debug and trace logging.
715
+ * Call `trace` / `traceGroup` for diagnostics (gated by tenant Debug Mode).
716
+ * Call `warn` / `error` for always-on console output.
717
+ *
718
+ * Debug Mode is applied via `setDebugMode()` (wired from settings in platform common).
719
+ */
720
+ class AXPDebugService {
721
+ //#endregion
722
+ //#region ---- Lifecycle ----
723
+ constructor() {
724
+ //#endregion
725
+ //#region ---- State ----
726
+ this.debugModeEnabled = false;
727
+ AXPDebugService.instance = this;
728
+ }
729
+ //#endregion
730
+ //#region ---- Debug Mode ----
731
+ isDebugMode() {
732
+ return this.debugModeEnabled;
733
+ }
734
+ setDebugMode(enabled) {
735
+ this.debugModeEnabled = enabled;
736
+ }
737
+ //#endregion
738
+ //#region ---- Trace API ----
739
+ /**
740
+ * @param namespace Module/feature namespace (kebab-case). Filter console with `[AXP:<namespace>]`.
741
+ * @param title Short area name (component, service, middleware).
742
+ * @param message What happened.
743
+ * @param data Optional structured payload, or a factory evaluated only when Debug Mode is on.
744
+ */
745
+ trace(namespace, title, message, data) {
746
+ if (!this.debugModeEnabled) {
747
+ return;
748
+ }
749
+ this.log('log', namespace, title, message, data);
750
+ }
751
+ /**
752
+ * Same as {@link trace} but emits a collapsible console group (useful for multi-field payloads).
753
+ */
754
+ traceGroup(namespace, title, message, data) {
755
+ if (!this.debugModeEnabled) {
756
+ return;
757
+ }
758
+ const resolved = this.resolveData(data);
759
+ console.groupCollapsed(this.formatPrefix(namespace, title, message));
760
+ if (resolved != null) {
761
+ for (const [key, value] of Object.entries(resolved)) {
762
+ if (value !== undefined) {
763
+ console.log(key, value);
764
+ }
765
+ }
766
+ }
767
+ console.groupEnd();
768
+ }
769
+ warn(namespace, title, message, data) {
770
+ this.log('warn', namespace, title, message, data);
771
+ }
772
+ error(namespace, title, message, data) {
773
+ this.log('error', namespace, title, message, data);
774
+ }
775
+ //#endregion
776
+ //#region ---- Utility Methods ----
777
+ formatPrefix(namespace, title, message) {
778
+ return `[AXP:${namespace}] ${title} — ${message}`;
779
+ }
780
+ resolveData(data) {
781
+ if (data == null) {
782
+ return undefined;
783
+ }
784
+ return typeof data === 'function' ? data() : data;
785
+ }
786
+ log(level, namespace, title, message, data) {
787
+ const prefix = this.formatPrefix(namespace, title, message);
788
+ const resolved = this.resolveData(data);
789
+ if (resolved != null) {
790
+ console[level](prefix, resolved);
791
+ return;
792
+ }
793
+ console[level](prefix);
794
+ }
795
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDebugService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
796
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDebugService, providedIn: 'root' }); }
797
+ }
798
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPDebugService, decorators: [{
799
+ type: Injectable,
800
+ args: [{
801
+ providedIn: 'root',
802
+ }]
803
+ }], ctorParameters: () => [] });
804
+
805
+ /** Trace namespace for form dirty-state diagnostics (lookup/select revert, discard, baseline). */
806
+ const FORM_DIRTY_TRACE_NS = 'FORM STATE';
807
+
709
808
  //#region ---- Locale map shape ----
710
809
  /** Per-locale string map (`{ 'en-US': '...', 'fa-IR': '...' }`). */
711
810
  function isLocaleStringMap(value) {
@@ -1028,6 +1127,13 @@ function normalizeLocaleStringMap(value) {
1028
1127
  }
1029
1128
  return Object.keys(normalized).length === 0 ? null : normalized;
1030
1129
  }
1130
+ function compareMultiLanguageLocaleStrings(a, b) {
1131
+ const htmlEqual = compareHtmlFormValues(a, b);
1132
+ if (htmlEqual !== null) {
1133
+ return htmlEqual;
1134
+ }
1135
+ return a === b;
1136
+ }
1031
1137
  /**
1032
1138
  * Compares multi-language field values (plain string vs locale map) for dirty/baseline checks.
1033
1139
  * Returns `null` when either side is not a multi-language shape (caller uses generic normalization).
@@ -1058,15 +1164,13 @@ function compareMultiLanguageFormValues(a, b) {
1058
1164
  return false;
1059
1165
  }
1060
1166
  if (typeof left === 'string' && typeof right === 'string') {
1061
- return left === right;
1167
+ return compareMultiLanguageLocaleStrings(left, right);
1062
1168
  }
1063
1169
  if (typeof left === 'string' && typeof right === 'object') {
1064
- const values = Object.values(right);
1065
- return values.length > 0 && values.every((text) => text === left);
1170
+ return Object.values(right).some((text) => typeof text === 'string' && compareMultiLanguageLocaleStrings(left, text));
1066
1171
  }
1067
1172
  if (typeof right === 'string' && typeof left === 'object') {
1068
- const values = Object.values(left);
1069
- return values.length > 0 && values.every((text) => text === right);
1173
+ return Object.values(left).some((text) => typeof text === 'string' && compareMultiLanguageLocaleStrings(right, text));
1070
1174
  }
1071
1175
  if (typeof left !== 'object' || typeof right !== 'object') {
1072
1176
  return false;
@@ -1078,7 +1182,56 @@ function compareMultiLanguageFormValues(a, b) {
1078
1182
  if (leftKeys.length !== rightKeys.length) {
1079
1183
  return false;
1080
1184
  }
1081
- return leftKeys.every((key) => leftMap[key] === rightMap[key]);
1185
+ return leftKeys.every((key) => compareMultiLanguageLocaleStrings(leftMap[key], rightMap[key]));
1186
+ }
1187
+ /**
1188
+ * Lookup/select expose may write a resolved MLS string while the baseline keeps the locale map.
1189
+ * Restore baseline shape when the string matches any locale entry.
1190
+ */
1191
+ function shouldRestoreSavedMultiLanguageShape(value, savedAtPath) {
1192
+ if (typeof value !== 'string' || !isLocaleStringMap(savedAtPath)) {
1193
+ return false;
1194
+ }
1195
+ const trimmed = value.trim();
1196
+ if (trimmed === '') {
1197
+ return false;
1198
+ }
1199
+ return Object.values(savedAtPath).some((entry) => typeof entry === 'string' && entry.trim() === trimmed);
1200
+ }
1201
+ /** Decode common HTML entities for rich-text baseline compare. */
1202
+ function decodeHtmlEntities(value) {
1203
+ return value
1204
+ .replace(/&#x([0-9a-f]+);/gi, (_, hex) => String.fromCharCode(parseInt(hex, 16)))
1205
+ .replace(/&#(\d+);/g, (_, dec) => String.fromCharCode(parseInt(dec, 10)))
1206
+ .replace(/&amp;/g, '&')
1207
+ .replace(/&lt;/g, '<')
1208
+ .replace(/&gt;/g, '>')
1209
+ .replace(/&quot;/g, '"');
1210
+ }
1211
+ function looksLikeHtmlFormValue(value) {
1212
+ return /<[a-z][\s\S]*>/i.test(value.trim());
1213
+ }
1214
+ /** Normalizes rich-text HTML for semantic dirty/baseline compare (e.g. Quill `p`/`br` drift). */
1215
+ function normalizeRichTextHtmlForCompare(value) {
1216
+ const html = decodeHtmlEntities(value.trim());
1217
+ if (typeof document === 'undefined') {
1218
+ return html.replace(/\s+/g, ' ').trim();
1219
+ }
1220
+ const doc = new DOMParser().parseFromString(html, 'text/html');
1221
+ return (doc.body.textContent ?? '').replace(/\s+/g, ' ').trim();
1222
+ }
1223
+ /**
1224
+ * Compares rich-text HTML strings by visible text (ignores `p` vs `br` structure drift).
1225
+ * Returns `null` when either side is not HTML markup.
1226
+ */
1227
+ function compareHtmlFormValues(a, b) {
1228
+ if (typeof a !== 'string' || typeof b !== 'string') {
1229
+ return null;
1230
+ }
1231
+ if (!looksLikeHtmlFormValue(a) || !looksLikeHtmlFormValue(b)) {
1232
+ return null;
1233
+ }
1234
+ return normalizeRichTextHtmlForCompare(a) === normalizeRichTextHtmlForCompare(b);
1082
1235
  }
1083
1236
  /** Lookup/select filter-mode payload: `{ value, displayText?, operation }`. */
1084
1237
  function isFilterFormShape(value) {
@@ -1286,6 +1439,12 @@ function isFormValueEqual(a, b) {
1286
1439
  }
1287
1440
  return true;
1288
1441
  }
1442
+ if (typeof a === 'string' && typeof b === 'string') {
1443
+ const htmlEqual = compareHtmlFormValues(a, b);
1444
+ if (htmlEqual !== null) {
1445
+ return htmlEqual;
1446
+ }
1447
+ }
1289
1448
  return isEqual(normalizeFormValue(a), normalizeFormValue(b));
1290
1449
  }
1291
1450
  /**
@@ -1294,6 +1453,45 @@ function isFormValueEqual(a, b) {
1294
1453
  function isFormContextDirty(current, baseline) {
1295
1454
  return !isFormValueEqual(current, baseline);
1296
1455
  }
1456
+ /**
1457
+ * Lists paths where live context differs from baseline (for dirty-state trace logs).
1458
+ */
1459
+ function summarizeFormContextDirtyDiff(current, baseline, maxEntries = 12) {
1460
+ const diffs = [];
1461
+ const walk = (path, currentValue, baselineValue) => {
1462
+ if (diffs.length >= maxEntries) {
1463
+ return;
1464
+ }
1465
+ if (isFormValueEqual(currentValue, baselineValue)) {
1466
+ return;
1467
+ }
1468
+ const bothPlainObjects = isPlainObject(currentValue) &&
1469
+ isPlainObject(baselineValue) &&
1470
+ !isArray(currentValue) &&
1471
+ !isArray(baselineValue);
1472
+ if (bothPlainObjects) {
1473
+ const left = currentValue;
1474
+ const right = baselineValue;
1475
+ const keys = new Set([...Object.keys(left), ...Object.keys(right)]);
1476
+ for (const key of keys) {
1477
+ if (diffs.length >= maxEntries) {
1478
+ return;
1479
+ }
1480
+ const nextPath = path ? `${path}.${key}` : key;
1481
+ walk(nextPath, left[key], right[key]);
1482
+ }
1483
+ return;
1484
+ }
1485
+ diffs.push({
1486
+ path: path || '(root)',
1487
+ current: currentValue,
1488
+ baseline: baselineValue,
1489
+ selectionEqual: isSelectionValueEqual(currentValue, baselineValue),
1490
+ });
1491
+ };
1492
+ walk('', current, baseline);
1493
+ return diffs;
1494
+ }
1297
1495
  /**
1298
1496
  * Clones a context object for use as a dirty-tracking baseline.
1299
1497
  */
@@ -1312,20 +1510,26 @@ const AXPContextStore = signalStore(withState(() => ({
1312
1510
  /** Last committed / saved baseline — discard reverts to this snapshot. */
1313
1511
  savedSnapshot: {},
1314
1512
  previousSnapshot: {},
1513
+ /** True after a user-origin update since the last {@link commitSaved}. */
1514
+ userEditedSinceCommit: false,
1315
1515
  lastChange: {
1316
1516
  state: 'initiated',
1317
1517
  },
1318
- })), withComputed(({ data, state, lastChange, savedSnapshot, previousSnapshot }) => ({
1518
+ })), withComputed(({ data, state, lastChange, savedSnapshot, previousSnapshot, userEditedSinceCommit }) => ({
1319
1519
  isChanged: computed(() => state() === 'changed'),
1320
1520
  isReset: computed(() => state() === 'restored'),
1321
1521
  isInitiated: computed(() => state() === 'initiated'),
1322
1522
  isEmpty: computed(() => Object.keys(data()).length === 0),
1323
1523
  isSavedCommitted: computed(() => !isEmpty(savedSnapshot())),
1524
+ hasUserEditedSinceCommit: computed(() => userEditedSinceCommit()),
1324
1525
  isDirty: computed(() => {
1325
1526
  const saved = savedSnapshot();
1326
1527
  if (isEmpty(saved)) {
1327
1528
  return false;
1328
1529
  }
1530
+ if (!userEditedSinceCommit()) {
1531
+ return false;
1532
+ }
1329
1533
  return isFormContextDirty(data(), saved);
1330
1534
  }),
1331
1535
  snapshot: computed(() => cloneDeep(data())),
@@ -1335,24 +1539,80 @@ const AXPContextStore = signalStore(withState(() => ({
1335
1539
  previous: computed(() => cloneDeep(previousSnapshot())),
1336
1540
  changeEvent: computed(() => lastChange()),
1337
1541
  })), withMethods((store) => {
1542
+ const traceDirty = (title, message, data) => {
1543
+ AXPDebugService.instance?.trace(FORM_DIRTY_TRACE_NS, title, message, data);
1544
+ };
1545
+ const traceDirtyState = (reason, data, path) => {
1546
+ const saved = store.savedSnapshot();
1547
+ const current = store.data();
1548
+ const hasSaved = !isEmpty(saved);
1549
+ const contextDirty = hasSaved && isFormContextDirty(current, saved);
1550
+ traceDirty('context-store', reason, () => ({
1551
+ path,
1552
+ userEditedSinceCommit: store.userEditedSinceCommit(),
1553
+ isSavedCommitted: hasSaved,
1554
+ isFormContextDirty: contextDirty,
1555
+ isDirty: store.isDirty(),
1556
+ ...(hasSaved
1557
+ ? {
1558
+ dirtyPaths: contextDirty ? summarizeFormContextDirtyDiff(current, saved) : [],
1559
+ }
1560
+ : {}),
1561
+ ...data,
1562
+ }));
1563
+ };
1338
1564
  const updateValue = (path, value, options) => {
1339
1565
  const currentData = cloneDeep(store.data());
1340
1566
  const oldValue = getSmart(currentData, path);
1341
1567
  const hasSaved = !isEmpty(store.savedSnapshot());
1342
- const savedAtPath = hasSaved ? getSmart(store.savedSnapshot(), path) : undefined;
1568
+ const saved = store.savedSnapshot();
1569
+ const savedAtPath = hasSaved ? getSmart(saved, path) : undefined;
1570
+ const origin = options?.origin ?? 'system';
1343
1571
  if (hasSaved && isSelectionValueEqual(value, savedAtPath) && !isEqual(value, savedAtPath)) {
1344
1572
  value = cloneDeep(savedAtPath);
1345
1573
  }
1574
+ if (hasSaved && !isEqual(value, savedAtPath) && isFormValueEqual(value, savedAtPath)) {
1575
+ value = cloneDeep(savedAtPath);
1576
+ }
1346
1577
  const isArrayLengthChange = Array.isArray(value) && (!Array.isArray(oldValue) || value.length !== oldValue.length);
1347
- if (!isArrayLengthChange && isEqual(oldValue, value)) {
1578
+ /** Same selection id as baseline but different object shape (lookup/select item vs scalar). */
1579
+ const needsSavedShapeRestore = hasSaved && isSelectionValueEqual(value, savedAtPath) && !isFormValueEqual(value, savedAtPath);
1580
+ if (!isArrayLengthChange && isEqual(oldValue, value) && !needsSavedShapeRestore) {
1581
+ traceDirty('context-store', 'updateValue skipped (lodash isEqual)', () => ({
1582
+ path,
1583
+ origin,
1584
+ oldValue,
1585
+ value,
1586
+ needsSavedShapeRestore,
1587
+ selectionEqualToSaved: hasSaved ? isSelectionValueEqual(value, savedAtPath) : null,
1588
+ savedAtPath,
1589
+ }));
1348
1590
  return;
1349
1591
  }
1350
1592
  const shouldNormalizeSavedShape = hasSaved && isSelectionValueEqual(value, savedAtPath) && !isEqual(oldValue, value);
1351
- if (!isArrayLengthChange && isFormValueEqual(oldValue, value) && !shouldNormalizeSavedShape) {
1593
+ if (!isArrayLengthChange &&
1594
+ isFormValueEqual(oldValue, value) &&
1595
+ !shouldNormalizeSavedShape &&
1596
+ !needsSavedShapeRestore) {
1597
+ traceDirty('context-store', 'updateValue skipped (isFormValueEqual)', () => ({
1598
+ path,
1599
+ origin,
1600
+ oldValue,
1601
+ value,
1602
+ needsSavedShapeRestore,
1603
+ shouldNormalizeSavedShape,
1604
+ selectionEqualToSaved: hasSaved ? isSelectionValueEqual(value, savedAtPath) : null,
1605
+ savedAtPath,
1606
+ }));
1352
1607
  return;
1353
1608
  }
1354
- const origin = options?.origin ?? 'system';
1355
1609
  const updatedData = setSmart(currentData, path, value);
1610
+ const isStillDirty = hasSaved && isFormContextDirty(updatedData, saved);
1611
+ const nextUserEdited = isStillDirty
1612
+ ? origin === 'user'
1613
+ ? true
1614
+ : store.userEditedSinceCommit()
1615
+ : false;
1356
1616
  const changeEvent = {
1357
1617
  oldValue,
1358
1618
  newValue: value,
@@ -1366,7 +1626,22 @@ const AXPContextStore = signalStore(withState(() => ({
1366
1626
  data: updatedData,
1367
1627
  state: 'changed',
1368
1628
  lastChange: changeEvent,
1629
+ userEditedSinceCommit: nextUserEdited,
1369
1630
  });
1631
+ traceDirty('context-store', 'updateValue applied', () => ({
1632
+ path,
1633
+ origin,
1634
+ oldValue,
1635
+ newValue: value,
1636
+ savedAtPath,
1637
+ selectionEqualToSaved: hasSaved ? isSelectionValueEqual(value, savedAtPath) : null,
1638
+ formValueEqualToSaved: hasSaved ? isFormValueEqual(value, savedAtPath) : null,
1639
+ needsSavedShapeRestore,
1640
+ isStillDirty,
1641
+ nextUserEdited,
1642
+ isDirty: !isEmpty(saved) && nextUserEdited && isStillDirty,
1643
+ dirtyPaths: isStillDirty ? summarizeFormContextDirtyDiff(updatedData, saved) : [],
1644
+ }));
1370
1645
  };
1371
1646
  const applyObjectPaths = (obj, options, prefix = '') => {
1372
1647
  for (const [key, value] of Object.entries(obj ?? {})) {
@@ -1379,6 +1654,57 @@ const AXPContextStore = signalStore(withState(() => ({
1379
1654
  }
1380
1655
  }
1381
1656
  };
1657
+ const removePathFromContext = (path, origin = 'system') => {
1658
+ const currentData = cloneDeep(store.data());
1659
+ if (!has(currentData, path)) {
1660
+ return;
1661
+ }
1662
+ unset(currentData, path);
1663
+ const parts = path.split('.');
1664
+ for (let i = parts.length - 1; i > 0; i--) {
1665
+ const parentPath = parts.slice(0, i).join('.');
1666
+ const parentObj = getSmart(currentData, parentPath);
1667
+ if (isPlainObject(parentObj) && isEmpty(Object.keys(parentObj))) {
1668
+ unset(currentData, parentPath);
1669
+ }
1670
+ }
1671
+ const saved = store.savedSnapshot();
1672
+ const isStillDirty = !isEmpty(saved) && isFormContextDirty(currentData, saved);
1673
+ patchState(store, {
1674
+ previousSnapshot: store.snapshot(),
1675
+ data: currentData,
1676
+ state: 'changed',
1677
+ lastChange: {
1678
+ path,
1679
+ state: 'changed',
1680
+ data: currentData,
1681
+ origin,
1682
+ },
1683
+ userEditedSinceCommit: isStillDirty
1684
+ ? origin === 'user'
1685
+ ? true
1686
+ : store.userEditedSinceCommit()
1687
+ : false,
1688
+ });
1689
+ traceDirty('context-store', 'removePathFromContext', () => ({
1690
+ path,
1691
+ origin,
1692
+ isStillDirty,
1693
+ dirtyPaths: isStillDirty ? summarizeFormContextDirtyDiff(currentData, saved) : [],
1694
+ }));
1695
+ };
1696
+ const syncPathToSavedBaseline = (path, options) => {
1697
+ const saved = store.savedSnapshot();
1698
+ if (isEmpty(saved)) {
1699
+ return;
1700
+ }
1701
+ const origin = options?.origin ?? 'system';
1702
+ if (has(saved, path)) {
1703
+ updateValue(path, cloneDeep(getSmart(saved, path)), { origin });
1704
+ return;
1705
+ }
1706
+ removePathFromContext(path, origin);
1707
+ };
1382
1708
  const revertToSaved = () => {
1383
1709
  const savedData = store.saved();
1384
1710
  const changeEvent = {
@@ -1393,13 +1719,17 @@ const AXPContextStore = signalStore(withState(() => ({
1393
1719
  data: savedData,
1394
1720
  state: 'restored',
1395
1721
  lastChange: changeEvent,
1722
+ userEditedSinceCommit: false,
1396
1723
  });
1724
+ traceDirtyState('revertToSaved');
1397
1725
  };
1398
1726
  return {
1399
1727
  update(path, value, options) {
1400
1728
  updateValue(path, value, options);
1401
1729
  },
1402
1730
  applyObjectPaths,
1731
+ /** Aligns a context path with the saved baseline (restore value or remove if absent). */
1732
+ syncPathToSavedBaseline,
1403
1733
  patch(context, options) {
1404
1734
  const currentData = cloneDeep(store.data());
1405
1735
  const updatedData = { ...currentData, ...context };
@@ -1440,6 +1770,7 @@ const AXPContextStore = signalStore(withState(() => ({
1440
1770
  data: initialData,
1441
1771
  state: 'initiated',
1442
1772
  lastChange: changeEvent,
1773
+ userEditedSinceCommit: false,
1443
1774
  });
1444
1775
  },
1445
1776
  getValue(path) {
@@ -1458,11 +1789,13 @@ const AXPContextStore = signalStore(withState(() => ({
1458
1789
  savedSnapshot: snapshot,
1459
1790
  previousSnapshot: snapshot,
1460
1791
  state: 'initiated',
1792
+ userEditedSinceCommit: false,
1461
1793
  lastChange: {
1462
1794
  state: 'initiated',
1463
1795
  data: snapshot,
1464
1796
  },
1465
1797
  });
1798
+ traceDirtyState('commitSaved');
1466
1799
  },
1467
1800
  /** Merges parent-bound entity fields without resetting the saved baseline. */
1468
1801
  applyParentBind(merged) {
@@ -2826,12 +3159,12 @@ const HORIZONTAL_DIRECTIONAL_KEY_MIRRORS = {
2826
3159
  };
2827
3160
  /** Maps a horizontal direction key to its RTL semantic counterpart. */
2828
3161
  function mirrorHorizontalDirectionalKey(key) {
2829
- const normalized = normalizeShortcutToken(key);
3162
+ const normalized = normalizeShortcutToken$1(key);
2830
3163
  return HORIZONTAL_DIRECTIONAL_KEY_MIRRORS[normalized] ?? normalized;
2831
3164
  }
2832
3165
  /** True when the chord's primary key is a horizontal direction key (`←`/`→`, `[`/`]`). */
2833
3166
  function isHorizontalDirectionalShortcutKey(key) {
2834
- return normalizeShortcutToken(key) in HORIZONTAL_DIRECTIONAL_KEY_MIRRORS;
3167
+ return normalizeShortcutToken$1(key) in HORIZONTAL_DIRECTIONAL_KEY_MIRRORS;
2835
3168
  }
2836
3169
  /**
2837
3170
  * Resolves direction behavior for a chord.
@@ -2847,7 +3180,7 @@ function resolveEffectiveDirectionBehavior(chord, explicit) {
2847
3180
  }
2848
3181
  /** Resolves the key the user presses for a semantically registered chord in RTL. */
2849
3182
  function resolveSemanticDirectionalKey(storedKey, rtl) {
2850
- const normalized = normalizeShortcutToken(storedKey);
3183
+ const normalized = normalizeShortcutToken$1(storedKey);
2851
3184
  if (!rtl) {
2852
3185
  return normalized;
2853
3186
  }
@@ -2914,7 +3247,7 @@ function parseKeyboardShortcutChord(chord) {
2914
3247
  .split('+')
2915
3248
  .map((part) => part.trim())
2916
3249
  .filter(Boolean);
2917
- const key = normalizeShortcutToken(parts.pop() ?? '');
3250
+ const key = normalizeShortcutToken$1(parts.pop() ?? '');
2918
3251
  const parsed = {
2919
3252
  ctrl: false,
2920
3253
  shift: false,
@@ -2942,7 +3275,7 @@ function matchesKeyboardShortcutChord(event, chord, options) {
2942
3275
  return false;
2943
3276
  }
2944
3277
  const actualKey = normalizeShortcutEventKey(event);
2945
- const expectedKey = normalizeShortcutToken(parsed.key);
3278
+ const expectedKey = normalizeShortcutToken$1(parsed.key);
2946
3279
  const rtlSemantic = directionBehavior === 'semantic' &&
2947
3280
  options?.isRtl === true &&
2948
3281
  isHorizontalDirectionalShortcutKey(expectedKey);
@@ -3006,7 +3339,7 @@ function formatKeyboardShortcutChord(chord, options) {
3006
3339
  if (parts.length === 0) {
3007
3340
  return '';
3008
3341
  }
3009
- const keyPart = normalizeShortcutToken(parts.pop() ?? '');
3342
+ const keyPart = normalizeShortcutToken$1(parts.pop() ?? '');
3010
3343
  const modifierParts = parts.map((part) => formatShortcutPart(part.toLowerCase(), mac));
3011
3344
  const keyDisplay = formatShortcutPart(keyPart, mac);
3012
3345
  if (mac) {
@@ -3100,7 +3433,7 @@ function isMacPlatform() {
3100
3433
  }
3101
3434
  return /Mac|iPhone|iPad|iPod/i.test(navigator.userAgent);
3102
3435
  }
3103
- function normalizeShortcutToken(key) {
3436
+ function normalizeShortcutToken$1(key) {
3104
3437
  const normalized = key.trim().toLowerCase();
3105
3438
  if (normalized === 'esc') {
3106
3439
  return 'escape';
@@ -3162,7 +3495,7 @@ function normalizeShortcutEventKey(event) {
3162
3495
  return event.key.toLowerCase();
3163
3496
  }
3164
3497
  function formatShortcutPart(part, mac) {
3165
- const normalized = normalizeShortcutToken(part);
3498
+ const normalized = normalizeShortcutToken$1(part);
3166
3499
  if (mac && KEY_DISPLAY_MAC[normalized]) {
3167
3500
  return KEY_DISPLAY_MAC[normalized];
3168
3501
  }
@@ -3439,6 +3772,271 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
3439
3772
  }]
3440
3773
  }] });
3441
3774
 
3775
+ //#region ---- Dialog Action Shortcut Utilities ----
3776
+ const DEFAULT_CANCEL_DIALOG_ACTION_SHORTCUTS = ['Esc'];
3777
+ const DEFAULT_SUBMIT_DIALOG_ACTION_SHORTCUTS = ['Enter', 'ctrl+s'];
3778
+ const PRIMARY_DIALOG_ACTION_COMMANDS = new Set([
3779
+ 'submit',
3780
+ 'create',
3781
+ 'apply',
3782
+ 'save',
3783
+ 'select',
3784
+ 'entity-form-done',
3785
+ 'upload-image',
3786
+ ]);
3787
+ /**
3788
+ * Parses a shortcut string such as `Enter`, `Escape`, or `ctrl+shift+s`.
3789
+ */
3790
+ function parseDialogActionShortcut(shortcut) {
3791
+ const parts = shortcut
3792
+ .trim()
3793
+ .toLowerCase()
3794
+ .split('+')
3795
+ .map((part) => part.trim())
3796
+ .filter(Boolean);
3797
+ const key = normalizeShortcutToken(parts.pop() ?? '');
3798
+ return {
3799
+ ctrl: parts.includes('ctrl') || parts.includes('control'),
3800
+ shift: parts.includes('shift'),
3801
+ alt: parts.includes('alt') || parts.includes('option'),
3802
+ meta: parts.includes('meta') || parts.includes('cmd') || parts.includes('command'),
3803
+ key,
3804
+ };
3805
+ }
3806
+ /**
3807
+ * Returns true when the keyboard event matches the given shortcut definition.
3808
+ */
3809
+ function matchesDialogActionShortcut(event, shortcut) {
3810
+ const parsed = parseDialogActionShortcut(shortcut);
3811
+ if (parsed.ctrl !== event.ctrlKey) {
3812
+ return false;
3813
+ }
3814
+ if (parsed.shift !== event.shiftKey) {
3815
+ return false;
3816
+ }
3817
+ if (parsed.alt !== event.altKey) {
3818
+ return false;
3819
+ }
3820
+ if (parsed.meta !== event.metaKey) {
3821
+ return false;
3822
+ }
3823
+ return normalizeShortcutKey(event) === normalizeShortcutToken(parsed.key);
3824
+ }
3825
+ /**
3826
+ * Resolves footer action shortcuts: defaults when omitted, merge when extras are provided, none when `[]`.
3827
+ */
3828
+ function resolveDialogActionShortcuts(defaults, overrides) {
3829
+ if (overrides !== undefined) {
3830
+ if (overrides.length === 0) {
3831
+ return undefined;
3832
+ }
3833
+ return flattenDialogActionShortcutChords([...defaults, ...overrides]);
3834
+ }
3835
+ return flattenDialogActionShortcutChords(defaults);
3836
+ }
3837
+ /**
3838
+ * Applies built-in footer shortcuts when actions are declared without `shortcuts`
3839
+ * (e.g. workflow `show-layout-popup` raw action config).
3840
+ */
3841
+ function resolveConfiguredFooterActionShortcuts(command, explicit) {
3842
+ if (explicit !== undefined) {
3843
+ return resolveDialogActionShortcuts([], explicit);
3844
+ }
3845
+ if (command === 'cancel') {
3846
+ return resolveDialogActionShortcuts(DEFAULT_CANCEL_DIALOG_ACTION_SHORTCUTS, undefined);
3847
+ }
3848
+ if (command && PRIMARY_DIALOG_ACTION_COMMANDS.has(command)) {
3849
+ return resolveDialogActionShortcuts(DEFAULT_SUBMIT_DIALOG_ACTION_SHORTCUTS, undefined);
3850
+ }
3851
+ return undefined;
3852
+ }
3853
+ function flattenDialogActionShortcutChords(shortcuts) {
3854
+ const chords = normalizeKeyboardShortcuts(shortcuts).flatMap((shortcut) => shortcut.keys);
3855
+ const deduped = dedupeDialogActionShortcuts(chords);
3856
+ return deduped.length ? deduped : undefined;
3857
+ }
3858
+ function dedupeDialogActionShortcuts(shortcuts) {
3859
+ const seen = new Set();
3860
+ const result = [];
3861
+ for (const shortcut of shortcuts) {
3862
+ const token = normalizeShortcutToken(shortcut);
3863
+ if (!token || seen.has(token)) {
3864
+ continue;
3865
+ }
3866
+ seen.add(token);
3867
+ result.push(shortcut.trim());
3868
+ }
3869
+ return result;
3870
+ }
3871
+ function normalizeShortcutToken(key) {
3872
+ const normalized = key.trim().toLowerCase();
3873
+ if (normalized === 'esc') {
3874
+ return 'escape';
3875
+ }
3876
+ return normalized;
3877
+ }
3878
+ /**
3879
+ * Whether a dialog footer shortcut may fire while focus is inside an editable field.
3880
+ */
3881
+ function isDialogShortcutAllowedInEditableField(shortcut) {
3882
+ const parsed = parseDialogActionShortcut(shortcut);
3883
+ const isPlainEnter = parsed.key === 'enter' && !parsed.ctrl && !parsed.shift && !parsed.alt && !parsed.meta;
3884
+ return !isPlainEnter;
3885
+ }
3886
+ /**
3887
+ * Normalizes dialog footer chord strings for {@link AXPKeyboardShortcutRegistry} (`Esc` → `escape`).
3888
+ */
3889
+ function normalizeDialogActionShortcutChord(shortcut) {
3890
+ const parts = shortcut
3891
+ .trim()
3892
+ .split('+')
3893
+ .map((part) => part.trim())
3894
+ .filter(Boolean);
3895
+ if (parts.length === 0) {
3896
+ return shortcut.trim();
3897
+ }
3898
+ const key = normalizeShortcutToken(parts.pop() ?? '');
3899
+ const modifiers = parts.map((part) => part.toLowerCase());
3900
+ return modifiers.length ? `${modifiers.join('+')}+${key}` : key;
3901
+ }
3902
+ /**
3903
+ * Whether a shortcut should fire given the current focus target.
3904
+ * Enter without modifiers is suppressed in multiline / rich-text fields.
3905
+ */
3906
+ function shouldTriggerDialogActionShortcut(event, shortcut) {
3907
+ const parsed = parseDialogActionShortcut(shortcut);
3908
+ const isPlainEnter = parsed.key === 'enter' && !parsed.ctrl && !parsed.shift && !parsed.alt && !parsed.meta;
3909
+ if (!isPlainEnter) {
3910
+ return true;
3911
+ }
3912
+ return !isKeyboardTargetMultilineEditable(event.target);
3913
+ }
3914
+ function normalizeShortcutKey(event) {
3915
+ if (event.key === 'Enter') {
3916
+ return 'enter';
3917
+ }
3918
+ if (event.key === 'Escape') {
3919
+ return 'escape';
3920
+ }
3921
+ if (event.key === ' ') {
3922
+ return 'space';
3923
+ }
3924
+ if (event.key.length === 1) {
3925
+ return event.key.toLowerCase();
3926
+ }
3927
+ const codeMatch = event.code.match(/^Key([A-Z])$/);
3928
+ if (codeMatch) {
3929
+ return codeMatch[1].toLowerCase();
3930
+ }
3931
+ const digitMatch = event.code.match(/^Digit([0-9])$/);
3932
+ if (digitMatch) {
3933
+ return digitMatch[1];
3934
+ }
3935
+ return event.key.toLowerCase();
3936
+ }
3937
+ function isKeyboardTargetMultilineEditable(target) {
3938
+ if (!(target instanceof HTMLElement)) {
3939
+ return false;
3940
+ }
3941
+ if (target.isContentEditable) {
3942
+ return true;
3943
+ }
3944
+ const textarea = target.closest('textarea');
3945
+ if (textarea && !textarea.readOnly && !textarea.disabled) {
3946
+ return true;
3947
+ }
3948
+ const richText = target.closest('[contenteditable="true"]');
3949
+ return richText instanceof HTMLElement;
3950
+ }
3951
+ //#endregion
3952
+
3953
+ //#region ---- Popup Footer Keyboard Shortcuts ----
3954
+ /**
3955
+ * Registers popup footer shortcuts at modal priority so they win over page bindings and stop bubbling.
3956
+ */
3957
+ function registerPopupFooterKeyboardShortcuts(options) {
3958
+ const group = '@general:keyboard-shortcuts.groups.dialog';
3959
+ const scope = options.scope ?? group;
3960
+ const shortcuts = [];
3961
+ for (const action of options.actions) {
3962
+ if (action.hidden?.()) {
3963
+ continue;
3964
+ }
3965
+ const chords = action.shortcuts !== undefined
3966
+ ? resolveConfiguredFooterActionShortcuts(action.command, action.shortcuts)
3967
+ : resolveConfiguredFooterActionShortcuts(action.command, undefined);
3968
+ if (!chords?.length) {
3969
+ continue;
3970
+ }
3971
+ for (const shortcut of chords) {
3972
+ shortcuts.push({
3973
+ keys: [normalizeDialogActionShortcutChord(shortcut)],
3974
+ title: action.title,
3975
+ group,
3976
+ allowInEditableFields: isDialogShortcutAllowedInEditableField(shortcut),
3977
+ when: () => {
3978
+ if (options.when && !options.when()) {
3979
+ return false;
3980
+ }
3981
+ if (action.hidden?.()) {
3982
+ return false;
3983
+ }
3984
+ if (action.disabled?.()) {
3985
+ return false;
3986
+ }
3987
+ return true;
3988
+ },
3989
+ handler: () => {
3990
+ void action.handler();
3991
+ },
3992
+ });
3993
+ }
3994
+ }
3995
+ options.registry.register({
3996
+ owner: options.owner,
3997
+ elementRef: options.elementRef,
3998
+ id: options.id,
3999
+ priority: AXPKeyboardShortcutPriority.Modal,
4000
+ scope,
4001
+ when: options.when,
4002
+ shortcuts,
4003
+ });
4004
+ }
4005
+ /**
4006
+ * Binds footer shortcuts for AXPopupService-hosted components. Call from the popup constructor.
4007
+ */
4008
+ function setupPopupFooterKeyboardShortcuts(getActions, config) {
4009
+ const destroyRef = inject(DestroyRef);
4010
+ const elementRef = inject(ElementRef);
4011
+ const registry = inject(AXPKeyboardShortcutRegistry);
4012
+ const id = config?.id ?? 'popup-footer';
4013
+ effect(() => {
4014
+ getActions();
4015
+ config?.when?.();
4016
+ untracked(() => {
4017
+ registerPopupFooterKeyboardShortcuts({
4018
+ registry,
4019
+ owner: destroyRef,
4020
+ elementRef,
4021
+ id,
4022
+ scope: config?.scope,
4023
+ when: config?.when,
4024
+ actions: getActions(),
4025
+ });
4026
+ });
4027
+ });
4028
+ }
4029
+ //#endregion
4030
+
4031
+ /** Global overlay flag + task count ({@link AXPLayoutThemeService}). */
4032
+ const OVERLAY_LAYOUT_TRACE_NS = 'OVERLAY-LAYOUT';
4033
+ /** Root shell loading dialog sync ({@link AXPRootLayoutComponent}). */
4034
+ const OVERLAY_ROOT_LAYOUT_TRACE_NS = 'OVERLAY-ROOT-LAYOUT';
4035
+ /** Details view page load and overlay release orchestration. */
4036
+ const OVERLAY_DETAILS_VIEW_TRACE_NS = 'OVERLAY-DETAILS-VIEW';
4037
+ /** Widget tree mount / settle polling ({@link AXPWidgetContainerComponent}). */
4038
+ const OVERLAY_WIDGET_SETTLE_TRACE_NS = 'OVERLAY-WIDGET-SETTLE';
4039
+
3442
4040
  //#region ---- Imports ----
3443
4041
  //#endregion
3444
4042
 
@@ -3932,7 +4530,7 @@ class AXPIdleSchedulerService {
3932
4530
  const timeoutMs = options?.timeoutMs ?? DEFAULT_IDLE_TIMEOUT_MS;
3933
4531
  const minIdleMs = options?.minIdleMs ?? DEFAULT_MIN_IDLE_MS;
3934
4532
  if (this.pausedState() || typeof document !== 'undefined' && document.visibilityState === 'hidden') {
3935
- return this.delay(timeoutMs);
4533
+ return delay(timeoutMs);
3936
4534
  }
3937
4535
  return new Promise((resolve) => {
3938
4536
  let settled = false;
@@ -3992,9 +4590,6 @@ class AXPIdleSchedulerService {
3992
4590
  }
3993
4591
  }
3994
4592
  }
3995
- delay(ms) {
3996
- return new Promise((resolve) => setTimeout(resolve, ms));
3997
- }
3998
4593
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIdleSchedulerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
3999
4594
  static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPIdleSchedulerService, providedIn: 'root' }); }
4000
4595
  }
@@ -5821,5 +6416,5 @@ function generateKebabCase(title) {
5821
6416
  * Generated bundle index. Do not edit.
5822
6417
  */
5823
6418
 
5824
- export { AXHighlightService, AXPActivityLogProvider, AXPActivityLogService, AXPAppStartUpProvider, AXPAppStartUpService, AXPBroadcastEventService, AXPCatalogScopeDefinitionProviderService, AXPCatalogScopeDefinitionsDataSourceDefinition, AXPColorPaletteProvider, AXPColorPaletteService, AXPColumnWidthService, AXPComponentLogoConfig, AXPComponentSlot, AXPComponentSlotDirective, AXPComponentSlotModule, AXPComponentSlotRegistryService, AXPContentCheckerDirective, AXPContextChangeEvent, AXPContextDefinitionProviderService, AXPContextEvalFactory, AXPContextStore, AXPCountdownPipe, AXPDataGenerator, AXPDataSourceDefinitionProviderService, AXPDblClickDirective, AXPDefaultColorPalettesProvider, AXPDeviceService, AXPDeviceType, AXPDistributedEventListenerService, AXPElementDataDirective, AXPExpressionEvaluatorScopeProviderContext, AXPExpressionEvaluatorScopeProviderService, AXPExpressionEvaluatorService, AXPFeatureDefinitionProviderContext, AXPGridLayoutDirective, AXPHookService, AXPIconLogoConfig, AXPIdleSchedulerService, AXPImageUrlLogoConfig, AXPKeyboardShortcutPriority, AXPKeyboardShortcutRegistry, AXPModuleManifestModule, AXPModuleManifestRegistry, AXPModuleManifestsDataSourceDefinition, AXPScreenSize, AXPSystemActions, AXPTagProvider, AXPTagService, AXP_ACTIVITY_LOG_PROVIDER, AXP_CATALOG_SCOPE_DEFINITION_PROVIDER, AXP_COLOR_PALETTE_PROVIDER, AXP_COLUMN_WIDTH_PROVIDER, AXP_CONTEXT_DEFINITION_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_FEATURE_DEFINITION_PROVIDER, AXP_MODULE_MANIFEST_PROVIDER, AXP_SESSION_SERVICE, AXP_TAG_PROVIDER, AX_OVERLAY_CONTAINER_SELECTOR, AX_OVERLAY_PANE_SELECTOR, applyContextEvalPipes, applyFilterArray, applyPagination, applyQueryArray, applySortArray, applySystemActionDefault, buildLocaleTextMapValue, captureFormContextBaseline, chordToKbdItemKeys, cleanDeep, coerceUnknownToBoolean, coerceUnknownToDate, coerceUnknownToFiniteNumber, coerceUnknownToTrimmedString, compareMultiLanguageStrings, containsHtmlMarkup, contextEvalWithPipes, createProviderWithInjectionContext, defaultColumnWidthProvider, extractNestedFieldsWildcard, extractTextFromHtml, extractValue, findOverlayContainerAncestor, formatKeyboardShortcutChord, formatKeyboardShortcutChords, generateKebabCase, getActionButton, getChangedPaths, getDetailedChanges, getEnumValues, getNestedVisibleOverlayPanes, getPrimaryKeyboardShortcutChord, getSmart, getSystemActions, getTopVisibleOverlayContainer, getVisibleAnchoredOverlayPanes, getVisibleOverlayContainers, hasForegroundOverlayLayer, isFormContextDirty, isFormValueEqual, isHorizontalDirectionalShortcutKey, isKeyboardTargetInsideEditableField, isLocaleStringMap, isMacPlatform, isSelectionValueEqual, isVisibleOverlayElement, matchesKeyboardShortcutChord, mirrorHorizontalDirectionalKey, normalizeContextEvalPipes, normalizeExpressionTemplate, normalizeKeyboardShortcut, normalizeKeyboardShortcuts, objectKeyValueTransforms, parseKeyboardShortcutChord, provideLazyProvider, resolveActionLook, resolveDisplayShortcutChord, resolveEffectiveDirectionBehavior, resolveSemanticDirectionalKey, searchInMultiLanguageString, setSmart, shouldDeferEscapeToOpenOverlay, shouldUseLocaleMapShape, sortByMultiLanguageString, unwrapValueProperty };
6419
+ export { AXHighlightService, AXPActivityLogProvider, AXPActivityLogService, AXPAppStartUpProvider, AXPAppStartUpService, AXPBroadcastEventService, AXPCatalogScopeDefinitionProviderService, AXPCatalogScopeDefinitionsDataSourceDefinition, AXPColorPaletteProvider, AXPColorPaletteService, AXPColumnWidthService, AXPComponentLogoConfig, AXPComponentSlot, AXPComponentSlotDirective, AXPComponentSlotModule, AXPComponentSlotRegistryService, AXPContentCheckerDirective, AXPContextChangeEvent, AXPContextDefinitionProviderService, AXPContextEvalFactory, AXPContextStore, AXPCountdownPipe, AXPDataGenerator, AXPDataSourceDefinitionProviderService, AXPDblClickDirective, AXPDebugService, AXPDefaultColorPalettesProvider, AXPDeviceService, AXPDeviceType, AXPDistributedEventListenerService, AXPElementDataDirective, AXPExpressionEvaluatorScopeProviderContext, AXPExpressionEvaluatorScopeProviderService, AXPExpressionEvaluatorService, AXPFeatureDefinitionProviderContext, AXPGridLayoutDirective, AXPHookService, AXPIconLogoConfig, AXPIdleSchedulerService, AXPImageUrlLogoConfig, AXPKeyboardShortcutPriority, AXPKeyboardShortcutRegistry, AXPModuleManifestModule, AXPModuleManifestRegistry, AXPModuleManifestsDataSourceDefinition, AXPScreenSize, AXPSystemActions, AXPTagProvider, AXPTagService, AXP_ACTIVITY_LOG_PROVIDER, AXP_CATALOG_SCOPE_DEFINITION_PROVIDER, AXP_COLOR_PALETTE_PROVIDER, AXP_COLUMN_WIDTH_PROVIDER, AXP_CONTEXT_DEFINITION_PROVIDER, AXP_DATASOURCE_DEFINITION_PROVIDER, AXP_DISTRIBUTED_EVENT_LISTENER_PROVIDER, AXP_EXPRESSION_EVALUATOR_SCOPE_PROVIDER, AXP_FEATURE_DEFINITION_PROVIDER, AXP_MODULE_MANIFEST_PROVIDER, AXP_SESSION_SERVICE, AXP_TAG_PROVIDER, AX_OVERLAY_CONTAINER_SELECTOR, AX_OVERLAY_PANE_SELECTOR, DEFAULT_CANCEL_DIALOG_ACTION_SHORTCUTS, DEFAULT_SUBMIT_DIALOG_ACTION_SHORTCUTS, FORM_DIRTY_TRACE_NS, OVERLAY_DETAILS_VIEW_TRACE_NS, OVERLAY_LAYOUT_TRACE_NS, OVERLAY_ROOT_LAYOUT_TRACE_NS, OVERLAY_WIDGET_SETTLE_TRACE_NS, applyContextEvalPipes, applyFilterArray, applyPagination, applyQueryArray, applySortArray, applySystemActionDefault, buildLocaleTextMapValue, captureFormContextBaseline, chordToKbdItemKeys, cleanDeep, coerceUnknownToBoolean, coerceUnknownToDate, coerceUnknownToFiniteNumber, coerceUnknownToTrimmedString, compareMultiLanguageStrings, containsHtmlMarkup, contextEvalWithPipes, createProviderWithInjectionContext, defaultColumnWidthProvider, extractNestedFieldsWildcard, extractTextFromHtml, extractValue, findOverlayContainerAncestor, formatKeyboardShortcutChord, formatKeyboardShortcutChords, generateKebabCase, getActionButton, getChangedPaths, getDetailedChanges, getEnumValues, getNestedVisibleOverlayPanes, getPrimaryKeyboardShortcutChord, getSmart, getSystemActions, getTopVisibleOverlayContainer, getVisibleAnchoredOverlayPanes, getVisibleOverlayContainers, hasForegroundOverlayLayer, isDialogShortcutAllowedInEditableField, isFormContextDirty, isFormValueEqual, isHorizontalDirectionalShortcutKey, isKeyboardTargetInsideEditableField, isLocaleStringMap, isMacPlatform, isSelectionValueEqual, isVisibleOverlayElement, matchesDialogActionShortcut, matchesKeyboardShortcutChord, mirrorHorizontalDirectionalKey, normalizeContextEvalPipes, normalizeDialogActionShortcutChord, normalizeExpressionTemplate, normalizeKeyboardShortcut, normalizeKeyboardShortcuts, objectKeyValueTransforms, parseDialogActionShortcut, parseKeyboardShortcutChord, provideLazyProvider, registerPopupFooterKeyboardShortcuts, resolveActionLook, resolveConfiguredFooterActionShortcuts, resolveDialogActionShortcuts, resolveDisplayShortcutChord, resolveEffectiveDirectionBehavior, resolveSemanticDirectionalKey, searchInMultiLanguageString, setSmart, setupPopupFooterKeyboardShortcuts, shouldDeferEscapeToOpenOverlay, shouldRestoreSavedMultiLanguageShape, shouldTriggerDialogActionShortcut, shouldUseLocaleMapShape, sortByMultiLanguageString, summarizeFormContextDirtyDiff, unwrapValueProperty };
5825
6420
  //# sourceMappingURL=acorex-platform-core.mjs.map