@acorex/platform 21.0.0-next.57 → 21.0.0-next.63

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.
@@ -21,12 +21,12 @@ import * as i4 from '@acorex/components/skeleton';
21
21
  import { AXSkeletonModule } from '@acorex/components/skeleton';
22
22
  import * as i2 from '@acorex/components/popover';
23
23
  import { AXPopoverModule } from '@acorex/components/popover';
24
+ import { AXFormatService } from '@acorex/core/format';
24
25
  import * as i5 from '@angular/common';
25
26
  import { CommonModule, AsyncPipe } from '@angular/common';
26
27
  import { AXPThemeLayoutBlockComponent, AXPPreloadFiltersComponent, AXPStateMessageComponent, AXPColumnItemListComponent, AXPDataSelectorService, AXPPageComponentRegistryService } from '@acorex/platform/layout/components';
27
28
  import { AXPPageLayoutBaseComponent, AXPPageLayoutComponent, AXPPageComponentInstanceRegistryService } from '@acorex/platform/layout/views';
28
29
  import { AXDataSource } from '@acorex/cdk/common';
29
- import { AXFormatService } from '@acorex/core/format';
30
30
  import * as i1$3 from '@acorex/platform/workflow';
31
31
  import { AXPWorkflowService, ofType, createWorkFlowEvent, AXPWorkflowAction, AXPWorkflowEventService, AXPWorkflowModule } from '@acorex/platform/workflow';
32
32
  import { AXPLayoutThemeService } from '@acorex/platform/themes/shared';
@@ -2845,17 +2845,119 @@ var viewEntityDetails_command = /*#__PURE__*/Object.freeze({
2845
2845
  AXPViewEntityDetailsCommand: AXPViewEntityDetailsCommand
2846
2846
  });
2847
2847
 
2848
+ //#region ---- Template resolution ----
2849
+ /**
2850
+ * Normalizes lookup/search display templates for row-based formatting.
2851
+ * Converts `context.eval('path')` expressions to `{{ path }}` and single braces to mustache form.
2852
+ */
2853
+ function normalizeLookupDisplayTemplate(template) {
2854
+ const withContextEval = template.replace(/\{\{\s*context\.eval\(['"]([^'"]+)['"]\)\s*\}\}/g, '{{ $1 }}');
2855
+ if (withContextEval.includes('{{')) {
2856
+ return withContextEval;
2857
+ }
2858
+ return withContextEval.replace(/\{/g, '{{').replace(/\}/g, '}}');
2859
+ }
2860
+ /**
2861
+ * Resolves the display template for a lookup item.
2862
+ * Priority: explicit `displayFormat` → entity `formats.lookup` (template) → entity `formats.searchResult.title`.
2863
+ * Returns undefined when `textField` is set or no template applies (use {@link resolveLookupDisplayField} instead).
2864
+ */
2865
+ function resolveLookupDisplayTemplate(entity, options) {
2866
+ const explicit = options.displayFormat?.trim();
2867
+ if (explicit) {
2868
+ return normalizeLookupDisplayTemplate(explicit);
2869
+ }
2870
+ if (options.textField?.trim()) {
2871
+ return undefined;
2872
+ }
2873
+ const lookupFormat = entity?.formats?.lookup?.trim();
2874
+ if (lookupFormat && (lookupFormat.includes('{{') || lookupFormat.includes('{'))) {
2875
+ return normalizeLookupDisplayTemplate(lookupFormat);
2876
+ }
2877
+ const searchTitle = entity?.formats?.searchResult?.title?.trim();
2878
+ if (searchTitle) {
2879
+ return normalizeLookupDisplayTemplate(searchTitle);
2880
+ }
2881
+ return undefined;
2882
+ }
2883
+ /**
2884
+ * Resolves the property path used for lookup display when no template applies.
2885
+ * Priority: explicit `textField` → entity `formats.lookup` (simple path) → common property names.
2886
+ */
2887
+ function resolveLookupDisplayField(entity, options) {
2888
+ if (options.textField?.trim()) {
2889
+ return options.textField.trim();
2890
+ }
2891
+ const lookupFormat = entity?.formats?.lookup?.trim();
2892
+ if (lookupFormat && !lookupFormat.includes('{') && !lookupFormat.includes('{{')) {
2893
+ return lookupFormat;
2894
+ }
2895
+ const defaults = ['title', 'name', 'code', 'description'];
2896
+ const found = defaults.find((name) => entity?.properties?.some((p) => p.name === name));
2897
+ return found ?? 'title';
2898
+ }
2899
+ /**
2900
+ * Formats a lookup row for display using template and/or field resolution.
2901
+ */
2902
+ function formatLookupItemDisplay(item, entity, options, formatService, resolveMultiLanguage) {
2903
+ if (item == null) {
2904
+ return '';
2905
+ }
2906
+ if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
2907
+ return String(item);
2908
+ }
2909
+ if (typeof item !== 'object') {
2910
+ return '';
2911
+ }
2912
+ if (options.isMultiLanguage?.(item) && resolveMultiLanguage) {
2913
+ return resolveMultiLanguage(item);
2914
+ }
2915
+ const template = resolveLookupDisplayTemplate(entity, options);
2916
+ if (template) {
2917
+ const formatted = formatService.format(template, 'string', item);
2918
+ if (formatted) {
2919
+ const text = String(formatted);
2920
+ if (!isUnresolvedLookupDisplayTemplate(text)) {
2921
+ return text;
2922
+ }
2923
+ }
2924
+ }
2925
+ const field = resolveLookupDisplayField(entity, options);
2926
+ const raw = get(item, field);
2927
+ if (raw == null) {
2928
+ return '';
2929
+ }
2930
+ if (typeof raw === 'string' || typeof raw === 'number' || typeof raw === 'boolean') {
2931
+ return String(raw);
2932
+ }
2933
+ if (typeof raw === 'object' && !Array.isArray(raw)) {
2934
+ if (resolveMultiLanguage) {
2935
+ return resolveMultiLanguage(raw);
2936
+ }
2937
+ return raw;
2938
+ }
2939
+ return String(raw);
2940
+ }
2941
+ /** True when a formatted label still contains unresolved template markers. */
2942
+ function isUnresolvedLookupDisplayTemplate(value) {
2943
+ return /\{\{/.test(value) || /context\.eval\s*\(/.test(value);
2944
+ }
2945
+ //#endregion
2946
+
2848
2947
  class AXPEntityDetailPopoverComponent {
2849
2948
  constructor() {
2850
2949
  //#region ---- Dependencies ----
2851
2950
  this.commandService = inject(AXPCommandService);
2852
2951
  this.queryService = inject(AXPQueryService);
2952
+ this.formatService = inject(AXFormatService);
2953
+ this.translation = inject(AXTranslationService);
2853
2954
  //#endregion
2854
2955
  //#region ---- Inputs ----
2855
2956
  this.entity = input.required(...(ngDevMode ? [{ debugName: "entity" }] : /* istanbul ignore next */ []));
2856
2957
  this.entityId = input.required(...(ngDevMode ? [{ debugName: "entityId" }] : /* istanbul ignore next */ []));
2857
2958
  this.textField = input('title', ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
2858
2959
  this.valueField = input('id', ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
2960
+ this.displayTitle = input('', ...(ngDevMode ? [{ debugName: "displayTitle" }] : /* istanbul ignore next */ []));
2859
2961
  this.item = input(...(ngDevMode ? [undefined, { debugName: "item" }] : /* istanbul ignore next */ []));
2860
2962
  this.breadcrumb = input(null, ...(ngDevMode ? [{ debugName: "breadcrumb" }] : /* istanbul ignore next */ []));
2861
2963
  //#endregion
@@ -2868,6 +2970,29 @@ class AXPEntityDetailPopoverComponent {
2868
2970
  this.isDetailPopoverOpen = signal(false, ...(ngDevMode ? [{ debugName: "isDetailPopoverOpen" }] : /* istanbul ignore next */ []));
2869
2971
  /** Placeholder rows for the loading skeleton (matches typical property count). */
2870
2972
  this.loadingSkeletonRows = [1, 2, 3, 4, 5];
2973
+ this.headerTitle = computed(() => {
2974
+ const details = this.entityDetails();
2975
+ const entityDefinition = details?.entityDefinition;
2976
+ const data = details?.entityData;
2977
+ if (data && entityDefinition) {
2978
+ const fromDetails = this.resolveLookupDisplayLabel(data, entityDefinition);
2979
+ if (fromDetails) {
2980
+ return fromDetails;
2981
+ }
2982
+ }
2983
+ const preset = this.displayTitle()?.trim();
2984
+ if (preset && !isUnresolvedLookupDisplayTemplate(preset)) {
2985
+ return preset;
2986
+ }
2987
+ const fallbackItem = this.item();
2988
+ if (fallbackItem) {
2989
+ const fromItem = this.resolveLookupDisplayLabel(fallbackItem, entityDefinition);
2990
+ if (fromItem) {
2991
+ return fromItem;
2992
+ }
2993
+ }
2994
+ return preset ?? '';
2995
+ }, ...(ngDevMode ? [{ debugName: "headerTitle" }] : /* istanbul ignore next */ []));
2871
2996
  /**
2872
2997
  * Stable list of property widgets for the template. Must be a signal (computed), not a method:
2873
2998
  * calling a method from the template rebuilds nodes every CD cycle and can make the widget renderer loop.
@@ -2952,6 +3077,11 @@ class AXPEntityDetailPopoverComponent {
2952
3077
  }
2953
3078
  //#endregion
2954
3079
  //#region ---- Helper Methods ----
3080
+ resolveLookupDisplayLabel(item, entityDefinition) {
3081
+ const label = formatLookupItemDisplay(item, entityDefinition, { textField: this.textField() }, this.formatService, (value) => this.translation.resolve(value));
3082
+ const resolved = typeof label === 'string' ? label : this.translation.resolve(label);
3083
+ return resolved && !isUnresolvedLookupDisplayTemplate(resolved) ? resolved : '';
3084
+ }
2955
3085
  /**
2956
3086
  * Returns true if a value is meaningful for display (non-empty/non-null).
2957
3087
  */
@@ -3129,12 +3259,12 @@ class AXPEntityDetailPopoverComponent {
3129
3259
  return prop.name;
3130
3260
  }
3131
3261
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityDetailPopoverComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3132
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPEntityDetailPopoverComponent, isStandalone: true, selector: "axp-entity-detail-popover", inputs: { entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: true, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: true, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, breadcrumb: { classPropertyName: "breadcrumb", publicName: "breadcrumb", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "detailPopover", first: true, predicate: ["detailPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ax-popover [openOn]=\"'manual'\" #detailPopover (openChange)=\"onDetailPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-border ax-rounded-lg ax-shadow-lg ax-p-4 ax-w-[min(600px,calc(100vw-2rem))]\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold ax-text-on-lightest-surface\">\n {{ entityDetails()?.entityData?.[textField()] ?? item()?.[textField()] | translate | async }}\n </h3>\n @if (breadcrumb()) {\n <div class=\"ax-text-xs ax-text-neutral-500 ax-mt-1\">{{ breadcrumb() }}</div>\n }\n </div>\n @if (isLoadingDetails()) {\n <div class=\"ax-space-y-2 ax-mb-4\">\n @for (row of loadingSkeletonRows; track row) {\n <div class=\"ax-grid ax-grid-cols-[minmax(7rem,35%)_1fr] ax-gap-x-4 ax-items-start\">\n <ax-skeleton [animated]=\"true\" class=\"ax-h-4 ax-w-2/3 ax-rounded\"></ax-skeleton>\n @if (row === 2) {\n <ax-skeleton [animated]=\"true\" class=\"ax-h-16 ax-w-full ax-rounded\"></ax-skeleton>\n } @else {\n <ax-skeleton [animated]=\"true\" class=\"ax-h-4 ax-w-full ax-rounded\"></ax-skeleton>\n }\n </div>\n }\n </div>\n <div class=\"ax-flex ax-justify-end\">\n <ax-skeleton [animated]=\"true\" class=\"ax-h-9 ax-w-28 ax-rounded\"></ax-skeleton>\n </div>\n } @else if (entityDetails()) {\n <div class=\"ax-space-y-3 ax-mb-4\">\n <!-- Important Entity Data -->\n @if (entityDetails()?.entityData) {\n <axp-widgets-container [context]=\"entityDetails()?.entityData\">\n <div class=\"ax-space-y-2\">\n @for (item of entityPropertiesWithWidgets(); track item.name) {\n <div class=\"ax-grid ax-grid-cols-[minmax(7rem,35%)_1fr] ax-gap-x-4 ax-gap-y-1 ax-items-start\">\n <span class=\"ax-text-sm ax-font-medium ax-text-neutral-600 ax-shrink-0\">{{ item.title | translate | async }}:</span>\n <div class=\"ax-min-w-0 ax-text-sm\">\n <ng-container axp-widget-renderer [node]=\"item.node\" [mode]=\"'view'\"></ng-container>\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n }\n </div>\n <div class=\"ax-flex ax-gap-2 ax-justify-end ax-sm\">\n <ax-button [color]=\"'primary'\" [look]=\"'solid'\" [text]=\"'@general:actions.open-details.title' | translate | async\"\n (click)=\"navigateToDetails()\">\n </ax-button>\n </div>\n }\n </div>\n</ax-popover>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.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: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i3.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i4.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3262
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPEntityDetailPopoverComponent, isStandalone: true, selector: "axp-entity-detail-popover", inputs: { entity: { classPropertyName: "entity", publicName: "entity", isSignal: true, isRequired: true, transformFunction: null }, entityId: { classPropertyName: "entityId", publicName: "entityId", isSignal: true, isRequired: true, transformFunction: null }, textField: { classPropertyName: "textField", publicName: "textField", isSignal: true, isRequired: false, transformFunction: null }, valueField: { classPropertyName: "valueField", publicName: "valueField", isSignal: true, isRequired: false, transformFunction: null }, displayTitle: { classPropertyName: "displayTitle", publicName: "displayTitle", isSignal: true, isRequired: false, transformFunction: null }, item: { classPropertyName: "item", publicName: "item", isSignal: true, isRequired: false, transformFunction: null }, breadcrumb: { classPropertyName: "breadcrumb", publicName: "breadcrumb", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "detailPopover", first: true, predicate: ["detailPopover"], descendants: true, isSignal: true }], ngImport: i0, template: "<ax-popover [openOn]=\"'manual'\" #detailPopover (openChange)=\"onDetailPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-p-4 ax-w-[min(600px,calc(100vw-2rem))]\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold ax-text-on-lightest-surface\">\n {{ headerTitle() }}\n </h3>\n @if (breadcrumb()) {\n <div class=\"ax-text-xs ax-text-neutral-500 ax-mt-1\">{{ breadcrumb() }}</div>\n }\n </div>\n @if (isLoadingDetails()) {\n <div class=\"ax-space-y-2 ax-mb-4\">\n @for (row of loadingSkeletonRows; track row) {\n <div class=\"ax-grid ax-grid-cols-[minmax(7rem,35%)_1fr] ax-gap-x-4 ax-items-start\">\n <ax-skeleton [animated]=\"true\" class=\"ax-h-4 ax-w-2/3 ax-rounded\"></ax-skeleton>\n @if (row === 2) {\n <ax-skeleton [animated]=\"true\" class=\"ax-h-16 ax-w-full ax-rounded\"></ax-skeleton>\n } @else {\n <ax-skeleton [animated]=\"true\" class=\"ax-h-4 ax-w-full ax-rounded\"></ax-skeleton>\n }\n </div>\n }\n </div>\n <div class=\"ax-flex ax-justify-end\">\n <ax-skeleton [animated]=\"true\" class=\"ax-h-9 ax-w-28 ax-rounded\"></ax-skeleton>\n </div>\n } @else if (entityDetails()) {\n <div class=\"ax-space-y-3 ax-mb-4\">\n <!-- Important Entity Data -->\n @if (entityDetails()?.entityData) {\n <axp-widgets-container [context]=\"entityDetails()?.entityData\">\n <div class=\"ax-space-y-2\">\n @for (item of entityPropertiesWithWidgets(); track item.name) {\n <div class=\"ax-grid ax-grid-cols-[minmax(7rem,35%)_1fr] ax-gap-x-4 ax-gap-y-1 ax-items-start\">\n <span class=\"ax-text-sm ax-font-medium ax-text-neutral-600 ax-shrink-0\">{{ item.title | translate | async\n }}:</span>\n <div class=\"ax-min-w-0 ax-text-sm\">\n <ng-container axp-widget-renderer [node]=\"item.node\" [mode]=\"'view'\"></ng-container>\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n }\n </div>\n <div class=\"ax-flex ax-gap-2 ax-justify-end ax-sm\">\n <ax-button [color]=\"'primary'\" [look]=\"'solid'\" [text]=\"'@general:actions.open-details.title' | translate | async\"\n (click)=\"navigateToDetails()\">\n </ax-button>\n </div>\n }\n </div>\n</ax-popover>", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: AXButtonModule }, { kind: "component", type: i1.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: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }, { kind: "ngmodule", type: AXPWidgetCoreModule }, { kind: "component", type: i3.AXPWidgetContainerComponent, selector: "axp-widgets-container", inputs: ["context", "functions"], outputs: ["onContextChanged"] }, { kind: "directive", type: i3.AXPWidgetRendererDirective, selector: "[axp-widget-renderer]", inputs: ["parentNode", "index", "mode", "node"], outputs: ["onOptionsChanged", "onValueChanged", "onLoad"], exportAs: ["widgetRenderer"] }, { kind: "ngmodule", type: AXTranslationModule }, { kind: "ngmodule", type: AXSkeletonModule }, { kind: "component", type: i4.AXSkeletonComponent, selector: "ax-skeleton", inputs: ["animated"] }, { kind: "pipe", type: i5.AsyncPipe, name: "async" }, { kind: "pipe", type: i6.AXTranslatorPipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
3133
3263
  }
3134
3264
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPEntityDetailPopoverComponent, decorators: [{
3135
3265
  type: Component,
3136
- args: [{ selector: 'axp-entity-detail-popover', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, AXButtonModule, AXPopoverModule, AXPWidgetCoreModule, AXTranslationModule, AXSkeletonModule], template: "<ax-popover [openOn]=\"'manual'\" #detailPopover (openChange)=\"onDetailPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-border ax-rounded-lg ax-shadow-lg ax-p-4 ax-w-[min(600px,calc(100vw-2rem))]\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold ax-text-on-lightest-surface\">\n {{ entityDetails()?.entityData?.[textField()] ?? item()?.[textField()] | translate | async }}\n </h3>\n @if (breadcrumb()) {\n <div class=\"ax-text-xs ax-text-neutral-500 ax-mt-1\">{{ breadcrumb() }}</div>\n }\n </div>\n @if (isLoadingDetails()) {\n <div class=\"ax-space-y-2 ax-mb-4\">\n @for (row of loadingSkeletonRows; track row) {\n <div class=\"ax-grid ax-grid-cols-[minmax(7rem,35%)_1fr] ax-gap-x-4 ax-items-start\">\n <ax-skeleton [animated]=\"true\" class=\"ax-h-4 ax-w-2/3 ax-rounded\"></ax-skeleton>\n @if (row === 2) {\n <ax-skeleton [animated]=\"true\" class=\"ax-h-16 ax-w-full ax-rounded\"></ax-skeleton>\n } @else {\n <ax-skeleton [animated]=\"true\" class=\"ax-h-4 ax-w-full ax-rounded\"></ax-skeleton>\n }\n </div>\n }\n </div>\n <div class=\"ax-flex ax-justify-end\">\n <ax-skeleton [animated]=\"true\" class=\"ax-h-9 ax-w-28 ax-rounded\"></ax-skeleton>\n </div>\n } @else if (entityDetails()) {\n <div class=\"ax-space-y-3 ax-mb-4\">\n <!-- Important Entity Data -->\n @if (entityDetails()?.entityData) {\n <axp-widgets-container [context]=\"entityDetails()?.entityData\">\n <div class=\"ax-space-y-2\">\n @for (item of entityPropertiesWithWidgets(); track item.name) {\n <div class=\"ax-grid ax-grid-cols-[minmax(7rem,35%)_1fr] ax-gap-x-4 ax-gap-y-1 ax-items-start\">\n <span class=\"ax-text-sm ax-font-medium ax-text-neutral-600 ax-shrink-0\">{{ item.title | translate | async }}:</span>\n <div class=\"ax-min-w-0 ax-text-sm\">\n <ng-container axp-widget-renderer [node]=\"item.node\" [mode]=\"'view'\"></ng-container>\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n }\n </div>\n <div class=\"ax-flex ax-gap-2 ax-justify-end ax-sm\">\n <ax-button [color]=\"'primary'\" [look]=\"'solid'\" [text]=\"'@general:actions.open-details.title' | translate | async\"\n (click)=\"navigateToDetails()\">\n </ax-button>\n </div>\n }\n </div>\n</ax-popover>" }]
3137
- }], propDecorators: { entity: [{ type: i0.Input, args: [{ isSignal: true, alias: "entity", required: true }] }], entityId: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityId", required: true }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], breadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "breadcrumb", required: false }] }], detailPopover: [{ type: i0.ViewChild, args: ['detailPopover', { isSignal: true }] }] } });
3266
+ args: [{ selector: 'axp-entity-detail-popover', changeDetection: ChangeDetectionStrategy.OnPush, imports: [CommonModule, AXButtonModule, AXPopoverModule, AXPWidgetCoreModule, AXTranslationModule, AXSkeletonModule], template: "<ax-popover [openOn]=\"'manual'\" #detailPopover (openChange)=\"onDetailPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-p-4 ax-w-[min(600px,calc(100vw-2rem))]\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold ax-text-on-lightest-surface\">\n {{ headerTitle() }}\n </h3>\n @if (breadcrumb()) {\n <div class=\"ax-text-xs ax-text-neutral-500 ax-mt-1\">{{ breadcrumb() }}</div>\n }\n </div>\n @if (isLoadingDetails()) {\n <div class=\"ax-space-y-2 ax-mb-4\">\n @for (row of loadingSkeletonRows; track row) {\n <div class=\"ax-grid ax-grid-cols-[minmax(7rem,35%)_1fr] ax-gap-x-4 ax-items-start\">\n <ax-skeleton [animated]=\"true\" class=\"ax-h-4 ax-w-2/3 ax-rounded\"></ax-skeleton>\n @if (row === 2) {\n <ax-skeleton [animated]=\"true\" class=\"ax-h-16 ax-w-full ax-rounded\"></ax-skeleton>\n } @else {\n <ax-skeleton [animated]=\"true\" class=\"ax-h-4 ax-w-full ax-rounded\"></ax-skeleton>\n }\n </div>\n }\n </div>\n <div class=\"ax-flex ax-justify-end\">\n <ax-skeleton [animated]=\"true\" class=\"ax-h-9 ax-w-28 ax-rounded\"></ax-skeleton>\n </div>\n } @else if (entityDetails()) {\n <div class=\"ax-space-y-3 ax-mb-4\">\n <!-- Important Entity Data -->\n @if (entityDetails()?.entityData) {\n <axp-widgets-container [context]=\"entityDetails()?.entityData\">\n <div class=\"ax-space-y-2\">\n @for (item of entityPropertiesWithWidgets(); track item.name) {\n <div class=\"ax-grid ax-grid-cols-[minmax(7rem,35%)_1fr] ax-gap-x-4 ax-gap-y-1 ax-items-start\">\n <span class=\"ax-text-sm ax-font-medium ax-text-neutral-600 ax-shrink-0\">{{ item.title | translate | async\n }}:</span>\n <div class=\"ax-min-w-0 ax-text-sm\">\n <ng-container axp-widget-renderer [node]=\"item.node\" [mode]=\"'view'\"></ng-container>\n </div>\n </div>\n }\n </div>\n </axp-widgets-container>\n }\n </div>\n <div class=\"ax-flex ax-gap-2 ax-justify-end ax-sm\">\n <ax-button [color]=\"'primary'\" [look]=\"'solid'\" [text]=\"'@general:actions.open-details.title' | translate | async\"\n (click)=\"navigateToDetails()\">\n </ax-button>\n </div>\n }\n </div>\n</ax-popover>" }]
3267
+ }], propDecorators: { entity: [{ type: i0.Input, args: [{ isSignal: true, alias: "entity", required: true }] }], entityId: [{ type: i0.Input, args: [{ isSignal: true, alias: "entityId", required: true }] }], textField: [{ type: i0.Input, args: [{ isSignal: true, alias: "textField", required: false }] }], valueField: [{ type: i0.Input, args: [{ isSignal: true, alias: "valueField", required: false }] }], displayTitle: [{ type: i0.Input, args: [{ isSignal: true, alias: "displayTitle", required: false }] }], item: [{ type: i0.Input, args: [{ isSignal: true, alias: "item", required: false }] }], breadcrumb: [{ type: i0.Input, args: [{ isSignal: true, alias: "breadcrumb", required: false }] }], detailPopover: [{ type: i0.ViewChild, args: ['detailPopover', { isSignal: true }] }] } });
3138
3268
 
3139
3269
  class AXPEntityDetailPopoverService {
3140
3270
  constructor() {
@@ -3164,6 +3294,7 @@ class AXPEntityDetailPopoverService {
3164
3294
  this.activePopoverRef.setInput('entityId', options.id);
3165
3295
  this.activePopoverRef.setInput('textField', options.textField || 'title');
3166
3296
  this.activePopoverRef.setInput('valueField', options.valueField || 'id');
3297
+ this.activePopoverRef.setInput('displayTitle', options.displayTitle ?? '');
3167
3298
  this.activePopoverRef.setInput('breadcrumb', options.breadcrumb || null);
3168
3299
  this.activePopoverRef.setInput('item', options.item);
3169
3300
  // Attach to application
@@ -12547,22 +12678,18 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
12547
12678
  constructor() {
12548
12679
  super(...arguments);
12549
12680
  this.formatService = inject(AXFormatService);
12681
+ this.translation = inject(AXTranslationService);
12550
12682
  this.entityResolver = inject(AXPEntityDefinitionRegistryService);
12551
12683
  this.entity = computed(() => this.options()['entity'], ...(ngDevMode ? [{ debugName: "entity" }] : /* istanbul ignore next */ []));
12552
12684
  this.multiple = computed(() => this.options()['multiple'], ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
12553
12685
  this.valueField = computed(() => this.options()['valueField'] ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
12554
12686
  this.textField = computed(() => this.options()['textField'] ?? 'title', ...(ngDevMode ? [{ debugName: "textField" }] : /* istanbul ignore next */ []));
12555
12687
  this.badgeClass = computed(() => this.options()['badgeClass'] ?? 'ax-accent1', ...(ngDevMode ? [{ debugName: "badgeClass" }] : /* istanbul ignore next */ []));
12556
- this.displayFormat = computed(() => {
12557
- const template = this.options()['displayFormat'];
12558
- return template ? template.replace(/\{/g, '{{').replace(/\}/g, '}}') : undefined;
12559
- }, ...(ngDevMode ? [{ debugName: "displayFormat" }] : /* istanbul ignore next */ []));
12560
- this.displayField = computed(() => {
12561
- return (this.textField() ??
12562
- this.entityDef()?.formats.lookup ??
12563
- this.entityDef()?.properties.find((c) => c.name != 'id')?.name ??
12564
- 'title');
12565
- }, ...(ngDevMode ? [{ debugName: "displayField" }] : /* istanbul ignore next */ []));
12688
+ this.displayFormat = computed(() => resolveLookupDisplayTemplate(this.entityDef(), {
12689
+ displayFormat: this.options()['displayFormat'],
12690
+ textField: this.textField(),
12691
+ }), ...(ngDevMode ? [{ debugName: "displayFormat" }] : /* istanbul ignore next */ []));
12692
+ this.displayField = computed(() => resolveLookupDisplayField(this.entityDef(), { textField: this.textField() }), ...(ngDevMode ? [{ debugName: "displayField" }] : /* istanbul ignore next */ []));
12566
12693
  this.loading = signal(false, ...(ngDevMode ? [{ debugName: "loading" }] : /* istanbul ignore next */ []));
12567
12694
  this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : /* istanbul ignore next */ []));
12568
12695
  this.displayItems = signal([], ...(ngDevMode ? [{ debugName: "displayItems" }] : /* istanbul ignore next */ []));
@@ -12605,27 +12732,11 @@ class AXPLookupWidgetViewComponent extends AXPValueWidgetComponent {
12605
12732
  };
12606
12733
  }
12607
12734
  getDisplayRaw(item) {
12608
- if (!item) {
12609
- return '';
12610
- }
12611
- const template = this.displayFormat();
12612
- if (template) {
12613
- const formatted = this.formatService.format(template, 'string', item);
12614
- if (formatted) {
12615
- return formatted;
12616
- }
12617
- }
12618
- const raw = get(item, this.displayField());
12619
- if (raw == null) {
12620
- return '';
12621
- }
12622
- if (typeof raw === 'string' || typeof raw === 'number' || typeof raw === 'boolean') {
12623
- return String(raw);
12624
- }
12625
- if (typeof raw === 'object' && !Array.isArray(raw)) {
12626
- return raw;
12627
- }
12628
- return String(raw);
12735
+ const text = formatLookupItemDisplay(item, this.entityDef(), {
12736
+ displayFormat: this.options()['displayFormat'],
12737
+ textField: this.textField(),
12738
+ }, this.formatService, (value) => this.translation.resolve(value));
12739
+ return text;
12629
12740
  }
12630
12741
  get __class() {
12631
12742
  const cls = {};
@@ -13520,27 +13631,10 @@ class AXPLookupWidgetTagboxComponent extends LookupWidgetLookBase {
13520
13631
  //#endregion
13521
13632
  //#region ---- Utility Methods ----
13522
13633
  getDisplayRaw(item) {
13523
- if (!item) {
13524
- return '';
13525
- }
13526
- const template = this.displayFormatValue();
13527
- if (template) {
13528
- const formatted = this.formatService.format(template, 'string', item);
13529
- if (formatted) {
13530
- return formatted;
13531
- }
13532
- }
13533
- const raw = get(item, this.displayFieldValue());
13534
- if (raw == null) {
13535
- return '';
13536
- }
13537
- if (typeof raw === 'string' || typeof raw === 'number' || typeof raw === 'boolean') {
13538
- return String(raw);
13539
- }
13540
- if (typeof raw === 'object' && !Array.isArray(raw)) {
13541
- return raw;
13542
- }
13543
- return String(raw);
13634
+ return formatLookupItemDisplay(item, this.entityDef()(), {
13635
+ displayFormat: this.displayFormatValue(),
13636
+ textField: this.displayFieldValue(),
13637
+ }, this.formatService, (value) => this.translateService.resolve(value));
13544
13638
  }
13545
13639
  /**
13546
13640
  * Get current input value from tag box
@@ -13800,23 +13894,13 @@ class AXPLookupWidgetEditComponent extends AXPValueWidgetComponent {
13800
13894
  this.filterMode = computed(() => this.options()['filterMode'], ...(ngDevMode ? [{ debugName: "filterMode" }] : /* istanbul ignore next */ []));
13801
13895
  this.multiple = computed(() => (this.options()['multiple'] ?? false), ...(ngDevMode ? [{ debugName: "multiple" }] : /* istanbul ignore next */ []));
13802
13896
  this.look = computed(() => this.options()['look'] ?? 'lookup', ...(ngDevMode ? [{ debugName: "look" }] : /* istanbul ignore next */ []));
13803
- this.defaultTextField = computed(() => {
13804
- const list = ['title', 'name', 'code', 'description'];
13805
- const textField = list.find((c) => this.entityDef()?.properties.find((p) => p.name == c)) ?? 'title';
13806
- return textField;
13807
- }, ...(ngDevMode ? [{ debugName: "defaultTextField" }] : /* istanbul ignore next */ []));
13808
- this.displayField = computed(() => {
13809
- if (this.textField()) {
13810
- return this.textField();
13811
- }
13812
- return this.defaultTextField();
13813
- }, ...(ngDevMode ? [{ debugName: "displayField" }] : /* istanbul ignore next */ []));
13897
+ this.displayField = computed(() => resolveLookupDisplayField(this.entityDef(), { textField: this.textField() }), ...(ngDevMode ? [{ debugName: "displayField" }] : /* istanbul ignore next */ []));
13814
13898
  this.allowCreate = computed(() => this.options()['allowCreate'] ?? 'none', ...(ngDevMode ? [{ debugName: "allowCreate" }] : /* istanbul ignore next */ []));
13815
13899
  this.valueField = computed(() => this.entityDef()?.properties.find((c) => c.name == 'id')?.name ?? 'id', ...(ngDevMode ? [{ debugName: "valueField" }] : /* istanbul ignore next */ []));
13816
- this.displayFormat = computed(() => {
13817
- const template = this.options()['displayFormat'];
13818
- return template ? template.replace(/\{/g, '{{').replace(/\}/g, '}}') : undefined;
13819
- }, ...(ngDevMode ? [{ debugName: "displayFormat" }] : /* istanbul ignore next */ []));
13900
+ this.displayFormat = computed(() => resolveLookupDisplayTemplate(this.entityDef(), {
13901
+ displayFormat: this.options()['displayFormat'],
13902
+ textField: this.textField(),
13903
+ }), ...(ngDevMode ? [{ debugName: "displayFormat" }] : /* istanbul ignore next */ []));
13820
13904
  this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : /* istanbul ignore next */ []));
13821
13905
  this.selectedItems = signal([], ...(ngDevMode ? [{ debugName: "selectedItems" }] : /* istanbul ignore next */ []));
13822
13906
  this.initialItems = signal(false, ...(ngDevMode ? [{ debugName: "initialItems" }] : /* istanbul ignore next */ []));
@@ -14212,6 +14296,7 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
14212
14296
  this.translation = inject(AXTranslationService);
14213
14297
  this.formatService = inject(AXFormatService);
14214
14298
  this.entityService = inject(AXPEntityService);
14299
+ this.entityResolver = inject(AXPEntityDefinitionRegistryService);
14215
14300
  this.queryExecutor = inject(AXPQueryExecutor);
14216
14301
  //#endregion
14217
14302
  //#region ---- View Children ----
@@ -14222,15 +14307,16 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
14222
14307
  //#region ---- Properties ----
14223
14308
  this.host = inject(ElementRef);
14224
14309
  this.valueField = this.options['valueField'] ?? 'id';
14225
- this.textField = this.options['textField'] ?? 'title';
14226
14310
  this.entity = this.options['entity'] ?? '';
14227
14311
  this.columnName = this.options['columnName'] ?? 'title';
14228
14312
  this.maxVisible = this.options['maxVisible'] ?? 2;
14229
- this.displayFormat = computed(() => {
14230
- const template = this.options['displayFormat'];
14231
- return template ? template.replace(/\{/g, '{{').replace(/\}/g, '}}') : undefined;
14232
- }, ...(ngDevMode ? [{ debugName: "displayFormat" }] : /* istanbul ignore next */ []));
14233
- this.displayField = computed(() => this.textField ?? 'title', ...(ngDevMode ? [{ debugName: "displayField" }] : /* istanbul ignore next */ []));
14313
+ this.lookupDisplayOptions = computed(() => ({
14314
+ displayFormat: this.options['displayFormat'],
14315
+ textField: this.options['textField'],
14316
+ isMultiLanguage: (value) => this.translation.isValidMultiLanguageObject(value),
14317
+ }), ...(ngDevMode ? [{ debugName: "lookupDisplayOptions" }] : /* istanbul ignore next */ []));
14318
+ this.displayFormat = computed(() => resolveLookupDisplayTemplate(this.entityDef(), this.lookupDisplayOptions()), ...(ngDevMode ? [{ debugName: "displayFormat" }] : /* istanbul ignore next */ []));
14319
+ this.displayField = computed(() => resolveLookupDisplayField(this.entityDef(), this.lookupDisplayOptions()), ...(ngDevMode ? [{ debugName: "displayField" }] : /* istanbul ignore next */ []));
14234
14320
  this.columnResolve = computed(() => this.options['columnResolve'], ...(ngDevMode ? [{ debugName: "columnResolve" }] : /* istanbul ignore next */ []));
14235
14321
  this.resolveStrategy = computed(() => {
14236
14322
  return this.columnResolve()?.strategy ?? 'hydrated';
@@ -14245,6 +14331,9 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
14245
14331
  this.resolveError = signal(null, ...(ngDevMode ? [{ debugName: "resolveError" }] : /* istanbul ignore next */ []));
14246
14332
  this.summaryLabel = signal('', ...(ngDevMode ? [{ debugName: "summaryLabel" }] : /* istanbul ignore next */ []));
14247
14333
  this.popoverHeader = signal('', ...(ngDevMode ? [{ debugName: "popoverHeader" }] : /* istanbul ignore next */ []));
14334
+ this.entityDef = signal(null, ...(ngDevMode ? [{ debugName: "entityDef" }] : /* istanbul ignore next */ []));
14335
+ this.hydratedDisplayItems = signal(null, ...(ngDevMode ? [{ debugName: "hydratedDisplayItems" }] : /* istanbul ignore next */ []));
14336
+ this.hydrateRequestId = 0;
14248
14337
  //#endregion
14249
14338
  //#region ---- Computed ----
14250
14339
  this.displayItems = computed(() => isNil(this.rawValue)
@@ -14252,7 +14341,13 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
14252
14341
  : castArray(this.rawValue)
14253
14342
  .map((item) => this.extractItem(item))
14254
14343
  .filter((c) => c != null), ...(ngDevMode ? [{ debugName: "displayItems" }] : /* istanbul ignore next */ []));
14255
- this.allItems = computed(() => this.displayItems(), ...(ngDevMode ? [{ debugName: "allItems" }] : /* istanbul ignore next */ []));
14344
+ this.allItems = computed(() => {
14345
+ const hydrated = this.hydratedDisplayItems();
14346
+ if (hydrated != null && hydrated.length > 0) {
14347
+ return hydrated;
14348
+ }
14349
+ return this.displayItems();
14350
+ }, ...(ngDevMode ? [{ debugName: "allItems" }] : /* istanbul ignore next */ []));
14256
14351
  this.visibleItems = computed(() => {
14257
14352
  const items = this.allItems();
14258
14353
  return items.slice(0, this.maxVisible);
@@ -14309,6 +14404,8 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
14309
14404
  }
14310
14405
  this.previousLazyRowId = key;
14311
14406
  this.resetLazyState();
14407
+ this.hydratedDisplayItems.set(null);
14408
+ this.hydrateRequestId++;
14312
14409
  });
14313
14410
  effect(() => {
14314
14411
  if (!this.isHydratedStrategy()) {
@@ -14325,6 +14422,40 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
14325
14422
  : this.displayCount();
14326
14423
  void this.refreshPopoverHeader(count);
14327
14424
  });
14425
+ effect(() => {
14426
+ const key = this.entity;
14427
+ if (!key?.includes('.')) {
14428
+ this.entityDef.set(null);
14429
+ return;
14430
+ }
14431
+ const [module, name] = key.split('.');
14432
+ void this.entityResolver.resolve(module, name).then((def) => this.entityDef.set(def));
14433
+ });
14434
+ effect(() => {
14435
+ if (!this.isHydratedStrategy()) {
14436
+ this.hydratedDisplayItems.set(null);
14437
+ return;
14438
+ }
14439
+ const entityKey = this.entity;
14440
+ const raw = this.rawValue;
14441
+ if (!entityKey?.includes('.') || isNil(raw)) {
14442
+ this.hydratedDisplayItems.set(null);
14443
+ return;
14444
+ }
14445
+ // Display text is already on the row (dataPath, denormalized title, nested object, etc.) — no byKey fetch.
14446
+ if (this.hasPreresolvedDisplay()) {
14447
+ this.hydratedDisplayItems.set(null);
14448
+ return;
14449
+ }
14450
+ const values = castArray(raw).filter((value) => value != null && value !== '');
14451
+ const needsHydrate = values.length > 0 &&
14452
+ values.every((value) => typeof value !== 'object' && this.isLikelyEntityId(value));
14453
+ if (!needsHydrate) {
14454
+ this.hydratedDisplayItems.set(null);
14455
+ return;
14456
+ }
14457
+ void this.hydrateScalarIds(entityKey, values);
14458
+ });
14328
14459
  }
14329
14460
  //#endregion
14330
14461
  //#region ---- Public methods ----
@@ -14354,7 +14485,7 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
14354
14485
  this.closeMorePopover();
14355
14486
  // Prefer the row's FK / stored value (columnName) first. List columns often use options.dataPath so
14356
14487
  // rawValue (and thus `item`) is only display text (e.g. manager.person.fullName) while managerId holds the real id.
14357
- const columnData = this.rowData?.[this.columnName];
14488
+ const columnData = get(this.rowData, this.columnName);
14358
14489
  let id;
14359
14490
  if (Array.isArray(columnData)) {
14360
14491
  const cell = columnData[index];
@@ -14375,11 +14506,33 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
14375
14506
  if (isNil(id) || id === '') {
14376
14507
  return;
14377
14508
  }
14509
+ const headerItem = this.allItems()[index] ?? item;
14510
+ let resolvedTitle = '';
14511
+ if (headerItem != null && this.hasDisplayTextOnLookupValue(headerItem)) {
14512
+ resolvedTitle =
14513
+ typeof headerItem === 'object'
14514
+ ? this.renderLookupLabel(headerItem)
14515
+ : this.formatDisplayValue(headerItem);
14516
+ }
14517
+ else if (!this.isMultiValueLookup()) {
14518
+ const rowText = this.getRowDisplayTextFromTextField();
14519
+ if (!isNil(rowText) && rowText !== '') {
14520
+ resolvedTitle = this.formatDisplayValue(rowText);
14521
+ }
14522
+ }
14523
+ if (!resolvedTitle) {
14524
+ const displayTitle = formatLookupItemDisplay(headerItem, this.entityDef(), this.lookupDisplayOptions(), this.formatService, (value) => this.translation.resolve(value));
14525
+ resolvedTitle = typeof displayTitle === 'string' ? displayTitle : this.translation.resolve(displayTitle);
14526
+ if (isUnresolvedLookupDisplayTemplate(resolvedTitle)) {
14527
+ resolvedTitle = '';
14528
+ }
14529
+ }
14378
14530
  await this.entityDetailPopoverService.show(this.host, {
14379
14531
  entity: this.entity,
14380
14532
  id,
14381
- textField: this.textField,
14533
+ textField: this.options['textField'] ?? this.displayField(),
14382
14534
  valueField: this.valueField,
14535
+ displayTitle: resolvedTitle,
14383
14536
  item,
14384
14537
  });
14385
14538
  }
@@ -14409,21 +14562,45 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
14409
14562
  this.handleResolvedItemClick(index);
14410
14563
  }
14411
14564
  }
14565
+ /**
14566
+ * True when the cell can render without fetching row data via byKey.
14567
+ * Uses textField / expose targets on the row — not merely whether column dataPath differs from columnName.
14568
+ */
14569
+ hasPreresolvedDisplay() {
14570
+ if (this.isMultiValueLookup()) {
14571
+ const values = castArray(this.rawValue).filter((value) => value != null && value !== '');
14572
+ return values.length > 0 && values.every((value) => this.hasDisplayTextOnLookupValue(value));
14573
+ }
14574
+ const rowText = this.getRowDisplayTextFromTextField();
14575
+ if (!isNil(rowText) &&
14576
+ rowText !== '' &&
14577
+ (typeof rowText !== 'string' || !this.isLikelyEntityId(rowText))) {
14578
+ return true;
14579
+ }
14580
+ const raw = this.rawValue;
14581
+ if (isNil(raw)) {
14582
+ return false;
14583
+ }
14584
+ const values = castArray(raw).filter((value) => value != null && value !== '');
14585
+ return values.length > 0 && values.every((value) => this.hasDisplayTextOnLookupValue(value));
14586
+ }
14412
14587
  getDisplayRaw(item) {
14413
- if (isNil(item)) {
14414
- return '';
14588
+ if (item != null && typeof item === 'object' && this.translation.isValidMultiLanguageObject(item)) {
14589
+ return this.translation.resolve(item);
14415
14590
  }
14416
- const resolved = this.resolveDisplayValue(item);
14417
- const template = this.displayFormat();
14418
- if (template) {
14419
- const displayField = this.displayField();
14420
- const templateData = typeof item === 'object' && !Array.isArray(item)
14421
- ? { ...item, [displayField]: resolved }
14422
- : { [displayField]: resolved, value: resolved };
14423
- const formatted = this.formatService.format(template, 'string', templateData);
14424
- return formatted ?? resolved ?? '';
14591
+ if (!this.isMultiValueLookup()) {
14592
+ const rowText = this.getRowDisplayTextFromTextField();
14593
+ if (!isNil(rowText) && rowText !== '') {
14594
+ return this.formatDisplayValue(rowText);
14595
+ }
14596
+ }
14597
+ if (item != null && this.hasDisplayTextOnLookupValue(item)) {
14598
+ if (typeof item === 'object') {
14599
+ return this.renderLookupLabel(item);
14600
+ }
14601
+ return this.formatDisplayValue(item);
14425
14602
  }
14426
- return resolved ?? '';
14603
+ return this.renderLookupLabel(item);
14427
14604
  }
14428
14605
  //#endregion
14429
14606
  //#region ---- Private methods ----
@@ -14594,28 +14771,154 @@ class AXPLookupWidgetColumnComponent extends AXPColumnWidgetComponent {
14594
14771
  }
14595
14772
  return {
14596
14773
  [this.valueField]: item,
14597
- [this.textField]: item,
14774
+ [this.displayField()]: item,
14598
14775
  };
14599
14776
  }
14600
- resolveDisplayValue(item) {
14601
- if (isNil(item)) {
14602
- return '';
14777
+ async hydrateScalarIds(entityKey, ids) {
14778
+ const requestId = ++this.hydrateRequestId;
14779
+ try {
14780
+ const accessor = this.entityService.withEntity(entityKey).data();
14781
+ const items = await Promise.all(ids.map((id) => accessor.byKey(id)));
14782
+ if (requestId !== this.hydrateRequestId) {
14783
+ return;
14784
+ }
14785
+ const resolved = items.filter((item) => item != null);
14786
+ this.hydratedDisplayItems.set(resolved.length > 0 ? resolved : null);
14603
14787
  }
14604
- if (typeof item === 'string' || typeof item === 'number' || typeof item === 'boolean') {
14605
- return String(item);
14788
+ catch {
14789
+ if (requestId === this.hydrateRequestId) {
14790
+ this.hydratedDisplayItems.set(null);
14791
+ }
14606
14792
  }
14607
- if (typeof item !== 'object') {
14608
- return '';
14793
+ }
14794
+ isMultiValueLookup() {
14795
+ return Array.isArray(this.rawValue) && this.rawValue.length > 0;
14796
+ }
14797
+ /** Row display text resolved via widget textField and expose targets (not column dataPath alone). */
14798
+ getRowDisplayTextFromTextField() {
14799
+ const textField = resolveLookupDisplayField(this.entityDef(), this.lookupDisplayOptions());
14800
+ const exposeTargets = this.getExposeTargets();
14801
+ for (const entry of exposeTargets) {
14802
+ if (entry.source === this.valueField || entry.source === 'id') {
14803
+ continue;
14804
+ }
14805
+ if (entry.source === textField || entry.target.endsWith(`.${textField}`)) {
14806
+ const value = get(this.rowData, entry.target);
14807
+ if (!isNil(value) && value !== '') {
14808
+ return value;
14809
+ }
14810
+ }
14609
14811
  }
14610
- const rawDisplayValue = get(item, this.displayField());
14611
- if (!isNil(rawDisplayValue)) {
14612
- return this.resolveDisplayValue(rawDisplayValue);
14812
+ for (const entry of exposeTargets) {
14813
+ if (entry.source === 'title') {
14814
+ const value = get(this.rowData, entry.target);
14815
+ if (!isNil(value) && value !== '') {
14816
+ return value;
14817
+ }
14818
+ }
14613
14819
  }
14614
- if (this.translation.isValidMultiLanguageObject(item)) {
14615
- return this.translation.resolve(item);
14820
+ if (this.path && this.path !== this.columnName) {
14821
+ const atPath = get(this.rowData, this.path);
14822
+ if (typeof atPath === 'string' && atPath !== '' && !this.isLikelyEntityId(atPath)) {
14823
+ return atPath;
14824
+ }
14825
+ if (atPath != null && typeof atPath === 'object') {
14826
+ const nested = get(atPath, textField);
14827
+ if (!isNil(nested) && nested !== '') {
14828
+ return nested;
14829
+ }
14830
+ }
14831
+ const combined = get(this.rowData, `${this.path}.${textField}`);
14832
+ if (!isNil(combined) && combined !== '') {
14833
+ return combined;
14834
+ }
14835
+ }
14836
+ if (this.columnName.endsWith('Id')) {
14837
+ const parentKey = this.columnName.slice(0, -2);
14838
+ const nestedObject = get(this.rowData, parentKey);
14839
+ if (nestedObject != null && typeof nestedObject === 'object') {
14840
+ const nested = get(nestedObject, textField);
14841
+ if (!isNil(nested) && nested !== '') {
14842
+ return nested;
14843
+ }
14844
+ }
14845
+ const direct = get(this.rowData, `${parentKey}.${textField}`);
14846
+ if (!isNil(direct) && direct !== '') {
14847
+ return direct;
14848
+ }
14849
+ }
14850
+ if (this.columnName.includes('.')) {
14851
+ const parts = this.columnName.split('.');
14852
+ const leaf = parts[parts.length - 1];
14853
+ if (leaf === 'id' || leaf.endsWith('Id')) {
14854
+ const parent = parts.slice(0, -1).join('.');
14855
+ const direct = get(this.rowData, `${parent}.${textField}`);
14856
+ if (!isNil(direct) && direct !== '') {
14857
+ return direct;
14858
+ }
14859
+ }
14860
+ }
14861
+ return undefined;
14862
+ }
14863
+ getExposeTargets() {
14864
+ const expose = this.options['expose'];
14865
+ if (!Array.isArray(expose)) {
14866
+ return [];
14867
+ }
14868
+ return expose.filter((entry) => entry != null &&
14869
+ typeof entry === 'object' &&
14870
+ typeof entry.source === 'string' &&
14871
+ typeof entry.target === 'string');
14872
+ }
14873
+ hasDisplayTextOnLookupValue(value) {
14874
+ if (isNil(value) || value === '') {
14875
+ return false;
14876
+ }
14877
+ if (typeof value === 'string') {
14878
+ return !this.isLikelyEntityId(value);
14879
+ }
14880
+ if (typeof value === 'number' || typeof value === 'boolean') {
14881
+ return true;
14882
+ }
14883
+ if (typeof value !== 'object') {
14884
+ return false;
14885
+ }
14886
+ if (this.translation.isValidMultiLanguageObject(value)) {
14887
+ return true;
14888
+ }
14889
+ const textField = resolveLookupDisplayField(this.entityDef(), this.lookupDisplayOptions());
14890
+ const text = get(value, textField);
14891
+ if (!isNil(text) && text !== '' && !this.isLikelyEntityId(text)) {
14892
+ return true;
14893
+ }
14894
+ return ['title', 'name', 'code', 'description'].some((field) => {
14895
+ const candidate = get(value, field);
14896
+ return !isNil(candidate) && candidate !== '' && !this.isLikelyEntityId(candidate);
14897
+ });
14898
+ }
14899
+ renderLookupLabel(value) {
14900
+ const label = formatLookupItemDisplay(value, this.entityDef(), this.lookupDisplayOptions(), this.formatService, (item) => this.translation.resolve(item));
14901
+ return typeof label === 'string' ? label : this.translation.resolve(label);
14902
+ }
14903
+ formatDisplayValue(value) {
14904
+ if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
14905
+ return String(value);
14906
+ }
14907
+ if (value != null && typeof value === 'object' && this.translation.isValidMultiLanguageObject(value)) {
14908
+ return this.translation.resolve(value);
14616
14909
  }
14617
14910
  return '';
14618
14911
  }
14912
+ /** True when a scalar cell value is a stored entity key (uuid/numeric), not pre-resolved display text. */
14913
+ isLikelyEntityId(value) {
14914
+ if (typeof value === 'number') {
14915
+ return true;
14916
+ }
14917
+ if (typeof value !== 'string') {
14918
+ return false;
14919
+ }
14920
+ return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value) || /^\d+$/.test(value);
14921
+ }
14619
14922
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.9", ngImport: i0, type: AXPLookupWidgetColumnComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
14620
14923
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.9", type: AXPLookupWidgetColumnComponent, isStandalone: true, selector: "ng-component", inputs: { rawValue: "rawValue", rowData: "rowData" }, viewQueries: [{ propertyName: "moreButton", first: true, predicate: ["moreButton"], descendants: true, isSignal: true }, { propertyName: "lazyTrigger", first: true, predicate: ["lazyTrigger"], descendants: true, isSignal: true }, { propertyName: "morePopover", first: true, predicate: ["morePopover"], descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "@if (isHydratedStrategy()) {\n<div class=\"ax-relative ax-flex ax-min-w-0 ax-items-center ax-gap-1\">\n @for (item of visibleItems(); track $index) {\n @let label = getDisplayRaw(item);\n <span\n [class.ax-cursor-pointer]=\"!options['disableDetailPopover']\"\n [class.hover:ax-text-primary]=\"!options['disableDetailPopover']\"\n [class.hover:ax-underline]=\"!options['disableDetailPopover']\"\n (click)=\"handleItemClick($index)\"\n >\n {{ label }}\n </span>\n @if ($index < visibleItems().length - 1) {\n <span class=\"ax-text-muted\">\u2022</span>\n }\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n @if (hasMoreItems()) {\n <span\n class=\"ax-absolute ax-end-0 ax-flex ax-h-full ax-cursor-pointer ax-items-center ax-px-1 hover:ax-primary-lighter\"\n (click)=\"showMoreItems(); $event.stopPropagation()\"\n #moreButton\n >\n <i class=\"fa-light fa-ellipsis-vertical\"></i>\n </span>\n }\n</div>\n} @else {\n<div class=\"ax-flex ax-min-w-0 ax-items-center ax-gap-1\">\n @if (displayCount() > 0) {\n <span\n class=\"ax-cursor-pointer ax-text-primary hover:ax-underline\"\n (click)=\"openLazyPopover(); $event.stopPropagation()\"\n #lazyTrigger\n >\n {{ summaryLabel() }}\n </span>\n } @else {\n <span class=\"ax-text-muted\">---</span>\n }\n</div>\n}\n\n<ax-popover [openOn]=\"'manual'\" #morePopover (openChange)=\"onPopoverOpenChange($event)\">\n <div class=\"ax-lightest-surface ax-min-w-[280px] ax-rounded-lg ax-border ax-p-4 ax-shadow-lg\">\n <div class=\"ax-mb-4 ax-border-b ax-pb-2\">\n <h3 class=\"ax-text-base ax-font-semibold\">{{ popoverHeader() }}</h3>\n </div>\n\n @if (!isHydratedStrategy() && resolveStatus() === 'loading') {\n <div class=\"ax-flex ax-min-h-[120px] ax-items-center ax-justify-center\">\n <ax-loading></ax-loading>\n </div>\n } @else if (!isHydratedStrategy() && resolveStatus() === 'error') {\n <div class=\"ax-text-danger ax-text-sm\">{{ resolveError() }}</div>\n } @else {\n <div class=\"ax-flex ax-max-h-64 ax-flex-col ax-gap-3\">\n @for (item of popoverListItems(); track $index) {\n @let label = getDisplayRaw(item);\n <span\n [class.ax-cursor-pointer]=\"!options['disableDetailPopover']\"\n [class.hover:ax-text-primary]=\"!options['disableDetailPopover']\"\n [class.hover:ax-underline]=\"!options['disableDetailPopover']\"\n (click)=\"handlePopoverItemClick($index)\"\n >\n {{ label }}\n </span>\n } @empty {\n <span class=\"ax-text-muted\">---</span>\n }\n </div>\n }\n </div>\n</ax-popover>\n", dependencies: [{ kind: "ngmodule", type: AXLoadingModule }, { kind: "component", type: i1$2.AXLoadingComponent, selector: "ax-loading", inputs: ["visible", "type", "context"], outputs: ["visibleChange"] }, { kind: "ngmodule", type: AXPopoverModule }, { kind: "component", type: i2.AXPopoverComponent, selector: "ax-popover", inputs: ["width", "disablePanelClass", "disabled", "offsetX", "offsetY", "target", "placement", "content", "openOn", "closeOn", "hasBackdrop", "openAfter", "closeAfter", "closeOnScroll", "backdropClass", "panelClass", "adaptivityEnabled"], outputs: ["onOpened", "onClosed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
14621
14924
  }
@@ -21191,6 +21494,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.9", ngImpor
21191
21494
  }]
21192
21495
  }] });
21193
21496
 
21497
+ /** Entity query filter field for {@link AXPRecordWorkflowInfo.instanceId}. */
21498
+ const AXP_RECORD_WORKFLOW_INFO_INSTANCE_ID_FIELD = 'workflowInfo.instanceId';
21499
+ /** Entity query filter field for {@link AXPRecordWorkflowInfo.correlationId}. */
21500
+ const AXP_RECORD_WORKFLOW_INFO_CORRELATION_ID_FIELD = 'workflowInfo.correlationId';
21501
+ /** Entity query filter field for {@link AXPRecordWorkflowInfo.definitionId}. */
21502
+ const AXP_RECORD_WORKFLOW_INFO_DEFINITION_ID_FIELD = 'workflowInfo.definitionId';
21503
+ /** Returns a trimmed workflow instance id from a record, if present. */
21504
+ function getRecordWorkflowInstanceId(record) {
21505
+ const id = record?.workflowInfo?.instanceId?.trim();
21506
+ return id && id.length > 0 ? id : null;
21507
+ }
21508
+ /** Returns a trimmed workflow correlation id from a record, if present. */
21509
+ function getRecordWorkflowCorrelationId(record) {
21510
+ const id = record?.workflowInfo?.correlationId?.trim();
21511
+ return id && id.length > 0 ? id : null;
21512
+ }
21513
+ /** Builds canonical workflow metadata for a domain record (engine / middleware). */
21514
+ function buildAXPRecordWorkflowInfo(params) {
21515
+ const instanceId = params.instanceId?.trim();
21516
+ if (!instanceId) {
21517
+ return {};
21518
+ }
21519
+ const definitionId = params.definitionId?.trim();
21520
+ const correlationId = params.correlationId?.trim();
21521
+ return {
21522
+ instanceId,
21523
+ ...(definitionId ? { definitionId } : { definitionId: null }),
21524
+ ...(correlationId ? { correlationId } : { correlationId: null }),
21525
+ ...(params.pinnedVersion != null ? { pinnedVersion: params.pinnedVersion } : {}),
21526
+ };
21527
+ }
21528
+
21194
21529
  /**
21195
21530
  * Registers entity CRUD commands and queries for the given entity keys.
21196
21531
  * Use in app/module providers; consumes AXPEntityService from this package.
@@ -21394,5 +21729,5 @@ var getEntityDetails_query = /*#__PURE__*/Object.freeze({
21394
21729
  * Generated bundle index. Do not edit.
21395
21730
  */
21396
21731
 
21397
- export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityCommand, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntitiesListDataSourceDefinition, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionProviderWidget, AXPEntityDefinitionProviderWidgetEditComponent, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityEventDispatcherService, AXPEntityEventsKeys, AXPEntityFormBuilderService, AXPEntityListPersistenceModeDefault, AXPEntityListTableService, AXPEntityListToolbarService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityPreloadFiltersContainerComponent, AXPEntityPreloadFiltersViewModel, AXPEntityPreloadFiltersViewModelResolver, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPGetEntityDetailsQuery, AXPLayoutOrderingConfigService, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPMultiSourceDefinitionProviderContext, AXPMultiSourceDefinitionProviderService, AXPMultiSourceFederatedSearchService, AXPMultiSourceSelectorComponent, AXPMultiSourceSelectorService, AXPMultiSourceSelectorWidget, AXPMultiSourceSelectorWidgetColumnComponent, AXPMultiSourceSelectorWidgetEditComponent, AXPMultiSourceSelectorWidgetViewComponent, AXPMultiSourceType, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPRelatedColumnEnrichmentService, AXPRelatedColumnMetadataResolver, AXPSelectorStructureWidget, AXPSelectorStructureWidgetColumnComponent, AXPSelectorStructureWidgetEditComponent, AXPSelectorStructureWidgetViewComponent, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPTruncatedBreadcrumbComponent, AXPUpdateEntityCommand, AXPViewEntityDetailsCommand, AXP_CATEGORY_TREE_ROOT_TITLE_I18N_KEY, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER, AXP_ENTITY_MODIFIER, AXP_ENTITY_STORAGE_BACKEND, AXP_ENTITY_STORAGE_MIDDLEWARE, AXP_MULTI_SOURCE_DEFINITION_PROVIDER, DEFAULT_COLUMN_ORDER, DEFAULT_PAIR_SPAN_RULES, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY, EntityBuilder, EntityDataAccessor, actionExists, applyDataSourcePagingWithoutLoad, axpCreateEntityAiToolInputDefaults, axpCreateEntityCommandDefinition, canPersistEntityListState, cloneLayoutArrays, collectEntityQuickSearchFieldPaths, collectNestedCreateHiddenProperties, collectNestedFieldPathsFromEntityColumns, collectQuickSearchPathsFromSingleEntityDefinition, columnOrderingMiddleware, columnOrderingMiddlewareProvider, columnWidthMiddleware, columnWidthMiddlewareProvider, computeEntityAggregates, createColumnOrderingMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, defaultMultiLanguageMiddleware, defaultMultiLanguageMiddlewareProvider, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, entityDetailsCreateActions, entityDetailsCreateActionsDeferredParent, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, filterSortEntityRows, findEntityListRowDataInTree, getDataSourcePageIndex, getEntityListRowId, getMasterInterfacePropertySortKey, isAXPMiddlewareAbortError, isCategoryEntity, isCategoryFilter, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider, mergeForeignKeyFieldIntoCreateActions, normalizeEntityListPersistenceMode, normalizeListPaging, provideEntity, resolveEntityPluginDetailPageOrder, restoreEntityListExpandedRows, runEntityQuery, searchResultDescriptionMiddleware, searchResultDescriptionMiddlewareProvider, shouldLoadEntityListStateFromStorage, shouldResetEntityListStateOnRouteEntry };
21732
+ export { AXMEntityCrudService, AXMEntityCrudServiceImpl, AXPCategoryTreeService, AXPCreateEntityCommand, AXPCreateEntityWorkflow, AXPDataSeederService, AXPDeleteEntityWorkflow, AXPEntitiesListDataSourceDefinition, AXPEntityApplyUpdatesAction, AXPEntityCategoryTreeSelectorComponent, AXPEntityCategoryWidget, AXPEntityCategoryWidgetColumnComponent, AXPEntityCategoryWidgetEditComponent, AXPEntityCategoryWidgetViewComponent, AXPEntityCommandTriggerViewModel, AXPEntityCreateEvent, AXPEntityCreatePopupAction, AXPEntityCreateSubmittedAction, AXPEntityCreateViewElementViewModel, AXPEntityCreateViewModelFactory, AXPEntityCreateViewSectionViewModel, AXPEntityDataProvider, AXPEntityDataProviderImpl, AXPEntityDataSelectorService, AXPEntityDefinitionProviderWidget, AXPEntityDefinitionProviderWidgetEditComponent, AXPEntityDefinitionRegistryService, AXPEntityDeletedEvent, AXPEntityDetailListViewModel, AXPEntityDetailPopoverComponent, AXPEntityDetailPopoverService, AXPEntityDetailViewModelFactory, AXPEntityDetailViewModelResolver, AXPEntityEventDispatcherService, AXPEntityEventsKeys, AXPEntityFormBuilderService, AXPEntityListPersistenceModeDefault, AXPEntityListTableService, AXPEntityListToolbarService, AXPEntityListViewColumnViewModel, AXPEntityListViewModelFactory, AXPEntityListViewModelResolver, AXPEntityListWidget, AXPEntityListWidgetViewComponent, AXPEntityMasterCreateViewModel, AXPEntityMasterListViewModel, AXPEntityMasterListViewQueryViewModel, AXPEntityMasterSingleElementViewModel, AXPEntityMasterSingleViewGroupViewModel, AXPEntityMasterSingleViewModel, AXPEntityMasterUpdateElementViewModel, AXPEntityMasterUpdateViewModel, AXPEntityMasterUpdateViewModelFactory, AXPEntityMiddleware, AXPEntityModifyConfirmedAction, AXPEntityModifyEvent, AXPEntityModifySectionPopupAction, AXPEntityModule, AXPEntityPerformDeleteAction, AXPEntityPreloadFiltersContainerComponent, AXPEntityPreloadFiltersViewModel, AXPEntityPreloadFiltersViewModelResolver, AXPEntityResolver, AXPEntityService, AXPEntityStorageService, AXPEntityUpdateViewSectionViewModel, AXPGetEntityDetailsQuery, AXPLayoutOrderingConfigService, AXPLookupWidget, AXPLookupWidgetColumnComponent, AXPLookupWidgetEditComponent, AXPLookupWidgetViewComponent, AXPMiddlewareAbortError, AXPMiddlewareEntityStorageService, AXPModifyEntitySectionWorkflow, AXPMultiSourceDefinitionProviderContext, AXPMultiSourceDefinitionProviderService, AXPMultiSourceFederatedSearchService, AXPMultiSourceSelectorComponent, AXPMultiSourceSelectorService, AXPMultiSourceSelectorWidget, AXPMultiSourceSelectorWidgetColumnComponent, AXPMultiSourceSelectorWidgetEditComponent, AXPMultiSourceSelectorWidgetViewComponent, AXPMultiSourceType, AXPOpenEntityDetailsCommand, AXPQuickEntityModifyPopupAction, AXPQuickModifyEntityWorkflow, AXPRelatedColumnEnrichmentService, AXPRelatedColumnMetadataResolver, AXPSelectorStructureWidget, AXPSelectorStructureWidgetColumnComponent, AXPSelectorStructureWidgetEditComponent, AXPSelectorStructureWidgetViewComponent, AXPShowDetailViewAction, AXPShowDetailsViewWorkflow, AXPShowListViewAction, AXPShowListViewWorkflow, AXPTruncatedBreadcrumbComponent, AXPUpdateEntityCommand, AXPViewEntityDetailsCommand, AXP_CATEGORY_TREE_ROOT_TITLE_I18N_KEY, AXP_DATA_SEEDER_TOKEN, AXP_ENTITY_ACTION_PLUGIN, AXP_ENTITY_CONFIG_TOKEN, AXP_ENTITY_DEFINITION_LOADER, AXP_ENTITY_MODIFIER, AXP_ENTITY_STORAGE_BACKEND, AXP_ENTITY_STORAGE_MIDDLEWARE, AXP_MULTI_SOURCE_DEFINITION_PROVIDER, AXP_RECORD_WORKFLOW_INFO_CORRELATION_ID_FIELD, AXP_RECORD_WORKFLOW_INFO_DEFINITION_ID_FIELD, AXP_RECORD_WORKFLOW_INFO_INSTANCE_ID_FIELD, DEFAULT_COLUMN_ORDER, DEFAULT_PAIR_SPAN_RULES, DEFAULT_PROPERTY_ORDER, DEFAULT_SECTION_ORDER, ENTITY_LIST_ROUTE_CONTEXT_SESSION_KEY, EntityBuilder, EntityDataAccessor, actionExists, applyDataSourcePagingWithoutLoad, axpCreateEntityAiToolInputDefaults, axpCreateEntityCommandDefinition, buildAXPRecordWorkflowInfo, canPersistEntityListState, cloneLayoutArrays, collectEntityQuickSearchFieldPaths, collectNestedCreateHiddenProperties, collectNestedFieldPathsFromEntityColumns, collectQuickSearchPathsFromSingleEntityDefinition, columnOrderingMiddleware, columnOrderingMiddlewareProvider, columnWidthMiddleware, columnWidthMiddlewareProvider, computeEntityAggregates, createColumnOrderingMiddlewareProvider, createLayoutOrderingMiddlewareProvider, createModifierContext, defaultMultiLanguageMiddleware, defaultMultiLanguageMiddlewareProvider, detectEntityChanges, ensureLayoutPropertyView, ensureLayoutSection, ensureListActions, entityDetailsCreateActions, entityDetailsCreateActionsDeferredParent, entityDetailsCrudActions, entityDetailsEditAction, entityDetailsNewEditAction, entityDetailsReferenceCondition, entityDetailsReferenceCreateActions, entityDetailsSimpleCondition, entityMasterBulkDeleteAction, entityMasterCreateAction, entityMasterCrudActions, entityMasterDeleteAction, entityMasterEditAction, entityMasterRecordActions, entityMasterViewAction, entityOverrideDetailsViewAction, eventDispatchMiddleware, filterSortEntityRows, findEntityListRowDataInTree, formatLookupItemDisplay, getDataSourcePageIndex, getEntityListRowId, getMasterInterfacePropertySortKey, getRecordWorkflowCorrelationId, getRecordWorkflowInstanceId, isAXPMiddlewareAbortError, isCategoryEntity, isCategoryFilter, isUnresolvedLookupDisplayTemplate, layoutOrderingMiddlewareFactory, layoutOrderingMiddlewareProvider, mergeForeignKeyFieldIntoCreateActions, normalizeEntityListPersistenceMode, normalizeListPaging, normalizeLookupDisplayTemplate, provideEntity, resolveEntityPluginDetailPageOrder, resolveLookupDisplayField, resolveLookupDisplayTemplate, restoreEntityListExpandedRows, runEntityQuery, searchResultDescriptionMiddleware, searchResultDescriptionMiddlewareProvider, shouldLoadEntityListStateFromStorage, shouldResetEntityListStateOnRouteEntry };
21398
21733
  //# sourceMappingURL=acorex-platform-layout-entity.mjs.map