@praxisui/charts 10.0.0-rc.30 → 10.0.0-rc.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-10-16T15:16:17.774Z",
3
+ "generatedAt": "2026-10-17T14:44:09.509Z",
4
4
  "packageName": "@praxisui/charts",
5
- "packageVersion": "10.0.0-rc.30",
5
+ "packageVersion": "10.0.0-rc.32",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 4,
@@ -5789,7 +5789,7 @@ class PraxisAnalyticsPresentationComponent {
5789
5789
  return Object.entries(values).reduce((message, [name, value]) => message.replaceAll(`{${name}}`, value), this.t(key, fallback));
5790
5790
  }
5791
5791
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisAnalyticsPresentationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
5792
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisAnalyticsPresentationComponent, isStandalone: true, selector: "praxis-analytics-presentation", inputs: { analytics: { classPropertyName: "analytics", publicName: "analytics", isSignal: true, isRequired: true, transformFunction: null }, projectionId: { classPropertyName: "projectionId", publicName: "projectionId", isSignal: true, isRequired: true, transformFunction: null }, availableFamilies: { classPropertyName: "availableFamilies", publicName: "availableFamilies", isSignal: true, isRequired: false, transformFunction: null }, preferredFamily: { classPropertyName: "preferredFamily", publicName: "preferredFamily", isSignal: true, isRequired: false, transformFunction: null }, queryContext: { classPropertyName: "queryContext", publicName: "queryContext", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, enableCustomization: { classPropertyName: "enableCustomization", publicName: "enableCustomization", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { presentationChange: "presentationChange", pointClick: "pointClick", pointAction: "pointAction", selectionChange: "selectionChange", drillDown: "drillDown", crossFilter: "crossFilter", queryRequest: "queryRequest", loadStateChange: "loadStateChange" }, ngImport: i0, template: "<section class=\"analytics-presentation\" [attr.aria-label]=\"projectionId()\">\n <div class=\"analytics-presentation__toolbar\" role=\"group\" [attr.aria-label]=\"t('praxis.charts.analyticsPresentation.selectorLabel', 'Analytics presentation')\">\n @if (eligibleFamilies().includes('chart')) {\n <button type=\"button\" [attr.aria-pressed]=\"activeFamily() === 'chart'\" (click)=\"selectFamily('chart')\">\n {{ t('praxis.charts.analyticsPresentation.chart', 'Chart') }}\n </button>\n }\n @if (eligibleFamilies().includes('analytic-table')) {\n <button type=\"button\" [attr.aria-pressed]=\"activeFamily() === 'analytic-table'\" (click)=\"selectFamily('analytic-table')\">\n {{ t('praxis.charts.analyticsPresentation.table', 'Table') }}\n </button>\n }\n @if (eligibleFamilies().includes('kpi')) {\n <button type=\"button\" [attr.aria-pressed]=\"activeFamily() === 'kpi'\" (click)=\"selectFamily('kpi')\">\n {{ t('praxis.charts.analyticsPresentation.kpi', 'KPI') }}\n </button>\n }\n </div>\n\n @if (diagnostic(); as message) {\n <section class=\"analytics-presentation__state analytics-presentation__state--error\" role=\"alert\">\n <strong>{{ t('praxis.charts.analyticsPresentation.unavailable', 'Presentation unavailable') }}</strong>\n <span>{{ message }}</span>\n </section>\n } @else if (activeFamily() === 'chart' && chartConfig(); as config) {\n <praxis-chart\n [config]=\"config\"\n [queryContext]=\"queryContext()\"\n [enableCustomization]=\"enableCustomization()\"\n (pointClick)=\"pointClick.emit($event)\"\n (pointAction)=\"pointAction.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (drillDown)=\"drillDown.emit($event)\"\n (crossFilter)=\"crossFilter.emit($event)\"\n (queryRequest)=\"queryRequest.emit($event)\"\n (loadStateChange)=\"loadStateChange.emit($event)\"\n />\n } @else if (activeFamily() === 'analytic-table' && tableConfig(); as config) {\n @if (isResultLoading()) {\n <section class=\"analytics-presentation__state\" role=\"status\">{{ t('praxis.charts.analyticsPresentation.loading', 'Loading analytics\u2026') }}</section>\n } @else if (isResultEmpty()) {\n <section class=\"analytics-presentation__state\" role=\"status\">{{ t('praxis.charts.analyticsPresentation.empty', 'No data available.') }}</section>\n } @else {\n <praxis-table\n [config]=\"config\"\n [data]=\"resultRows()\"\n [tableId]=\"projectionId() + '-analytic-table'\"\n (rowClick)=\"handleTableRowClick($event)\"\n />\n }\n } @else if (activeFamily() === 'kpi') {\n @if (isResultLoading()) {\n <section class=\"analytics-presentation__state\" role=\"status\">{{ t('praxis.charts.analyticsPresentation.loading', 'Loading analytics\u2026') }}</section>\n } @else if (isResultEmpty()) {\n <section class=\"analytics-presentation__state\" role=\"status\">{{ t('praxis.charts.analyticsPresentation.empty', 'No data available.') }}</section>\n } @else {\n <section class=\"analytics-presentation__kpi\" [attr.aria-label]=\"kpiTitle() || t('praxis.charts.analyticsPresentation.kpiCollection', 'Key metrics')\">\n @if (kpiTitle(); as heading) {\n <header class=\"analytics-presentation__kpi-header\">\n <h3>{{ heading }}</h3>\n @if (kpiSubtitle(); as description) {\n <p>{{ description }}</p>\n }\n </header>\n }\n <div class=\"analytics-presentation__kpi-grid\" role=\"list\">\n @for (item of kpiItems(); track item.trackId) {\n <div role=\"listitem\">\n <button\n class=\"analytics-presentation__kpi-card\"\n type=\"button\"\n [attr.aria-label]=\"kpiItemAriaLabel(item.label, item.formattedValue, item.metricLabel)\"\n (click)=\"handleKpiClick(item.row, item.label, item.value)\"\n >\n <strong>{{ item.formattedValue }}</strong>\n <span>{{ item.label }}</span>\n <small>{{ item.metricLabel }}</small>\n </button>\n </div>\n }\n </div>\n </section>\n }\n }\n</section>\n", styles: [":host{display:block;min-width:0}.analytics-presentation{display:grid;gap:12px;min-width:0}.analytics-presentation__toolbar{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:4px}.analytics-presentation__toolbar button{min-height:40px;padding:0 14px;border:1px solid var(--md-sys-color-outline-variant, #c4c7c5);border-radius:999px;background:var(--md-sys-color-surface, #fff);color:var(--md-sys-color-on-surface, #1a1c1e);font:inherit;cursor:pointer}.analytics-presentation__toolbar button[aria-pressed=true]{border-color:var(--md-sys-color-primary, #1263b4);background:var(--md-sys-color-primary-container, #d7e3ff);color:var(--md-sys-color-on-primary-container, #001b3e)}.analytics-presentation__toolbar button:focus-visible{outline:3px solid color-mix(in srgb,var(--md-sys-color-primary, #1263b4) 45%,transparent);outline-offset:2px}.analytics-presentation__state{min-height:220px;display:grid;place-content:center;gap:6px;padding:24px;border:1px solid var(--md-sys-color-outline-variant, #c4c7c5);border-radius:16px;background:var(--md-sys-color-surface-container-low, #f7f8fa);color:var(--md-sys-color-on-surface, #1a1c1e);text-align:center}.analytics-presentation__state--error{border-color:var(--md-sys-color-error, #ba1a1a);color:var(--md-sys-color-error, #ba1a1a)}.analytics-presentation__kpi{display:grid;gap:16px;min-width:0}.analytics-presentation__kpi-header{display:grid;gap:4px}.analytics-presentation__kpi-header h3,.analytics-presentation__kpi-header p{margin:0}.analytics-presentation__kpi-header h3{color:var(--md-sys-color-on-surface, #1a1c1e);font-size:1rem;font-weight:650}.analytics-presentation__kpi-header p{color:var(--md-sys-color-on-surface-variant, #44474e);font-size:.875rem}.analytics-presentation__kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,176px),1fr));gap:12px;min-width:0}.analytics-presentation__kpi-card{display:grid;gap:6px;width:100%;height:100%;min-width:0;min-height:132px;align-content:center;padding:18px;border:1px solid var(--md-sys-color-outline-variant, #c4c7c5);border-radius:16px;background:var(--md-sys-color-surface-container-low, #f7f8fa);color:var(--md-sys-color-on-surface, #1a1c1e);font:inherit;text-align:left;cursor:pointer}.analytics-presentation__kpi-card:hover{border-color:var(--md-sys-color-primary, #1263b4);background:var(--md-sys-color-surface-container, #f0f1f3)}.analytics-presentation__kpi-card:focus-visible{outline:3px solid color-mix(in srgb,var(--md-sys-color-primary, #1263b4) 45%,transparent);outline-offset:2px}.analytics-presentation__kpi-card strong{overflow-wrap:anywhere;color:var(--md-sys-color-primary, #1263b4);font-size:clamp(1.75rem,5vw,2.5rem);font-variant-numeric:tabular-nums;line-height:1}.analytics-presentation__kpi-card span,.analytics-presentation__kpi-card small{overflow-wrap:anywhere}.analytics-presentation__kpi-card span{font-weight:600}.analytics-presentation__kpi-card small{color:var(--md-sys-color-on-surface-variant, #44474e)}@media(max-width:600px){.analytics-presentation__toolbar{justify-content:stretch}.analytics-presentation__toolbar button{flex:1 1 0}}\n"], dependencies: [{ kind: "component", type: PraxisChartComponent, selector: "praxis-chart", inputs: ["config", "resourceKey", "data", "chartDocument", "filterCriteria", "queryContext", "remoteDataResolver", "enableCustomization", "availableResources", "availableFields", "availableTargets"], outputs: ["pointClick", "pointAction", "selectionChange", "drillDown", "crossFilter", "queryRequest", "loadStateChange", "chartDocumentApplied", "chartDocumentSaved", "chartDocumentPatchChange"] }, { kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "filterTeleport", "widgetId", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "authoringCapability", "dense"], outputs: ["queryContextClear", "queryContextChange", "rowClick", "widgetEvent", "resourceEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "columnResize", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange", "drawerOpen", "drawerClose", "drawerTabChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5792
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisAnalyticsPresentationComponent, isStandalone: true, selector: "praxis-analytics-presentation", inputs: { analytics: { classPropertyName: "analytics", publicName: "analytics", isSignal: true, isRequired: true, transformFunction: null }, projectionId: { classPropertyName: "projectionId", publicName: "projectionId", isSignal: true, isRequired: true, transformFunction: null }, availableFamilies: { classPropertyName: "availableFamilies", publicName: "availableFamilies", isSignal: true, isRequired: false, transformFunction: null }, preferredFamily: { classPropertyName: "preferredFamily", publicName: "preferredFamily", isSignal: true, isRequired: false, transformFunction: null }, queryContext: { classPropertyName: "queryContext", publicName: "queryContext", isSignal: true, isRequired: false, transformFunction: null }, title: { classPropertyName: "title", publicName: "title", isSignal: true, isRequired: false, transformFunction: null }, subtitle: { classPropertyName: "subtitle", publicName: "subtitle", isSignal: true, isRequired: false, transformFunction: null }, enableCustomization: { classPropertyName: "enableCustomization", publicName: "enableCustomization", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { presentationChange: "presentationChange", pointClick: "pointClick", pointAction: "pointAction", selectionChange: "selectionChange", drillDown: "drillDown", crossFilter: "crossFilter", queryRequest: "queryRequest", loadStateChange: "loadStateChange" }, ngImport: i0, template: "<section class=\"analytics-presentation\" [attr.aria-label]=\"projectionId()\">\n <div class=\"analytics-presentation__toolbar\" role=\"group\" [attr.aria-label]=\"t('praxis.charts.analyticsPresentation.selectorLabel', 'Analytics presentation')\">\n @if (eligibleFamilies().includes('chart')) {\n <button type=\"button\" [attr.aria-pressed]=\"activeFamily() === 'chart'\" (click)=\"selectFamily('chart')\">\n {{ t('praxis.charts.analyticsPresentation.chart', 'Chart') }}\n </button>\n }\n @if (eligibleFamilies().includes('analytic-table')) {\n <button type=\"button\" [attr.aria-pressed]=\"activeFamily() === 'analytic-table'\" (click)=\"selectFamily('analytic-table')\">\n {{ t('praxis.charts.analyticsPresentation.table', 'Table') }}\n </button>\n }\n @if (eligibleFamilies().includes('kpi')) {\n <button type=\"button\" [attr.aria-pressed]=\"activeFamily() === 'kpi'\" (click)=\"selectFamily('kpi')\">\n {{ t('praxis.charts.analyticsPresentation.kpi', 'KPI') }}\n </button>\n }\n </div>\n\n @if (diagnostic(); as message) {\n <section class=\"analytics-presentation__state analytics-presentation__state--error\" role=\"alert\">\n <strong>{{ t('praxis.charts.analyticsPresentation.unavailable', 'Presentation unavailable') }}</strong>\n <span>{{ message }}</span>\n </section>\n } @else if (activeFamily() === 'chart' && chartConfig(); as config) {\n <praxis-chart\n [config]=\"config\"\n [queryContext]=\"queryContext()\"\n [enableCustomization]=\"enableCustomization()\"\n (pointClick)=\"pointClick.emit($event)\"\n (pointAction)=\"pointAction.emit($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (drillDown)=\"drillDown.emit($event)\"\n (crossFilter)=\"crossFilter.emit($event)\"\n (queryRequest)=\"queryRequest.emit($event)\"\n (loadStateChange)=\"loadStateChange.emit($event)\"\n />\n } @else if (activeFamily() === 'analytic-table' && tableConfig(); as config) {\n @if (isResultLoading()) {\n <section class=\"analytics-presentation__state\" role=\"status\">{{ t('praxis.charts.analyticsPresentation.loading', 'Loading analytics\u2026') }}</section>\n } @else if (isResultEmpty()) {\n <section class=\"analytics-presentation__state\" role=\"status\">{{ t('praxis.charts.analyticsPresentation.empty', 'No data available.') }}</section>\n } @else {\n <praxis-table\n [config]=\"config\"\n [data]=\"resultRows()\"\n [tableId]=\"projectionId() + '-analytic-table'\"\n (rowClick)=\"handleTableRowClick($event)\"\n />\n }\n } @else if (activeFamily() === 'kpi') {\n @if (isResultLoading()) {\n <section class=\"analytics-presentation__state\" role=\"status\">{{ t('praxis.charts.analyticsPresentation.loading', 'Loading analytics\u2026') }}</section>\n } @else if (isResultEmpty()) {\n <section class=\"analytics-presentation__state\" role=\"status\">{{ t('praxis.charts.analyticsPresentation.empty', 'No data available.') }}</section>\n } @else {\n <section class=\"analytics-presentation__kpi\" [attr.aria-label]=\"kpiTitle() || t('praxis.charts.analyticsPresentation.kpiCollection', 'Key metrics')\">\n @if (kpiTitle(); as heading) {\n <header class=\"analytics-presentation__kpi-header\">\n <h3>{{ heading }}</h3>\n @if (kpiSubtitle(); as description) {\n <p>{{ description }}</p>\n }\n </header>\n }\n <div class=\"analytics-presentation__kpi-grid\" role=\"list\">\n @for (item of kpiItems(); track item.trackId) {\n <div role=\"listitem\">\n <button\n class=\"analytics-presentation__kpi-card\"\n type=\"button\"\n [attr.aria-label]=\"kpiItemAriaLabel(item.label, item.formattedValue, item.metricLabel)\"\n (click)=\"handleKpiClick(item.row, item.label, item.value)\"\n >\n <strong>{{ item.formattedValue }}</strong>\n <span>{{ item.label }}</span>\n <small>{{ item.metricLabel }}</small>\n </button>\n </div>\n }\n </div>\n </section>\n }\n }\n</section>\n", styles: [":host{display:block;min-width:0}.analytics-presentation{display:grid;gap:12px;min-width:0}.analytics-presentation__toolbar{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:4px}.analytics-presentation__toolbar button{min-height:40px;padding:0 14px;border:1px solid var(--md-sys-color-outline-variant, #c4c7c5);border-radius:999px;background:var(--md-sys-color-surface, #fff);color:var(--md-sys-color-on-surface, #1a1c1e);font:inherit;cursor:pointer}.analytics-presentation__toolbar button[aria-pressed=true]{border-color:var(--md-sys-color-primary, #1263b4);background:var(--md-sys-color-primary-container, #d7e3ff);color:var(--md-sys-color-on-primary-container, #001b3e)}.analytics-presentation__toolbar button:focus-visible{outline:3px solid color-mix(in srgb,var(--md-sys-color-primary, #1263b4) 45%,transparent);outline-offset:2px}.analytics-presentation__state{min-height:220px;display:grid;place-content:center;gap:6px;padding:24px;border:1px solid var(--md-sys-color-outline-variant, #c4c7c5);border-radius:16px;background:var(--md-sys-color-surface-container-low, #f7f8fa);color:var(--md-sys-color-on-surface, #1a1c1e);text-align:center}.analytics-presentation__state--error{border-color:var(--md-sys-color-error, #ba1a1a);color:var(--md-sys-color-error, #ba1a1a)}.analytics-presentation__kpi{display:grid;gap:16px;min-width:0}.analytics-presentation__kpi-header{display:grid;gap:4px}.analytics-presentation__kpi-header h3,.analytics-presentation__kpi-header p{margin:0}.analytics-presentation__kpi-header h3{color:var(--md-sys-color-on-surface, #1a1c1e);font-size:1rem;font-weight:650}.analytics-presentation__kpi-header p{color:var(--md-sys-color-on-surface-variant, #44474e);font-size:.875rem}.analytics-presentation__kpi-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,176px),1fr));gap:12px;min-width:0}.analytics-presentation__kpi-card{display:grid;gap:6px;width:100%;height:100%;min-width:0;min-height:132px;align-content:center;padding:18px;border:1px solid var(--md-sys-color-outline-variant, #c4c7c5);border-radius:16px;background:var(--md-sys-color-surface-container-low, #f7f8fa);color:var(--md-sys-color-on-surface, #1a1c1e);font:inherit;text-align:left;cursor:pointer}.analytics-presentation__kpi-card:hover{border-color:var(--md-sys-color-primary, #1263b4);background:var(--md-sys-color-surface-container, #f0f1f3)}.analytics-presentation__kpi-card:focus-visible{outline:3px solid color-mix(in srgb,var(--md-sys-color-primary, #1263b4) 45%,transparent);outline-offset:2px}.analytics-presentation__kpi-card strong{overflow-wrap:anywhere;color:var(--md-sys-color-primary, #1263b4);font-size:clamp(1.75rem,5vw,2.5rem);font-variant-numeric:tabular-nums;line-height:1}.analytics-presentation__kpi-card span,.analytics-presentation__kpi-card small{overflow-wrap:anywhere}.analytics-presentation__kpi-card span{font-weight:600}.analytics-presentation__kpi-card small{color:var(--md-sys-color-on-surface-variant, #44474e)}@media(max-width:600px){.analytics-presentation__toolbar{justify-content:stretch}.analytics-presentation__toolbar button{flex:1 1 0}}\n"], dependencies: [{ kind: "component", type: PraxisChartComponent, selector: "praxis-chart", inputs: ["config", "resourceKey", "data", "chartDocument", "filterCriteria", "queryContext", "remoteDataResolver", "enableCustomization", "availableResources", "availableFields", "availableTargets"], outputs: ["pointClick", "pointAction", "selectionChange", "drillDown", "crossFilter", "queryRequest", "loadStateChange", "chartDocumentApplied", "chartDocumentSaved", "chartDocumentPatchChange"] }, { kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "filterTeleport", "widgetId", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "authoringCapability", "dense"], outputs: ["filterCriteriaChange", "queryContextClear", "queryContextChange", "rowClick", "widgetEvent", "resourceEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "columnResize", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange", "drawerOpen", "drawerClose", "drawerTabChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5793
5793
  }
5794
5794
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisAnalyticsPresentationComponent, decorators: [{
5795
5795
  type: Component,
@@ -7765,7 +7765,11 @@ class PraxisChartConfigEditorContextResolverService {
7765
7765
  ],
7766
7766
  };
7767
7767
  }
7768
- async resolveResource(resourceIdentity) {
7768
+ async resolveResource(resourceIdentity, knownResource) {
7769
+ const knownCandidate = this.candidateFromKnownResource(resourceIdentity, knownResource);
7770
+ if (knownCandidate) {
7771
+ return this.resolveCandidateCapabilities(knownCandidate);
7772
+ }
7769
7773
  let projection;
7770
7774
  try {
7771
7775
  projection = await this.getCatalogProjection();
@@ -7782,6 +7786,29 @@ class PraxisChartConfigEditorContextResolverService {
7782
7786
  diagnostics: [...projection.diagnostics, ...selected.diagnostics],
7783
7787
  };
7784
7788
  }
7789
+ candidateFromKnownResource(resourceIdentity, knownResource) {
7790
+ if (!knownResource) {
7791
+ return null;
7792
+ }
7793
+ const id = String(knownResource.id || '').trim();
7794
+ const rawPath = String(knownResource.path || '').trim();
7795
+ if (!id || !this.isGovernedRelativePath(rawPath)) {
7796
+ return null;
7797
+ }
7798
+ const resourcePath = this.normalizeOperationalPath(rawPath);
7799
+ const identity = String(resourceIdentity || '').trim();
7800
+ if (identity && id !== identity && this.normalizeOperationalPath(identity) !== resourcePath) {
7801
+ return null;
7802
+ }
7803
+ return {
7804
+ option: {
7805
+ ...knownResource,
7806
+ id,
7807
+ path: resourcePath,
7808
+ },
7809
+ capabilitiesHref: `${resourcePath}/capabilities`,
7810
+ };
7811
+ }
7785
7812
  async resolveResourceFromProjection(resourceIdentity, projection) {
7786
7813
  const candidate = this.findCandidate(projection.candidates, resourceIdentity);
7787
7814
  if (!candidate) {
@@ -7794,6 +7821,9 @@ class PraxisChartConfigEditorContextResolverService {
7794
7821
  }],
7795
7822
  };
7796
7823
  }
7824
+ return this.resolveCandidateCapabilities(candidate);
7825
+ }
7826
+ async resolveCandidateCapabilities(candidate) {
7797
7827
  let capabilities;
7798
7828
  try {
7799
7829
  capabilities = await this.getCapabilities(candidate);
@@ -8801,7 +8831,7 @@ class PraxisChartShowcaseWidgetComponent {
8801
8831
  (rowClick)="handleRowClick($event)"
8802
8832
  ></praxis-table>
8803
8833
  }
8804
- `, isInline: true, styles: [":host{display:block;height:100%;min-width:0}.showcase-state-card{min-height:240px;display:grid;place-content:center;gap:8px;padding:24px;border-radius:18px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline, #c5c7ce) 72%,transparent);background:linear-gradient(180deg,#fffffff5,#f4f7fbfa);text-align:center}.showcase-state-card h4{margin:0;font-size:1rem;font-weight:600;color:var(--md-sys-color-on-surface, #1a1b20)}.showcase-state-card p{margin:0;color:var(--md-sys-color-on-surface-variant, #5a5d67)}\n"], dependencies: [{ kind: "component", type: PraxisChartComponent, selector: "praxis-chart", inputs: ["config", "resourceKey", "data", "chartDocument", "filterCriteria", "queryContext", "remoteDataResolver", "enableCustomization", "availableResources", "availableFields", "availableTargets"], outputs: ["pointClick", "pointAction", "selectionChange", "drillDown", "crossFilter", "queryRequest", "loadStateChange", "chartDocumentApplied", "chartDocumentSaved", "chartDocumentPatchChange"] }, { kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "filterTeleport", "widgetId", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "authoringCapability", "dense"], outputs: ["queryContextClear", "queryContextChange", "rowClick", "widgetEvent", "resourceEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "columnResize", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange", "drawerOpen", "drawerClose", "drawerTabChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8834
+ `, isInline: true, styles: [":host{display:block;height:100%;min-width:0}.showcase-state-card{min-height:240px;display:grid;place-content:center;gap:8px;padding:24px;border-radius:18px;border:1px solid color-mix(in srgb,var(--md-sys-color-outline, #c5c7ce) 72%,transparent);background:linear-gradient(180deg,#fffffff5,#f4f7fbfa);text-align:center}.showcase-state-card h4{margin:0;font-size:1rem;font-weight:600;color:var(--md-sys-color-on-surface, #1a1b20)}.showcase-state-card p{margin:0;color:var(--md-sys-color-on-surface-variant, #5a5d67)}\n"], dependencies: [{ kind: "component", type: PraxisChartComponent, selector: "praxis-chart", inputs: ["config", "resourceKey", "data", "chartDocument", "filterCriteria", "queryContext", "remoteDataResolver", "enableCustomization", "availableResources", "availableFields", "availableTargets"], outputs: ["pointClick", "pointAction", "selectionChange", "drillDown", "crossFilter", "queryRequest", "loadStateChange", "chartDocumentApplied", "chartDocumentSaved", "chartDocumentPatchChange"] }, { kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "filterTeleport", "widgetId", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "authoringCapability", "dense"], outputs: ["filterCriteriaChange", "queryContextClear", "queryContextChange", "rowClick", "widgetEvent", "resourceEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "columnResize", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange", "drawerOpen", "drawerClose", "drawerTabChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
8805
8835
  }
8806
8836
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisChartShowcaseWidgetComponent, decorators: [{
8807
8837
  type: Component,
@@ -11916,7 +11946,7 @@ class PraxisChartConfigEditor {
11916
11946
  this.refreshState(this.isDirty$.value);
11917
11947
  return;
11918
11948
  }
11919
- void this.resolveSelectedResource(resource);
11949
+ void this.resolveSelectedResource(resource, option);
11920
11950
  }
11921
11951
  setOperation(value) {
11922
11952
  if (this.doc().kind === 'gauge' && value !== 'group-by') {
@@ -12916,28 +12946,32 @@ class PraxisChartConfigEditor {
12916
12946
  return resourceIds.includes(resource.id)
12917
12947
  || resourcePaths.some((path) => this.normalizeResourcePath(path) === this.normalizeResourcePath(resource.path));
12918
12948
  }
12919
- async resolveSelectedResource(resource) {
12949
+ resolvedResourceCache = new Map();
12950
+ async resolveSelectedResource(resource, knownOption) {
12920
12951
  const requestId = ++this.catalogResolutionRequestId;
12952
+ const cacheKey = this.normalizeResourcePath(knownOption?.path || resource) || resource;
12953
+ const cached = this.resolvedResourceCache.get(cacheKey);
12954
+ if (cached) {
12955
+ this.applyResourceResolution(resource, cached);
12956
+ this.resolvingResource.set(false);
12957
+ this.isBusy$.next(false);
12958
+ this.refreshState(this.isDirty$.value);
12959
+ return;
12960
+ }
12921
12961
  this.resolvingResource.set(true);
12922
12962
  this.resolvedFields.set([]);
12923
12963
  this.catalogResolutionDiagnostics.set([]);
12924
12964
  this.isBusy$.next(true);
12925
12965
  this.refreshState(this.isDirty$.value);
12926
12966
  try {
12927
- const resolution = await this.contextResolver.resolveResource(resource);
12967
+ const resolution = await this.contextResolver.resolveResource(resource, knownOption);
12928
12968
  if (requestId !== this.catalogResolutionRequestId) {
12929
12969
  return;
12930
12970
  }
12931
- if (resolution.resource) {
12932
- const currentResources = this.resolvedResources() ?? this.baseAvailableResources();
12933
- const matchIndex = currentResources.findIndex((candidate) => (candidate.id === resolution.resource?.id
12934
- || this.resourceIdentityMatches(candidate, resource)));
12935
- this.resolvedResources.set(matchIndex >= 0
12936
- ? currentResources.map((candidate, index) => index === matchIndex ? resolution.resource : candidate)
12937
- : [...currentResources, resolution.resource]);
12971
+ if (resolution.resource && resolution.fields.length > 0 && !resolution.diagnostics.some((d) => d.severity === 'error')) {
12972
+ this.resolvedResourceCache.set(cacheKey, resolution);
12938
12973
  }
12939
- this.resolvedFields.set(resolution.fields);
12940
- this.catalogResolutionDiagnostics.set(resolution.diagnostics);
12974
+ this.applyResourceResolution(resource, resolution);
12941
12975
  }
12942
12976
  catch {
12943
12977
  if (requestId !== this.catalogResolutionRequestId) {
@@ -12958,6 +12992,18 @@ class PraxisChartConfigEditor {
12958
12992
  }
12959
12993
  }
12960
12994
  }
12995
+ applyResourceResolution(resource, resolution) {
12996
+ if (resolution.resource) {
12997
+ const currentResources = this.resolvedResources() ?? this.baseAvailableResources();
12998
+ const matchIndex = currentResources.findIndex((candidate) => (candidate.id === resolution.resource?.id
12999
+ || this.resourceIdentityMatches(candidate, resource)));
13000
+ this.resolvedResources.set(matchIndex >= 0
13001
+ ? currentResources.map((candidate, index) => index === matchIndex ? resolution.resource : candidate)
13002
+ : [...currentResources, resolution.resource]);
13003
+ }
13004
+ this.resolvedFields.set(resolution.fields);
13005
+ this.catalogResolutionDiagnostics.set(resolution.diagnostics);
13006
+ }
12961
13007
  resourceIdentityMatches(option, identity) {
12962
13008
  const normalizedIdentity = this.normalizeResourcePath(identity);
12963
13009
  return option.id === identity
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@praxisui/charts",
3
- "version": "10.0.0-rc.30",
3
+ "version": "10.0.0-rc.32",
4
4
  "description": "Metadata-driven charts library for Praxis UI Angular with engine adapters and Apache ECharts as the initial renderer.",
5
5
  "peerDependencies": {
6
6
  "@angular/common": "^21.0.0",
7
7
  "@angular/core": "^21.0.0",
8
- "@praxisui/core": "^10.0.0-rc.30",
8
+ "@praxisui/core": "^10.0.0-rc.32",
9
9
  "@angular/forms": "^21.0.0",
10
10
  "@angular/material": "^21.0.0",
11
- "@praxisui/table": "^10.0.0-rc.30",
11
+ "@praxisui/table": "^10.0.0-rc.32",
12
12
  "rxjs": "~7.8.0"
13
13
  },
14
14
  "dependencies": {
@@ -1667,7 +1667,9 @@ declare class PraxisChartConfigEditor implements SettingsValueProvider {
1667
1667
  private validateCatalogContext;
1668
1668
  private fieldMatchesSelectedResource;
1669
1669
  private fieldMatchesResourceOption;
1670
+ private readonly resolvedResourceCache;
1670
1671
  private resolveSelectedResource;
1672
+ private applyResourceResolution;
1671
1673
  private resourceIdentityMatches;
1672
1674
  private normalizeResourcePath;
1673
1675
  private groupCatalogResolutionDiagnostics;