@praxisui/charts 9.0.62 → 9.0.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.
package/README.md CHANGED
@@ -155,6 +155,8 @@ The public contract is `PraxisChartConfig` or the canonical `PraxisXUiChartContr
155
155
 
156
156
  The structured alternative is automatic. It does not add an accessibility field to `PraxisChartConfig` or `x-ui.chart`, and custom engines remain responsible for an accessible visual rendering while the component-level data alternative remains renderer-neutral.
157
157
 
158
+ Standalone charts render that toggle inside the component. When the chart is loaded by `WidgetShell`, it contributes the same stateful action to the shell toolbar and suppresses the duplicate internal control. The visual canvas becomes hidden and inert while the opaque structured-data surface is active, so the two representations never compete visually or interactively.
159
+
158
160
  Supported canonical kinds are `bar`, `horizontal-bar`, `line`, `area`, `stacked-bar`,
159
161
  `stacked-area`, `combo`, `pie`, `donut`, `scatter`, `funnel`, `pyramid`, `treemap`, and `gauge`. Funnel,
160
162
  pyramid, and treemap require one categorical dimension and exactly one non-negative metric. Funnel
@@ -190,9 +192,12 @@ requests.
190
192
 
191
193
  Choice precedence is temporary user choice, persisted `preferredFamily`, then projection hints.
192
194
  `availableFamilies` must already reflect host policy/capabilities; the runtime intersects it with
193
- installed and semantically eligible renderers. Incompatible preferences fail closed. This first
194
- cut may execute the same canonical query again when switching renderer, and stale table responses
195
- are ignored. KPI and summary-list remain unavailable until they have canonical remote renderers.
195
+ installed and semantically eligible renderers. Incompatible preferences fail closed. Switching
196
+ renderer may execute the same canonical query again; when projection, family or `queryContext`
197
+ changes, the component unsubscribes the previous Table/KPI request so the HTTP transport is
198
+ aborted instead of merely ignoring a stale result. KPI is eligible for canonical `group-by`
199
+ projections with exactly one primary metric. Summary-list remains unavailable until it has a
200
+ canonical remote renderer.
196
201
 
197
202
  ## Canonical Chart Documents
198
203
 
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-09-05T09:42:11.098Z",
3
+ "generatedAt": "2026-09-05T19:46:18.619Z",
4
4
  "packageName": "@praxisui/charts",
5
- "packageVersion": "9.0.62",
5
+ "packageVersion": "9.0.63",
6
6
  "sourceRegistry": "praxis-component-registry-ingestion",
7
7
  "sourceRegistryVersion": "1.0.0",
8
8
  "componentCount": 3,
@@ -878,7 +878,10 @@ class ChartContractValidationService {
878
878
  return;
879
879
  }
880
880
  if (!document.dimensions?.length) {
881
- issues.push(this.error('gauge-missing-dimension', 'dimensions', 'x-ui.chart gauge charts require at least one dimension.'));
881
+ issues.push(this.error('gauge-missing-dimension', 'dimensions', 'x-ui.chart gauge charts require one dimension.'));
882
+ }
883
+ else if (document.dimensions.length !== 1) {
884
+ issues.push(this.error('gauge-single-dimension', 'dimensions', 'x-ui.chart gauge charts require exactly one dimension.'));
882
885
  }
883
886
  if ((document.metrics?.length ?? 0) !== 1) {
884
887
  issues.push(this.error('gauge-single-metric', 'metrics', 'x-ui.chart gauge charts require exactly one metric.'));
@@ -1917,6 +1920,7 @@ class PraxisChartComponent {
1917
1920
  activeSelectionSignature = signal(null, ...(ngDevMode ? [{ debugName: "activeSelectionSignature" }] : /* istanbul ignore next */ []));
1918
1921
  configEditorContextPending = signal(false, ...(ngDevMode ? [{ debugName: "configEditorContextPending" }] : /* istanbul ignore next */ []));
1919
1922
  showAccessibleData = signal(false, ...(ngDevMode ? [{ debugName: "showAccessibleData" }] : /* istanbul ignore next */ []));
1923
+ widgetShellActionHostActive = signal(false, ...(ngDevMode ? [{ debugName: "widgetShellActionHostActive" }] : /* istanbul ignore next */ []));
1920
1924
  accessibilityPanelId = `praxis-chart-data-${++chartAccessibilityPanelSequence}`;
1921
1925
  accessibilityPanelTitleId = `${this.accessibilityPanelId}-title`;
1922
1926
  fillContainerHeight = signal(false, ...(ngDevMode ? [{ debugName: "fillContainerHeight" }] : /* istanbul ignore next */ []));
@@ -1982,6 +1986,21 @@ class PraxisChartComponent {
1982
1986
  const sizing = this.effectiveConfig().sizing;
1983
1987
  return this.toCssSize(sizing?.minHeight) ?? (this.isFillContainerMode() ? '0' : null);
1984
1988
  }, ...(ngDevMode ? [{ debugName: "resolvedMinHeight" }] : /* istanbul ignore next */ []));
1989
+ resolvedHostMinHeight = computed(() => {
1990
+ const sizing = this.effectiveConfig().sizing;
1991
+ const configuredMinHeight = this.toCssSize(sizing?.minHeight);
1992
+ if (configuredMinHeight) {
1993
+ return configuredMinHeight;
1994
+ }
1995
+ const mode = sizing?.mode ?? (sizing?.height !== undefined ? 'fixed' : undefined);
1996
+ if (mode === 'fixed' || mode === 'fill-container' || mode === 'auto') {
1997
+ return '0';
1998
+ }
1999
+ if (this.effectiveConfig().height !== undefined) {
2000
+ return '0';
2001
+ }
2002
+ return 'var(--praxis-chart-runtime-height, 320px)';
2003
+ }, ...(ngDevMode ? [{ debugName: "resolvedHostMinHeight" }] : /* istanbul ignore next */ []));
1985
2004
  resolvedMaxHeight = computed(() => this.toCssSize(this.effectiveConfig().sizing?.maxHeight) ?? null, ...(ngDevMode ? [{ debugName: "resolvedMaxHeight" }] : /* istanbul ignore next */ []));
1986
2005
  resolvedAspectRatio = computed(() => this.toCssAspectRatio(this.effectiveConfig().sizing?.aspectRatio), ...(ngDevMode ? [{ debugName: "resolvedAspectRatio" }] : /* istanbul ignore next */ []));
1987
2006
  isFillContainerMode = computed(() => {
@@ -1993,6 +2012,16 @@ class PraxisChartComponent {
1993
2012
  surfaceBorderWidth = computed(() => this.toCssSize(this.effectiveConfig().theme?.surface?.borderWidth) ?? null, ...(ngDevMode ? [{ debugName: "surfaceBorderWidth" }] : /* istanbul ignore next */ []));
1994
2013
  surfaceBorderRadius = computed(() => this.toCssSize(this.effectiveConfig().theme?.surface?.borderRadius) ?? null, ...(ngDevMode ? [{ debugName: "surfaceBorderRadius" }] : /* istanbul ignore next */ []));
1995
2014
  surfaceTextColor = computed(() => this.effectiveConfig().theme?.textColor ?? null, ...(ngDevMode ? [{ debugName: "surfaceTextColor" }] : /* istanbul ignore next */ []));
2015
+ accessibleDataSurfaceBackground = computed(() => {
2016
+ const background = this.surfaceBackground()?.trim();
2017
+ if (!background ||
2018
+ background.toLowerCase() === 'transparent' ||
2019
+ background.replace(/\s/g, '') === 'rgba(0,0,0,0)' ||
2020
+ background.toLowerCase() === '#00000000') {
2021
+ return 'var(--md-sys-color-surface-container-lowest, #fff)';
2022
+ }
2023
+ return background;
2024
+ }, ...(ngDevMode ? [{ debugName: "accessibleDataSurfaceBackground" }] : /* istanbul ignore next */ []));
1996
2025
  renderConfig = computed(() => {
1997
2026
  const config = this.effectiveConfig();
1998
2027
  const explicitData = this.data();
@@ -2081,6 +2110,26 @@ class PraxisChartComponent {
2081
2110
  accessibleCategoryHeading = computed(() => this.t('praxis.charts.runtime.accessibility.category', 'Category'), ...(ngDevMode ? [{ debugName: "accessibleCategoryHeading" }] : /* istanbul ignore next */ []));
2082
2111
  accessibleSeriesHeading = computed(() => this.t('praxis.charts.runtime.accessibility.series', 'Series'), ...(ngDevMode ? [{ debugName: "accessibleSeriesHeading" }] : /* istanbul ignore next */ []));
2083
2112
  accessibleValueHeading = computed(() => this.t('praxis.charts.runtime.accessibility.value', 'Value'), ...(ngDevMode ? [{ debugName: "accessibleValueHeading" }] : /* istanbul ignore next */ []));
2113
+ widgetShellActions = computed(() => {
2114
+ if (this.loadState() !== 'ready' || !this.accessiblePoints().length) {
2115
+ return [];
2116
+ }
2117
+ const dataVisible = this.showAccessibleData();
2118
+ const label = this.accessibleDataToggleLabel();
2119
+ return [{
2120
+ id: 'chart-data-view',
2121
+ label,
2122
+ tooltip: label,
2123
+ icon: 'table_view',
2124
+ pressedIcon: 'bar_chart',
2125
+ variant: 'icon',
2126
+ placement: 'header',
2127
+ command: 'praxis-chart:toggle-data-view',
2128
+ pressed: dataVisible,
2129
+ ariaControls: this.accessibilityPanelId,
2130
+ ariaExpanded: dataVisible,
2131
+ }];
2132
+ }, ...(ngDevMode ? [{ debugName: "widgetShellActions" }] : /* istanbul ignore next */ []));
2084
2133
  loadState = computed(() => {
2085
2134
  if (this.chartDocumentMappingError()) {
2086
2135
  return 'error';
@@ -2492,6 +2541,15 @@ class PraxisChartComponent {
2492
2541
  toggleAccessibleData() {
2493
2542
  this.showAccessibleData.update((visible) => !visible);
2494
2543
  }
2544
+ setWidgetShellActionHostActive(active) {
2545
+ this.widgetShellActionHostActive.set(active);
2546
+ }
2547
+ handleShellAction(action) {
2548
+ if (action.command === 'praxis-chart:toggle-data-view' ||
2549
+ action.id === 'chart-data-view') {
2550
+ this.toggleAccessibleData();
2551
+ }
2552
+ }
2495
2553
  activateAccessiblePoint(point) {
2496
2554
  this.handlePointClick({
2497
2555
  chartId: point.chartId,
@@ -2857,7 +2915,7 @@ class PraxisChartComponent {
2857
2915
  this.resizeFrameId = null;
2858
2916
  }
2859
2917
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2860
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisChartComponent, isStandalone: true, selector: "praxis-chart", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, chartDocument: { classPropertyName: "chartDocument", publicName: "chartDocument", isSignal: true, isRequired: false, transformFunction: null }, filterCriteria: { classPropertyName: "filterCriteria", publicName: "filterCriteria", isSignal: true, isRequired: false, transformFunction: null }, queryContext: { classPropertyName: "queryContext", publicName: "queryContext", isSignal: true, isRequired: false, transformFunction: null }, remoteDataResolver: { classPropertyName: "remoteDataResolver", publicName: "remoteDataResolver", isSignal: true, isRequired: false, transformFunction: null }, enableCustomization: { classPropertyName: "enableCustomization", publicName: "enableCustomization", isSignal: true, isRequired: false, transformFunction: null }, availableResources: { classPropertyName: "availableResources", publicName: "availableResources", isSignal: true, isRequired: false, transformFunction: null }, availableFields: { classPropertyName: "availableFields", publicName: "availableFields", isSignal: true, isRequired: false, transformFunction: null }, availableTargets: { classPropertyName: "availableTargets", publicName: "availableTargets", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pointClick: "pointClick", pointAction: "pointAction", selectionChange: "selectionChange", drillDown: "drillDown", crossFilter: "crossFilter", queryRequest: "queryRequest", loadStateChange: "loadStateChange", chartDocumentApplied: "chartDocumentApplied", chartDocumentSaved: "chartDocumentSaved", chartDocumentPatchChange: "chartDocumentPatchChange" }, host: { properties: { "class.praxis-chart-host-fill-container": "isFillContainerMode()" } }, viewQueries: [{ propertyName: "chartHost", first: true, predicate: ["chartHost"], descendants: true, isSignal: true }], ngImport: i0, template: `
2918
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisChartComponent, isStandalone: true, selector: "praxis-chart", inputs: { config: { classPropertyName: "config", publicName: "config", isSignal: true, isRequired: false, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null }, chartDocument: { classPropertyName: "chartDocument", publicName: "chartDocument", isSignal: true, isRequired: false, transformFunction: null }, filterCriteria: { classPropertyName: "filterCriteria", publicName: "filterCriteria", isSignal: true, isRequired: false, transformFunction: null }, queryContext: { classPropertyName: "queryContext", publicName: "queryContext", isSignal: true, isRequired: false, transformFunction: null }, remoteDataResolver: { classPropertyName: "remoteDataResolver", publicName: "remoteDataResolver", isSignal: true, isRequired: false, transformFunction: null }, enableCustomization: { classPropertyName: "enableCustomization", publicName: "enableCustomization", isSignal: true, isRequired: false, transformFunction: null }, availableResources: { classPropertyName: "availableResources", publicName: "availableResources", isSignal: true, isRequired: false, transformFunction: null }, availableFields: { classPropertyName: "availableFields", publicName: "availableFields", isSignal: true, isRequired: false, transformFunction: null }, availableTargets: { classPropertyName: "availableTargets", publicName: "availableTargets", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { pointClick: "pointClick", pointAction: "pointAction", selectionChange: "selectionChange", drillDown: "drillDown", crossFilter: "crossFilter", queryRequest: "queryRequest", loadStateChange: "loadStateChange", chartDocumentApplied: "chartDocumentApplied", chartDocumentSaved: "chartDocumentSaved", chartDocumentPatchChange: "chartDocumentPatchChange" }, host: { properties: { "class.praxis-chart-host-fill-container": "isFillContainerMode()", "style.height": "resolvedHeight()", "style.min-height": "resolvedHostMinHeight()", "style.max-height": "resolvedMaxHeight()", "style.aspect-ratio": "resolvedAspectRatio()" } }, viewQueries: [{ propertyName: "chartHost", first: true, predicate: ["chartHost"], descendants: true, isSignal: true }], ngImport: i0, template: `
2861
2919
  <section
2862
2920
  class="praxis-chart-shell"
2863
2921
  [class.praxis-chart-shell-fill-container]="isFillContainerMode()"
@@ -2889,7 +2947,11 @@ class PraxisChartComponent {
2889
2947
  ></button>
2890
2948
  }
2891
2949
 
2892
- @if (loadState() === 'ready' && accessiblePoints().length) {
2950
+ @if (
2951
+ loadState() === 'ready' &&
2952
+ accessiblePoints().length &&
2953
+ !widgetShellActionHostActive()
2954
+ ) {
2893
2955
  <button
2894
2956
  class="praxis-chart-data-trigger"
2895
2957
  [class.praxis-chart-data-trigger-with-settings]="canOpenConfigEditor()"
@@ -2963,6 +3025,8 @@ class PraxisChartComponent {
2963
3025
  @if (showAccessibleData()) {
2964
3026
  <section
2965
3027
  class="praxis-chart-accessible-data"
3028
+ [class.praxis-chart-accessible-data--shell-controlled]="widgetShellActionHostActive()"
3029
+ [style.background]="accessibleDataSurfaceBackground()"
2966
3030
  [id]="accessibilityPanelId"
2967
3031
  role="region"
2968
3032
  [attr.aria-labelledby]="accessibilityPanelTitleId"
@@ -3002,16 +3066,21 @@ class PraxisChartComponent {
3002
3066
  <div
3003
3067
  #chartHost
3004
3068
  class="praxis-chart-host"
3069
+ [class.praxis-chart-host--data-hidden]="showAccessibleData()"
3005
3070
  [attr.aria-hidden]="showAccessibleData() ? 'true' : null"
3006
3071
  ></div>
3007
3072
  }
3008
3073
  </section>
3009
- `, isInline: true, styles: [":host{display:block;min-height:var(--praxis-chart-runtime-height, 320px);min-width:0;color:var(--md-sys-color-on-surface, #1a1b20)}:host(.praxis-chart-host-fill-container){height:100%;min-height:0}:host-context(.pdx-shell.no-shell) .praxis-chart-shell,:host-context(.pdx-shell.body-fill) .praxis-chart-shell,:host-context(.pdx-shell.expanded) .praxis-chart-shell,:host-context(.pdx-shell.fullscreen) .praxis-chart-shell{height:100%!important}.praxis-chart-shell{position:relative;width:100%;height:100%;min-height:240px;border-radius:var(--praxis-chart-config-surface-radius, var(--praxis-chart-surface-radius, 8px));overflow:hidden;background:var( --praxis-chart-config-surface-bg, var(--praxis-chart-surface-bg, var(--md-sys-color-surface-container-lowest, #fff)) );border-color:var( --praxis-chart-config-surface-border, var( --praxis-chart-surface-border, color-mix(in srgb, var(--md-sys-color-outline, #c5c7ce) 44%, transparent) ) );border-style:solid;border-width:var(--praxis-chart-config-surface-border-width, 1px)}.praxis-chart-shell-fill-container{min-height:0}:host-context(.pdx-shell) .praxis-chart-shell:not(.praxis-chart-shell-contained),.praxis-chart-shell-embedded{border-width:var( --praxis-chart-config-surface-border-width, var(--praxis-chart-embedded-surface-border-width, 0) );border-radius:var( --praxis-chart-config-surface-radius, var(--praxis-chart-embedded-surface-radius, 0) );background:var( --praxis-chart-config-surface-bg, var(--praxis-chart-embedded-surface-bg, transparent) )}.praxis-chart-settings-trigger{position:absolute;top:10px;right:10px;z-index:3;--praxis-icon-button-filled-background: color-mix(in srgb, var(--md-sys-color-surface, #fff) 88%, rgba(18, 99, 180, .12));--praxis-icon-button-filled-foreground: var(--md-sys-color-on-surface-variant, #44474f);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.praxis-chart-data-trigger{position:absolute;top:10px;right:10px;z-index:5;--praxis-icon-button-filled-background: color-mix(in srgb, var(--md-sys-color-surface, #fff) 88%, rgba(18, 99, 180, .12));--praxis-icon-button-filled-foreground: var(--md-sys-color-on-surface-variant, #44474f);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.praxis-chart-data-trigger-with-settings{right:50px}.praxis-chart-accessible-data{position:absolute;inset:0;z-index:4;overflow:auto;padding:52px 16px 16px;color:var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface, #1a1b20));background:var( --praxis-chart-config-surface-bg, var(--praxis-chart-surface-bg, var(--md-sys-color-surface-container-lowest, #fff)) )}.praxis-chart-accessible-data h3{margin:0 0 12px;font-size:1rem;line-height:1.4}.praxis-chart-accessible-data table{width:100%;border-collapse:collapse;font-size:.875rem}.praxis-chart-accessible-data caption{padding:0 0 12px;text-align:left;color:inherit}.praxis-chart-accessible-data th,.praxis-chart-accessible-data td{padding:8px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline, #c5c7ce) 44%,transparent);text-align:left}.praxis-chart-accessible-data thead th{font-weight:600}.praxis-chart-point-action{appearance:none;padding:4px 6px;border:0;border-radius:4px;color:inherit;background:transparent;font:inherit;font-weight:600;text-align:left;text-decoration:underline;text-decoration-thickness:from-font;text-underline-offset:.16em;cursor:pointer}.praxis-chart-point-action:hover{background:color-mix(in srgb,currentColor 10%,transparent)}.praxis-chart-point-action:focus-visible{outline:3px solid currentColor;outline-offset:2px}.praxis-chart-point-action[aria-pressed=true]{color:var(--md-sys-color-on-primary-container, #001b3f);background:var(--md-sys-color-primary-container, #d7e3ff)}.praxis-chart-host{width:100%;height:100%;min-height:inherit}.praxis-chart-state{height:100%;min-height:min(240px,100%);display:grid;align-content:center;justify-items:center;gap:14px;padding:24px;text-align:center}.praxis-chart-state-copy{display:grid;gap:6px;justify-items:center}.praxis-chart-state-title{font-size:1rem;font-weight:600;color:var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface, #1a1b20))}.praxis-chart-state-description{font-size:.925rem;color:color-mix(in srgb,var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface-variant, #5a5d67)) 72%,transparent);max-width:36rem}.praxis-chart-loading-hero{width:min(100%,320px);display:grid;gap:14px}.praxis-chart-loading-summary{display:flex;gap:8px;justify-content:center}.praxis-chart-loading-chip,.praxis-chart-loading-bar{border-radius:999px;background:linear-gradient(90deg,#1263b414,#1263b438,#1263b414);background-size:200% 100%;animation:praxis-chart-loading-wave 1.2s ease-in-out infinite}.praxis-chart-loading-chip{display:block;width:104px;height:12px}.praxis-chart-loading-chip--short{width:64px}.praxis-chart-loading-plot{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));align-items:end;gap:10px;height:108px;padding:12px 8px 4px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container, #eef3f8) 72%,transparent);border:1px solid rgba(18,99,180,.08)}.praxis-chart-loading-bar{display:block;width:100%}.praxis-chart-loading-bar--1{height:32%}.praxis-chart-loading-bar--2{height:68%}.praxis-chart-loading-bar--3{height:48%}.praxis-chart-loading-bar--4{height:78%}.praxis-chart-loading-bar--5{height:56%}@keyframes praxis-chart-loading-wave{0%{background-position:100% 0}to{background-position:-100% 0}}\n"], dependencies: [{ kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i1$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3074
+ `, isInline: true, styles: [":host{display:block;min-height:var(--praxis-chart-runtime-height, 320px);min-width:0;color:var(--md-sys-color-on-surface, #1a1b20)}:host(.praxis-chart-host-fill-container){height:100%;min-height:0}:host-context(.pdx-shell.no-shell) .praxis-chart-shell,:host-context(.pdx-shell.body-fill) .praxis-chart-shell,:host-context(.pdx-shell.expanded) .praxis-chart-shell,:host-context(.pdx-shell.fullscreen) .praxis-chart-shell{height:100%!important}.praxis-chart-shell{box-sizing:border-box;position:relative;width:100%;height:100%;min-height:240px;border-radius:var(--praxis-chart-config-surface-radius, var(--praxis-chart-surface-radius, 8px));overflow:hidden;background:var( --praxis-chart-config-surface-bg, var(--praxis-chart-surface-bg, var(--md-sys-color-surface-container-lowest, #fff)) );border-color:var( --praxis-chart-config-surface-border, var( --praxis-chart-surface-border, color-mix(in srgb, var(--md-sys-color-outline, #c5c7ce) 44%, transparent) ) );border-style:solid;border-width:var(--praxis-chart-config-surface-border-width, 1px)}.praxis-chart-shell-fill-container{min-height:0}:host-context(.pdx-shell) .praxis-chart-shell:not(.praxis-chart-shell-contained),.praxis-chart-shell-embedded{border-width:var( --praxis-chart-config-surface-border-width, var(--praxis-chart-embedded-surface-border-width, 0) );border-radius:var( --praxis-chart-config-surface-radius, var(--praxis-chart-embedded-surface-radius, 0) );background:var( --praxis-chart-config-surface-bg, var(--praxis-chart-embedded-surface-bg, transparent) )}.praxis-chart-settings-trigger{position:absolute;top:10px;right:10px;z-index:3;--praxis-icon-button-filled-background: color-mix(in srgb, var(--md-sys-color-surface, #fff) 88%, rgba(18, 99, 180, .12));--praxis-icon-button-filled-foreground: var(--md-sys-color-on-surface-variant, #44474f);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.praxis-chart-data-trigger{position:absolute;top:10px;right:10px;z-index:5;--praxis-icon-button-filled-background: color-mix(in srgb, var(--md-sys-color-surface, #fff) 88%, rgba(18, 99, 180, .12));--praxis-icon-button-filled-foreground: var(--md-sys-color-on-surface-variant, #44474f);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.praxis-chart-data-trigger-with-settings{right:50px}.praxis-chart-accessible-data{position:absolute;inset:0;z-index:4;overflow:auto;padding:52px 16px 16px;color:var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface, #1a1b20));background:var(--md-sys-color-surface-container-lowest, #fff)}.praxis-chart-accessible-data--shell-controlled{padding-top:16px}.praxis-chart-accessible-data h3{margin:0 0 12px;font-size:1rem;line-height:1.4}.praxis-chart-accessible-data table{width:100%;border-collapse:collapse;font-size:.875rem}.praxis-chart-accessible-data caption{padding:0 0 12px;text-align:left;color:inherit}.praxis-chart-accessible-data th,.praxis-chart-accessible-data td{padding:8px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline, #c5c7ce) 44%,transparent);text-align:left}.praxis-chart-accessible-data thead th{font-weight:600}.praxis-chart-point-action{appearance:none;padding:4px 6px;border:0;border-radius:4px;color:inherit;background:transparent;font:inherit;font-weight:600;text-align:left;text-decoration:underline;text-decoration-thickness:from-font;text-underline-offset:.16em;cursor:pointer}.praxis-chart-point-action:hover{background:color-mix(in srgb,currentColor 10%,transparent)}.praxis-chart-point-action:focus-visible{outline:3px solid currentColor;outline-offset:2px}.praxis-chart-point-action[aria-pressed=true]{color:var(--md-sys-color-on-primary-container, #001b3f);background:var(--md-sys-color-primary-container, #d7e3ff)}.praxis-chart-host{width:100%;height:100%;min-height:inherit}.praxis-chart-host--data-hidden{visibility:hidden;pointer-events:none}.praxis-chart-state{height:100%;min-height:min(240px,100%);display:grid;align-content:center;justify-items:center;gap:14px;padding:24px;text-align:center}.praxis-chart-state-copy{display:grid;gap:6px;justify-items:center}.praxis-chart-state-title{font-size:1rem;font-weight:600;color:var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface, #1a1b20))}.praxis-chart-state-description{font-size:.925rem;color:color-mix(in srgb,var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface-variant, #5a5d67)) 72%,transparent);max-width:36rem}.praxis-chart-loading-hero{width:min(100%,320px);display:grid;gap:14px}.praxis-chart-loading-summary{display:flex;gap:8px;justify-content:center}.praxis-chart-loading-chip,.praxis-chart-loading-bar{border-radius:999px;background:linear-gradient(90deg,#1263b414,#1263b438,#1263b414);background-size:200% 100%;animation:praxis-chart-loading-wave 1.2s ease-in-out infinite}.praxis-chart-loading-chip{display:block;width:104px;height:12px}.praxis-chart-loading-chip--short{width:64px}.praxis-chart-loading-plot{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));align-items:end;gap:10px;height:108px;padding:12px 8px 4px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container, #eef3f8) 72%,transparent);border:1px solid rgba(18,99,180,.08)}.praxis-chart-loading-bar{display:block;width:100%}.praxis-chart-loading-bar--1{height:32%}.praxis-chart-loading-bar--2{height:68%}.praxis-chart-loading-bar--3{height:48%}.praxis-chart-loading-bar--4{height:78%}.praxis-chart-loading-bar--5{height:56%}@keyframes praxis-chart-loading-wave{0%{background-position:100% 0}to{background-position:-100% 0}}\n"], dependencies: [{ kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i1$2.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: PraxisIconButtonComponent, selector: "button[praxisIconButton]", inputs: ["praxisIconButton", "size", "appearance", "presentation", "pressed", "busy"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3010
3075
  }
3011
3076
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisChartComponent, decorators: [{
3012
3077
  type: Component,
3013
3078
  args: [{ selector: 'praxis-chart', standalone: true, host: {
3014
3079
  '[class.praxis-chart-host-fill-container]': 'isFillContainerMode()',
3080
+ '[style.height]': 'resolvedHeight()',
3081
+ '[style.min-height]': 'resolvedHostMinHeight()',
3082
+ '[style.max-height]': 'resolvedMaxHeight()',
3083
+ '[style.aspect-ratio]': 'resolvedAspectRatio()',
3015
3084
  }, imports: [MatTooltipModule, PraxisIconButtonComponent], changeDetection: ChangeDetectionStrategy.OnPush, template: `
3016
3085
  <section
3017
3086
  class="praxis-chart-shell"
@@ -3044,7 +3113,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
3044
3113
  ></button>
3045
3114
  }
3046
3115
 
3047
- @if (loadState() === 'ready' && accessiblePoints().length) {
3116
+ @if (
3117
+ loadState() === 'ready' &&
3118
+ accessiblePoints().length &&
3119
+ !widgetShellActionHostActive()
3120
+ ) {
3048
3121
  <button
3049
3122
  class="praxis-chart-data-trigger"
3050
3123
  [class.praxis-chart-data-trigger-with-settings]="canOpenConfigEditor()"
@@ -3118,6 +3191,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
3118
3191
  @if (showAccessibleData()) {
3119
3192
  <section
3120
3193
  class="praxis-chart-accessible-data"
3194
+ [class.praxis-chart-accessible-data--shell-controlled]="widgetShellActionHostActive()"
3195
+ [style.background]="accessibleDataSurfaceBackground()"
3121
3196
  [id]="accessibilityPanelId"
3122
3197
  role="region"
3123
3198
  [attr.aria-labelledby]="accessibilityPanelTitleId"
@@ -3157,11 +3232,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
3157
3232
  <div
3158
3233
  #chartHost
3159
3234
  class="praxis-chart-host"
3235
+ [class.praxis-chart-host--data-hidden]="showAccessibleData()"
3160
3236
  [attr.aria-hidden]="showAccessibleData() ? 'true' : null"
3161
3237
  ></div>
3162
3238
  }
3163
3239
  </section>
3164
- `, styles: [":host{display:block;min-height:var(--praxis-chart-runtime-height, 320px);min-width:0;color:var(--md-sys-color-on-surface, #1a1b20)}:host(.praxis-chart-host-fill-container){height:100%;min-height:0}:host-context(.pdx-shell.no-shell) .praxis-chart-shell,:host-context(.pdx-shell.body-fill) .praxis-chart-shell,:host-context(.pdx-shell.expanded) .praxis-chart-shell,:host-context(.pdx-shell.fullscreen) .praxis-chart-shell{height:100%!important}.praxis-chart-shell{position:relative;width:100%;height:100%;min-height:240px;border-radius:var(--praxis-chart-config-surface-radius, var(--praxis-chart-surface-radius, 8px));overflow:hidden;background:var( --praxis-chart-config-surface-bg, var(--praxis-chart-surface-bg, var(--md-sys-color-surface-container-lowest, #fff)) );border-color:var( --praxis-chart-config-surface-border, var( --praxis-chart-surface-border, color-mix(in srgb, var(--md-sys-color-outline, #c5c7ce) 44%, transparent) ) );border-style:solid;border-width:var(--praxis-chart-config-surface-border-width, 1px)}.praxis-chart-shell-fill-container{min-height:0}:host-context(.pdx-shell) .praxis-chart-shell:not(.praxis-chart-shell-contained),.praxis-chart-shell-embedded{border-width:var( --praxis-chart-config-surface-border-width, var(--praxis-chart-embedded-surface-border-width, 0) );border-radius:var( --praxis-chart-config-surface-radius, var(--praxis-chart-embedded-surface-radius, 0) );background:var( --praxis-chart-config-surface-bg, var(--praxis-chart-embedded-surface-bg, transparent) )}.praxis-chart-settings-trigger{position:absolute;top:10px;right:10px;z-index:3;--praxis-icon-button-filled-background: color-mix(in srgb, var(--md-sys-color-surface, #fff) 88%, rgba(18, 99, 180, .12));--praxis-icon-button-filled-foreground: var(--md-sys-color-on-surface-variant, #44474f);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.praxis-chart-data-trigger{position:absolute;top:10px;right:10px;z-index:5;--praxis-icon-button-filled-background: color-mix(in srgb, var(--md-sys-color-surface, #fff) 88%, rgba(18, 99, 180, .12));--praxis-icon-button-filled-foreground: var(--md-sys-color-on-surface-variant, #44474f);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.praxis-chart-data-trigger-with-settings{right:50px}.praxis-chart-accessible-data{position:absolute;inset:0;z-index:4;overflow:auto;padding:52px 16px 16px;color:var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface, #1a1b20));background:var( --praxis-chart-config-surface-bg, var(--praxis-chart-surface-bg, var(--md-sys-color-surface-container-lowest, #fff)) )}.praxis-chart-accessible-data h3{margin:0 0 12px;font-size:1rem;line-height:1.4}.praxis-chart-accessible-data table{width:100%;border-collapse:collapse;font-size:.875rem}.praxis-chart-accessible-data caption{padding:0 0 12px;text-align:left;color:inherit}.praxis-chart-accessible-data th,.praxis-chart-accessible-data td{padding:8px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline, #c5c7ce) 44%,transparent);text-align:left}.praxis-chart-accessible-data thead th{font-weight:600}.praxis-chart-point-action{appearance:none;padding:4px 6px;border:0;border-radius:4px;color:inherit;background:transparent;font:inherit;font-weight:600;text-align:left;text-decoration:underline;text-decoration-thickness:from-font;text-underline-offset:.16em;cursor:pointer}.praxis-chart-point-action:hover{background:color-mix(in srgb,currentColor 10%,transparent)}.praxis-chart-point-action:focus-visible{outline:3px solid currentColor;outline-offset:2px}.praxis-chart-point-action[aria-pressed=true]{color:var(--md-sys-color-on-primary-container, #001b3f);background:var(--md-sys-color-primary-container, #d7e3ff)}.praxis-chart-host{width:100%;height:100%;min-height:inherit}.praxis-chart-state{height:100%;min-height:min(240px,100%);display:grid;align-content:center;justify-items:center;gap:14px;padding:24px;text-align:center}.praxis-chart-state-copy{display:grid;gap:6px;justify-items:center}.praxis-chart-state-title{font-size:1rem;font-weight:600;color:var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface, #1a1b20))}.praxis-chart-state-description{font-size:.925rem;color:color-mix(in srgb,var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface-variant, #5a5d67)) 72%,transparent);max-width:36rem}.praxis-chart-loading-hero{width:min(100%,320px);display:grid;gap:14px}.praxis-chart-loading-summary{display:flex;gap:8px;justify-content:center}.praxis-chart-loading-chip,.praxis-chart-loading-bar{border-radius:999px;background:linear-gradient(90deg,#1263b414,#1263b438,#1263b414);background-size:200% 100%;animation:praxis-chart-loading-wave 1.2s ease-in-out infinite}.praxis-chart-loading-chip{display:block;width:104px;height:12px}.praxis-chart-loading-chip--short{width:64px}.praxis-chart-loading-plot{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));align-items:end;gap:10px;height:108px;padding:12px 8px 4px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container, #eef3f8) 72%,transparent);border:1px solid rgba(18,99,180,.08)}.praxis-chart-loading-bar{display:block;width:100%}.praxis-chart-loading-bar--1{height:32%}.praxis-chart-loading-bar--2{height:68%}.praxis-chart-loading-bar--3{height:48%}.praxis-chart-loading-bar--4{height:78%}.praxis-chart-loading-bar--5{height:56%}@keyframes praxis-chart-loading-wave{0%{background-position:100% 0}to{background-position:-100% 0}}\n"] }]
3240
+ `, styles: [":host{display:block;min-height:var(--praxis-chart-runtime-height, 320px);min-width:0;color:var(--md-sys-color-on-surface, #1a1b20)}:host(.praxis-chart-host-fill-container){height:100%;min-height:0}:host-context(.pdx-shell.no-shell) .praxis-chart-shell,:host-context(.pdx-shell.body-fill) .praxis-chart-shell,:host-context(.pdx-shell.expanded) .praxis-chart-shell,:host-context(.pdx-shell.fullscreen) .praxis-chart-shell{height:100%!important}.praxis-chart-shell{box-sizing:border-box;position:relative;width:100%;height:100%;min-height:240px;border-radius:var(--praxis-chart-config-surface-radius, var(--praxis-chart-surface-radius, 8px));overflow:hidden;background:var( --praxis-chart-config-surface-bg, var(--praxis-chart-surface-bg, var(--md-sys-color-surface-container-lowest, #fff)) );border-color:var( --praxis-chart-config-surface-border, var( --praxis-chart-surface-border, color-mix(in srgb, var(--md-sys-color-outline, #c5c7ce) 44%, transparent) ) );border-style:solid;border-width:var(--praxis-chart-config-surface-border-width, 1px)}.praxis-chart-shell-fill-container{min-height:0}:host-context(.pdx-shell) .praxis-chart-shell:not(.praxis-chart-shell-contained),.praxis-chart-shell-embedded{border-width:var( --praxis-chart-config-surface-border-width, var(--praxis-chart-embedded-surface-border-width, 0) );border-radius:var( --praxis-chart-config-surface-radius, var(--praxis-chart-embedded-surface-radius, 0) );background:var( --praxis-chart-config-surface-bg, var(--praxis-chart-embedded-surface-bg, transparent) )}.praxis-chart-settings-trigger{position:absolute;top:10px;right:10px;z-index:3;--praxis-icon-button-filled-background: color-mix(in srgb, var(--md-sys-color-surface, #fff) 88%, rgba(18, 99, 180, .12));--praxis-icon-button-filled-foreground: var(--md-sys-color-on-surface-variant, #44474f);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.praxis-chart-data-trigger{position:absolute;top:10px;right:10px;z-index:5;--praxis-icon-button-filled-background: color-mix(in srgb, var(--md-sys-color-surface, #fff) 88%, rgba(18, 99, 180, .12));--praxis-icon-button-filled-foreground: var(--md-sys-color-on-surface-variant, #44474f);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.praxis-chart-data-trigger-with-settings{right:50px}.praxis-chart-accessible-data{position:absolute;inset:0;z-index:4;overflow:auto;padding:52px 16px 16px;color:var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface, #1a1b20));background:var(--md-sys-color-surface-container-lowest, #fff)}.praxis-chart-accessible-data--shell-controlled{padding-top:16px}.praxis-chart-accessible-data h3{margin:0 0 12px;font-size:1rem;line-height:1.4}.praxis-chart-accessible-data table{width:100%;border-collapse:collapse;font-size:.875rem}.praxis-chart-accessible-data caption{padding:0 0 12px;text-align:left;color:inherit}.praxis-chart-accessible-data th,.praxis-chart-accessible-data td{padding:8px;border-bottom:1px solid color-mix(in srgb,var(--md-sys-color-outline, #c5c7ce) 44%,transparent);text-align:left}.praxis-chart-accessible-data thead th{font-weight:600}.praxis-chart-point-action{appearance:none;padding:4px 6px;border:0;border-radius:4px;color:inherit;background:transparent;font:inherit;font-weight:600;text-align:left;text-decoration:underline;text-decoration-thickness:from-font;text-underline-offset:.16em;cursor:pointer}.praxis-chart-point-action:hover{background:color-mix(in srgb,currentColor 10%,transparent)}.praxis-chart-point-action:focus-visible{outline:3px solid currentColor;outline-offset:2px}.praxis-chart-point-action[aria-pressed=true]{color:var(--md-sys-color-on-primary-container, #001b3f);background:var(--md-sys-color-primary-container, #d7e3ff)}.praxis-chart-host{width:100%;height:100%;min-height:inherit}.praxis-chart-host--data-hidden{visibility:hidden;pointer-events:none}.praxis-chart-state{height:100%;min-height:min(240px,100%);display:grid;align-content:center;justify-items:center;gap:14px;padding:24px;text-align:center}.praxis-chart-state-copy{display:grid;gap:6px;justify-items:center}.praxis-chart-state-title{font-size:1rem;font-weight:600;color:var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface, #1a1b20))}.praxis-chart-state-description{font-size:.925rem;color:color-mix(in srgb,var(--praxis-chart-config-text-color, var(--md-sys-color-on-surface-variant, #5a5d67)) 72%,transparent);max-width:36rem}.praxis-chart-loading-hero{width:min(100%,320px);display:grid;gap:14px}.praxis-chart-loading-summary{display:flex;gap:8px;justify-content:center}.praxis-chart-loading-chip,.praxis-chart-loading-bar{border-radius:999px;background:linear-gradient(90deg,#1263b414,#1263b438,#1263b414);background-size:200% 100%;animation:praxis-chart-loading-wave 1.2s ease-in-out infinite}.praxis-chart-loading-chip{display:block;width:104px;height:12px}.praxis-chart-loading-chip--short{width:64px}.praxis-chart-loading-plot{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));align-items:end;gap:10px;height:108px;padding:12px 8px 4px;border-radius:8px;background:color-mix(in srgb,var(--md-sys-color-surface-container, #eef3f8) 72%,transparent);border:1px solid rgba(18,99,180,.08)}.praxis-chart-loading-bar{display:block;width:100%}.praxis-chart-loading-bar--1{height:32%}.praxis-chart-loading-bar--2{height:68%}.praxis-chart-loading-bar--3{height:48%}.praxis-chart-loading-bar--4{height:78%}.praxis-chart-loading-bar--5{height:56%}@keyframes praxis-chart-loading-wave{0%{background-position:100% 0}to{background-position:-100% 0}}\n"] }]
3165
3241
  }], ctorParameters: () => [], propDecorators: { config: [{ type: i0.Input, args: [{ isSignal: true, alias: "config", required: false }] }], data: [{ type: i0.Input, args: [{ isSignal: true, alias: "data", required: false }] }], chartDocument: [{ type: i0.Input, args: [{ isSignal: true, alias: "chartDocument", required: false }] }], filterCriteria: [{ type: i0.Input, args: [{ isSignal: true, alias: "filterCriteria", required: false }] }], queryContext: [{ type: i0.Input, args: [{ isSignal: true, alias: "queryContext", required: false }] }], remoteDataResolver: [{ type: i0.Input, args: [{ isSignal: true, alias: "remoteDataResolver", required: false }] }], enableCustomization: [{ type: i0.Input, args: [{ isSignal: true, alias: "enableCustomization", required: false }] }], availableResources: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableResources", required: false }] }], availableFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableFields", required: false }] }], availableTargets: [{ type: i0.Input, args: [{ isSignal: true, alias: "availableTargets", required: false }] }], pointClick: [{ type: i0.Output, args: ["pointClick"] }], pointAction: [{ type: i0.Output, args: ["pointAction"] }], selectionChange: [{ type: i0.Output, args: ["selectionChange"] }], drillDown: [{ type: i0.Output, args: ["drillDown"] }], crossFilter: [{ type: i0.Output, args: ["crossFilter"] }], queryRequest: [{ type: i0.Output, args: ["queryRequest"] }], loadStateChange: [{ type: i0.Output, args: ["loadStateChange"] }], chartDocumentApplied: [{ type: i0.Output, args: ["chartDocumentApplied"] }], chartDocumentSaved: [{ type: i0.Output, args: ["chartDocumentSaved"] }], chartDocumentPatchChange: [{ type: i0.Output, args: ["chartDocumentPatchChange"] }], chartHost: [{ type: i0.ViewChild, args: ['chartHost', { isSignal: true }] }] } });
3166
3242
  function mergeRemoteQueryContext(config, queryContext, runtimeFilters) {
3167
3243
  const dataSource = config.dataSource;
@@ -4651,7 +4727,9 @@ class PraxisAnalyticsPresentationComponent {
4651
4727
  const resolved = this.resolved();
4652
4728
  const queryContext = this.queryContext();
4653
4729
  const generation = ++this.resultRequestGeneration;
4730
+ let resultSubscription;
4654
4731
  onCleanup(() => {
4732
+ resultSubscription?.unsubscribe();
4655
4733
  if (this.resultRequestGeneration === generation) {
4656
4734
  this.resultRequestGeneration += 1;
4657
4735
  }
@@ -4663,17 +4741,20 @@ class PraxisAnalyticsPresentationComponent {
4663
4741
  return;
4664
4742
  }
4665
4743
  this.resultState.set('loading');
4666
- void this.tableStats.execute(resolved.projection, queryContext).then((rows) => {
4667
- if (this.resultRequestGeneration !== generation)
4668
- return;
4669
- this.resultRows.set(rows);
4670
- this.resultState.set('ready');
4671
- }, () => {
4672
- if (this.resultRequestGeneration !== generation)
4673
- return;
4674
- this.resultRows.set([]);
4675
- this.resultState.set('error');
4676
- this.resultDiagnostic.set(this.t('praxis.charts.analyticsPresentation.loadError', 'Analytics data could not be loaded.'));
4744
+ resultSubscription = this.tableStats.execute(resolved.projection, queryContext).subscribe({
4745
+ next: (rows) => {
4746
+ if (this.resultRequestGeneration !== generation)
4747
+ return;
4748
+ this.resultRows.set(rows);
4749
+ this.resultState.set('ready');
4750
+ },
4751
+ error: () => {
4752
+ if (this.resultRequestGeneration !== generation)
4753
+ return;
4754
+ this.resultRows.set([]);
4755
+ this.resultState.set('error');
4756
+ this.resultDiagnostic.set(this.t('praxis.charts.analyticsPresentation.loadError', 'Analytics data could not be loaded.'));
4757
+ },
4677
4758
  });
4678
4759
  });
4679
4760
  }
@@ -4908,12 +4989,17 @@ class EChartsOptionBuilderService {
4908
4989
  if (transformed.mode === 'pie') {
4909
4990
  const hasChartTitle = this.hasText(config.title) || this.hasText(config.subtitle);
4910
4991
  const labelsVisible = config.series[0]?.labels?.visible ?? transformed.slices.length <= 4;
4992
+ const titledRadius = config.type === 'donut'
4993
+ ? labelsVisible ? ['32%', '52%'] : ['38%', '56%']
4994
+ : labelsVisible ? '52%' : '56%';
4911
4995
  const pieSeries = {
4912
4996
  type: 'pie',
4913
- radius: config.type === 'donut'
4914
- ? labelsVisible ? ['32%', '52%'] : ['42%', '64%']
4915
- : labelsVisible ? '54%' : '66%',
4916
- center: ['50%', hasChartTitle ? '54%' : '50%'],
4997
+ radius: hasChartTitle
4998
+ ? titledRadius
4999
+ : config.type === 'donut'
5000
+ ? labelsVisible ? ['32%', '52%'] : ['42%', '64%']
5001
+ : labelsVisible ? '54%' : '66%',
5002
+ center: ['50%', hasChartTitle ? '58%' : '50%'],
4917
5003
  avoidLabelOverlap: true,
4918
5004
  label: {
4919
5005
  show: labelsVisible,
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@praxisui/charts",
3
- "version": "9.0.62",
3
+ "version": "9.0.63",
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": "^9.0.62",
8
+ "@praxisui/core": "^9.0.63",
9
9
  "@angular/forms": "^21.0.0",
10
10
  "@angular/material": "^21.0.0",
11
- "@praxisui/table": "^9.0.62",
11
+ "@praxisui/table": "^9.0.63",
12
12
  "rxjs": "~7.8.0"
13
13
  },
14
14
  "dependencies": {
@@ -2,7 +2,7 @@ import * as _praxisui_charts from '@praxisui/charts';
2
2
  import * as _angular_core from '@angular/core';
3
3
  import { InjectionToken, Provider, OnChanges, OnDestroy, SimpleChanges } from '@angular/core';
4
4
  import * as _praxisui_core from '@praxisui/core';
5
- import { PraxisAnalyticsComparisonStatsRequest, PraxisDataQueryContext, PraxisTextValue, PraxisPresentationVisualizationConfig, PraxisPresentationVisualizationPoint, PraxisPresentationVisualizationSegment, PraxisPresentationVisualizationThreshold, AnalyticsPresentationFamily, PraxisXUiAnalytics, PraxisAnalyticsProjection, WidgetDefinition, WidgetShellConfig, WidgetInstance, PraxisI18nService, ApiUrlConfig, AnalyticsSchemaContractService, AnalyticsPresentationResolver, WidgetPageDefinition, SettingsValueProvider, ComponentConfigEditorContextResult, ResourceCapabilitySnapshot, PraxisI18nDictionary, PraxisI18nConfig, PraxisI18nMessageDescriptor, ComponentAuthoringManifest, ComponentDocMeta } from '@praxisui/core';
5
+ import { PraxisAnalyticsComparisonStatsRequest, PraxisDataQueryContext, PraxisTextValue, WidgetShellActionContributor, WidgetShellAction, WidgetShellActionEvent, PraxisPresentationVisualizationConfig, PraxisPresentationVisualizationPoint, PraxisPresentationVisualizationSegment, PraxisPresentationVisualizationThreshold, AnalyticsPresentationFamily, PraxisXUiAnalytics, PraxisAnalyticsProjection, WidgetDefinition, WidgetShellConfig, WidgetInstance, PraxisI18nService, ApiUrlConfig, AnalyticsSchemaContractService, AnalyticsPresentationResolver, WidgetPageDefinition, SettingsValueProvider, ComponentConfigEditorContextResult, ResourceCapabilitySnapshot, PraxisI18nDictionary, PraxisI18nConfig, PraxisI18nMessageDescriptor, ComponentAuthoringManifest, ComponentDocMeta } from '@praxisui/core';
6
6
  import { Observable, BehaviorSubject } from 'rxjs';
7
7
  import { AnalyticsTableRow } from '@praxisui/table';
8
8
  import { HttpClient } from '@angular/common/http';
@@ -558,7 +558,7 @@ interface PraxisChartAccessiblePoint extends PraxisChartPointEvent {
558
558
  seriesLabel: string;
559
559
  valueLabel: string;
560
560
  }
561
- declare class PraxisChartComponent {
561
+ declare class PraxisChartComponent implements WidgetShellActionContributor {
562
562
  readonly config: _angular_core.InputSignal<PraxisChartConfig>;
563
563
  readonly data: _angular_core.InputSignal<PraxisChartDataRow[] | null>;
564
564
  readonly chartDocument: _angular_core.InputSignal<PraxisXUiChartContract | null>;
@@ -606,6 +606,7 @@ declare class PraxisChartComponent {
606
606
  private readonly activeSelectionSignature;
607
607
  protected readonly configEditorContextPending: _angular_core.WritableSignal<boolean>;
608
608
  readonly showAccessibleData: _angular_core.WritableSignal<boolean>;
609
+ readonly widgetShellActionHostActive: _angular_core.WritableSignal<boolean>;
609
610
  readonly accessibilityPanelId: string;
610
611
  readonly accessibilityPanelTitleId: string;
611
612
  private readonly fillContainerHeight;
@@ -625,6 +626,7 @@ declare class PraxisChartComponent {
625
626
  readonly resolvedData: _angular_core.Signal<PraxisChartDataRow[]>;
626
627
  readonly resolvedHeight: _angular_core.Signal<string>;
627
628
  readonly resolvedMinHeight: _angular_core.Signal<string | null>;
629
+ readonly resolvedHostMinHeight: _angular_core.Signal<string>;
628
630
  readonly resolvedMaxHeight: _angular_core.Signal<string | null>;
629
631
  readonly resolvedAspectRatio: _angular_core.Signal<string | null>;
630
632
  readonly isFillContainerMode: _angular_core.Signal<boolean>;
@@ -634,6 +636,7 @@ declare class PraxisChartComponent {
634
636
  readonly surfaceBorderWidth: _angular_core.Signal<string | null>;
635
637
  readonly surfaceBorderRadius: _angular_core.Signal<string | null>;
636
638
  readonly surfaceTextColor: _angular_core.Signal<string | null>;
639
+ readonly accessibleDataSurfaceBackground: _angular_core.Signal<string>;
637
640
  readonly renderConfig: _angular_core.Signal<PraxisChartConfig>;
638
641
  readonly loadingLabel: _angular_core.Signal<string>;
639
642
  readonly loadingDescription: _angular_core.Signal<string>;
@@ -651,6 +654,7 @@ declare class PraxisChartComponent {
651
654
  readonly accessibleCategoryHeading: _angular_core.Signal<string>;
652
655
  readonly accessibleSeriesHeading: _angular_core.Signal<string>;
653
656
  readonly accessibleValueHeading: _angular_core.Signal<string>;
657
+ readonly widgetShellActions: _angular_core.Signal<readonly WidgetShellAction[]>;
654
658
  readonly loadState: _angular_core.Signal<PraxisChartLoadState>;
655
659
  constructor();
656
660
  private resolveDataDiagnosticDescription;
@@ -666,6 +670,8 @@ declare class PraxisChartComponent {
666
670
  private asRecord;
667
671
  private handlePointClick;
668
672
  toggleAccessibleData(): void;
673
+ setWidgetShellActionHostActive(active: boolean): void;
674
+ handleShellAction(action: WidgetShellActionEvent): void;
669
675
  activateAccessiblePoint(point: PraxisChartAccessiblePoint): void;
670
676
  accessiblePointPressed(point: PraxisChartAccessiblePoint): string | null;
671
677
  accessiblePointActionLabel(point: PraxisChartAccessiblePoint): string;