@praxisui/charts 9.0.0-beta.7 → 9.0.0-beta.71

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,7 +1,7 @@
1
1
  import * as i0 from '@angular/core';
2
2
  import { Injectable, Inject, InjectionToken, input, booleanAttribute, output, viewChild, inject, ElementRef, NgZone, DestroyRef, signal, computed, afterNextRender, effect, ChangeDetectionStrategy, Component, ViewChild, Input, ENVIRONMENT_INITIALIZER } from '@angular/core';
3
3
  import * as i1$1 from '@praxisui/core';
4
- import { buildApiUrl, API_URL, PraxisI18nService, SETTINGS_PANEL_BRIDGE, providePraxisI18n, SETTINGS_PANEL_DATA, ComponentMetadataRegistry, createDefaultTableConfig, AnalyticsStatsRequestBuilderService, DynamicWidgetPageComponent } from '@praxisui/core';
4
+ import { buildApiUrl, API_URL, PraxisI18nService, SETTINGS_PANEL_BRIDGE, normalizePraxisPresentationVisualization, providePraxisI18n, SETTINGS_PANEL_DATA, ComponentMetadataRegistry, createDefaultTableConfig, PRAXIS_TABLE_DETAIL_INLINE_RENDERERS, AnalyticsStatsRequestBuilderService, DynamicWidgetPageComponent } from '@praxisui/core';
5
5
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
6
6
  import { throwError, map, of, isObservable, from, BehaviorSubject, Subscription } from 'rxjs';
7
7
  import * as i1$2 from '@angular/material/button';
@@ -2263,7 +2263,13 @@ class PraxisChartComponent {
2263
2263
  const dataSource = config.dataSource;
2264
2264
  const explicitData = this.data();
2265
2265
  if (dataSource?.kind === 'remote' && (explicitData === null || explicitData === undefined)) {
2266
- return this.remoteRuntimeState() === 'ready' ? 'ready' : 'loading';
2266
+ const remoteState = this.remoteRuntimeState();
2267
+ if (remoteState === 'error') {
2268
+ return 'error';
2269
+ }
2270
+ if (remoteState !== 'ready') {
2271
+ return 'loading';
2272
+ }
2267
2273
  }
2268
2274
  const transformed = this.transformer.transform(config, this.resolvedData());
2269
2275
  return transformed.hasData ? 'ready' : 'empty';
@@ -2929,6 +2935,915 @@ function normalizeRemoteDataResolverResult$1(result) {
2929
2935
  return of([]);
2930
2936
  }
2931
2937
 
2938
+ const SUPPORTED_KINDS = new Set([
2939
+ 'comparison',
2940
+ 'stackedBar',
2941
+ 'bullet',
2942
+ 'delta',
2943
+ 'radial',
2944
+ 'harveyBall',
2945
+ 'line',
2946
+ 'area',
2947
+ 'column',
2948
+ 'processFlow',
2949
+ ]);
2950
+ class PraxisMicroVisualizationComponent {
2951
+ visualizationInput = input(null, { ...(ngDevMode ? { debugName: "visualizationInput" } : /* istanbul ignore next */ {}), alias: 'visualization' });
2952
+ fallbackInput = input('', { ...(ngDevMode ? { debugName: "fallbackInput" } : /* istanbul ignore next */ {}), alias: 'fallbackText' });
2953
+ visualization = computed(() => {
2954
+ const normalized = normalizePraxisPresentationVisualization(this.visualizationInput());
2955
+ return normalized && SUPPORTED_KINDS.has(normalized.kind)
2956
+ ? normalized
2957
+ : null;
2958
+ }, ...(ngDevMode ? [{ debugName: "visualization" }] : /* istanbul ignore next */ []));
2959
+ fallbackText = computed(() => this.visualizationInput()?.fallbackText?.trim() || this.fallbackInput().trim(), ...(ngDevMode ? [{ debugName: "fallbackText" }] : /* istanbul ignore next */ []));
2960
+ kind = computed(() => this.visualization()?.kind ?? 'fallback', ...(ngDevMode ? [{ debugName: "kind" }] : /* istanbul ignore next */ []));
2961
+ surface = computed(() => this.visualization()?.surface ?? null, ...(ngDevMode ? [{ debugName: "surface" }] : /* istanbul ignore next */ []));
2962
+ size = computed(() => this.visualization()?.size ?? null, ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
2963
+ isTableCell = computed(() => this.surface() === 'table-cell', ...(ngDevMode ? [{ debugName: "isTableCell" }] : /* istanbul ignore next */ []));
2964
+ ariaLabel = computed(() => {
2965
+ const config = this.visualization();
2966
+ return config?.ariaLabel || config?.fallbackText || null;
2967
+ }, ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
2968
+ comparisonItems = computed(() => this.visualization()?.points ?? [], ...(ngDevMode ? [{ debugName: "comparisonItems" }] : /* istanbul ignore next */ []));
2969
+ stackedSegments = computed(() => this.visualization()?.segments ?? [], ...(ngDevMode ? [{ debugName: "stackedSegments" }] : /* istanbul ignore next */ []));
2970
+ bulletThresholds = computed(() => this.visualization()?.thresholds ?? [], ...(ngDevMode ? [{ debugName: "bulletThresholds" }] : /* istanbul ignore next */ []));
2971
+ bulletBands = computed(() => {
2972
+ const max = this.resolveBulletMax();
2973
+ let previous = 0;
2974
+ return this.bulletThresholds()
2975
+ .map((threshold) => {
2976
+ const current = Math.max(threshold.value, previous);
2977
+ const left = max > 0 ? clampPercent((previous / max) * 100) : 0;
2978
+ const width = max > 0 ? clampPercent(((current - previous) / max) * 100) : 0;
2979
+ previous = current;
2980
+ return {
2981
+ ...(threshold.label ? { label: threshold.label } : {}),
2982
+ ...(threshold.tone ? { tone: threshold.tone } : {}),
2983
+ left,
2984
+ width,
2985
+ };
2986
+ })
2987
+ .filter((band) => band.width > 0);
2988
+ }, ...(ngDevMode ? [{ debugName: "bulletBands" }] : /* istanbul ignore next */ []));
2989
+ deltaValue = computed(() => {
2990
+ const value = this.visualization()?.value;
2991
+ return typeof value === 'number' && Number.isFinite(value) ? value : 0;
2992
+ }, ...(ngDevMode ? [{ debugName: "deltaValue" }] : /* istanbul ignore next */ []));
2993
+ deltaText = computed(() => {
2994
+ const config = this.visualization();
2995
+ if (!config) {
2996
+ return '';
2997
+ }
2998
+ return config.fallbackText || this.formatNumber(this.deltaValue());
2999
+ }, ...(ngDevMode ? [{ debugName: "deltaText" }] : /* istanbul ignore next */ []));
3000
+ deltaIcon = computed(() => {
3001
+ const fallbackText = this.visualization()?.fallbackText?.trim() ?? '';
3002
+ if (/^[+-]/.test(fallbackText)) {
3003
+ return '';
3004
+ }
3005
+ const value = this.deltaValue();
3006
+ if (value > 0) {
3007
+ return '+';
3008
+ }
3009
+ if (value < 0) {
3010
+ return '-';
3011
+ }
3012
+ return '';
3013
+ }, ...(ngDevMode ? [{ debugName: "deltaIcon" }] : /* istanbul ignore next */ []));
3014
+ itemPercent(value) {
3015
+ if (!Number.isFinite(value)) {
3016
+ return 0;
3017
+ }
3018
+ const values = this.comparisonItems()
3019
+ .map((item) => item.value)
3020
+ .filter((itemValue) => Number.isFinite(itemValue));
3021
+ const max = Math.max(...values, 0);
3022
+ return max > 0 ? clampPercent((value / max) * 100) : 0;
3023
+ }
3024
+ segmentPercent(value) {
3025
+ const total = this.stackedSegments()
3026
+ .reduce((sum, segment) => sum + Math.max(segment.value, 0), 0);
3027
+ return total > 0 ? clampPercent((Math.max(value, 0) / total) * 100) : 0;
3028
+ }
3029
+ valuePercent(value) {
3030
+ const max = this.resolveBulletMax();
3031
+ return typeof value === 'number' && max > 0 ? clampPercent((Math.max(value, 0) / max) * 100) : 0;
3032
+ }
3033
+ formatNumber(value) {
3034
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
3035
+ return '';
3036
+ }
3037
+ return new Intl.NumberFormat(undefined, {
3038
+ maximumFractionDigits: Math.abs(value) < 10 ? 2 : 0,
3039
+ }).format(value);
3040
+ }
3041
+ radialPercent = computed(() => {
3042
+ const config = this.visualization();
3043
+ if (!config)
3044
+ return 0;
3045
+ const val = typeof config.value === 'number' ? config.value : 0;
3046
+ const total = config.total && config.total > 0 ? config.total : 100;
3047
+ return clampPercent((val / total) * 100);
3048
+ }, ...(ngDevMode ? [{ debugName: "radialPercent" }] : /* istanbul ignore next */ []));
3049
+ radialDashArray = computed(() => {
3050
+ return `${this.radialPercent().toFixed(1)}, 100`;
3051
+ }, ...(ngDevMode ? [{ debugName: "radialDashArray" }] : /* istanbul ignore next */ []));
3052
+ radialText = computed(() => `${Math.round(this.radialPercent())}%`, ...(ngDevMode ? [{ debugName: "radialText" }] : /* istanbul ignore next */ []));
3053
+ harveyPercent = computed(() => {
3054
+ const config = this.visualization();
3055
+ if (!config)
3056
+ return 0;
3057
+ const val = typeof config.value === 'number' ? config.value : 0;
3058
+ const total = config.total && config.total > 0 ? config.total : 100;
3059
+ return clampPercent((val / total) * 100);
3060
+ }, ...(ngDevMode ? [{ debugName: "harveyPercent" }] : /* istanbul ignore next */ []));
3061
+ harveyDashArray = computed(() => {
3062
+ const len = this.harveyPercent() * 0.50265;
3063
+ return `${len.toFixed(3)} 50.265`;
3064
+ }, ...(ngDevMode ? [{ debugName: "harveyDashArray" }] : /* istanbul ignore next */ []));
3065
+ harveyText = computed(() => `${Math.round(this.harveyPercent())}%`, ...(ngDevMode ? [{ debugName: "harveyText" }] : /* istanbul ignore next */ []));
3066
+ firstPoint = computed(() => {
3067
+ const points = this.visualization()?.points ?? [];
3068
+ return points.length > 0 ? points[0] : null;
3069
+ }, ...(ngDevMode ? [{ debugName: "firstPoint" }] : /* istanbul ignore next */ []));
3070
+ lastPoint = computed(() => {
3071
+ const points = this.visualization()?.points ?? [];
3072
+ return points.length > 0 ? points[points.length - 1] : null;
3073
+ }, ...(ngDevMode ? [{ debugName: "lastPoint" }] : /* istanbul ignore next */ []));
3074
+ minPointIndex = computed(() => {
3075
+ const points = this.visualization()?.points ?? [];
3076
+ if (points.length === 0)
3077
+ return -1;
3078
+ let minIdx = 0;
3079
+ for (let i = 1; i < points.length; i++) {
3080
+ if (points[i].value < points[minIdx].value) {
3081
+ minIdx = i;
3082
+ }
3083
+ }
3084
+ return minIdx;
3085
+ }, ...(ngDevMode ? [{ debugName: "minPointIndex" }] : /* istanbul ignore next */ []));
3086
+ maxPointIndex = computed(() => {
3087
+ const points = this.visualization()?.points ?? [];
3088
+ if (points.length === 0)
3089
+ return -1;
3090
+ let maxIdx = 0;
3091
+ for (let i = 1; i < points.length; i++) {
3092
+ if (points[i].value > points[maxIdx].value) {
3093
+ maxIdx = i;
3094
+ }
3095
+ }
3096
+ return maxIdx;
3097
+ }, ...(ngDevMode ? [{ debugName: "maxPointIndex" }] : /* istanbul ignore next */ []));
3098
+ trendMarkers = computed(() => {
3099
+ const coords = this.trendCoords();
3100
+ const points = this.visualization()?.points ?? [];
3101
+ if (coords.length === 0)
3102
+ return [];
3103
+ const markers = [];
3104
+ const minIdx = this.minPointIndex();
3105
+ const maxIdx = this.maxPointIndex();
3106
+ const tone = this.visualization()?.tone ?? 'info';
3107
+ // Add first point
3108
+ markers.push({
3109
+ x: coords[0].x,
3110
+ y: coords[0].y,
3111
+ tone: points[0].tone ?? tone,
3112
+ label: `First: ${points[0].value}`,
3113
+ });
3114
+ // Add last point
3115
+ if (coords.length > 1) {
3116
+ markers.push({
3117
+ x: coords[coords.length - 1].x,
3118
+ y: coords[coords.length - 1].y,
3119
+ tone: points[points.length - 1].tone ?? tone,
3120
+ label: `Last: ${points[points.length - 1].value}`,
3121
+ });
3122
+ }
3123
+ // Add min point (if not first/last)
3124
+ if (minIdx !== 0 && minIdx !== coords.length - 1 && minIdx !== -1) {
3125
+ markers.push({
3126
+ x: coords[minIdx].x,
3127
+ y: coords[minIdx].y,
3128
+ tone: points[minIdx].tone ?? 'danger',
3129
+ label: `Min: ${points[minIdx].value}`,
3130
+ });
3131
+ }
3132
+ // Add max point (if not first/last)
3133
+ if (maxIdx !== 0 && maxIdx !== coords.length - 1 && maxIdx !== -1) {
3134
+ markers.push({
3135
+ x: coords[maxIdx].x,
3136
+ y: coords[maxIdx].y,
3137
+ tone: points[maxIdx].tone ?? 'success',
3138
+ label: `Max: ${points[maxIdx].value}`,
3139
+ });
3140
+ }
3141
+ return markers;
3142
+ }, ...(ngDevMode ? [{ debugName: "trendMarkers" }] : /* istanbul ignore next */ []));
3143
+ trendCoords = computed(() => {
3144
+ const config = this.visualization();
3145
+ const points = config?.points ?? [];
3146
+ if (points.length < 2)
3147
+ return [];
3148
+ const width = 100;
3149
+ const height = 30;
3150
+ const padding = 4;
3151
+ const values = points.map(p => p.value);
3152
+ const minVal = Math.min(...values);
3153
+ const maxVal = Math.max(...values);
3154
+ const valRange = maxVal - minVal === 0 ? 1 : maxVal - minVal;
3155
+ return points.map((p, index) => {
3156
+ const x = padding + (index / (points.length - 1)) * (width - 2 * padding);
3157
+ const y = height - padding - ((p.value - minVal) / valRange) * (height - 2 * padding);
3158
+ return { x, y };
3159
+ });
3160
+ }, ...(ngDevMode ? [{ debugName: "trendCoords" }] : /* istanbul ignore next */ []));
3161
+ trendPathD = computed(() => {
3162
+ const coords = this.trendCoords();
3163
+ if (coords.length < 2)
3164
+ return '';
3165
+ return coords.map((c, i) => `${i === 0 ? 'M' : 'L'} ${c.x.toFixed(1)} ${c.y.toFixed(1)}`).join(' ');
3166
+ }, ...(ngDevMode ? [{ debugName: "trendPathD" }] : /* istanbul ignore next */ []));
3167
+ trendAreaD = computed(() => {
3168
+ const pathD = this.trendPathD();
3169
+ const coords = this.trendCoords();
3170
+ if (!pathD || coords.length < 2)
3171
+ return '';
3172
+ const height = 30;
3173
+ const firstX = coords[0].x.toFixed(1);
3174
+ const lastX = coords[coords.length - 1].x.toFixed(1);
3175
+ return `${pathD} L ${lastX} ${height} L ${firstX} ${height} Z`;
3176
+ }, ...(ngDevMode ? [{ debugName: "trendAreaD" }] : /* istanbul ignore next */ []));
3177
+ trendColumns = computed(() => {
3178
+ const config = this.visualization();
3179
+ const points = config?.points ?? [];
3180
+ if (points.length === 0)
3181
+ return [];
3182
+ const width = 100;
3183
+ const height = 30;
3184
+ const padding = 4;
3185
+ const values = points.map(p => p.value);
3186
+ const maxVal = Math.max(...values, 0);
3187
+ const minVal = Math.min(...values, 0);
3188
+ const valRange = maxVal - minVal === 0 ? 1 : maxVal - minVal;
3189
+ const colWidth = Math.max(2, (width - 2 * padding) / points.length - 2);
3190
+ const tone = config?.tone ?? 'info';
3191
+ return points.map((p, i) => {
3192
+ const x = padding + i * ((width - 2 * padding) / points.length) + 1;
3193
+ const rectHeight = Math.max(2, ((p.value - minVal) / valRange) * (height - 2 * padding));
3194
+ const rectY = height - padding - rectHeight;
3195
+ return {
3196
+ x: x.toFixed(1),
3197
+ y: rectY.toFixed(1),
3198
+ width: colWidth.toFixed(1),
3199
+ height: rectHeight.toFixed(1),
3200
+ tone: p.tone ?? tone,
3201
+ };
3202
+ });
3203
+ }, ...(ngDevMode ? [{ debugName: "trendColumns" }] : /* istanbul ignore next */ []));
3204
+ processSteps = computed(() => {
3205
+ const config = this.visualization();
3206
+ return config?.items ?? [];
3207
+ }, ...(ngDevMode ? [{ debugName: "processSteps" }] : /* istanbul ignore next */ []));
3208
+ resolveBulletMax() {
3209
+ const config = this.visualization();
3210
+ const values = [
3211
+ typeof config?.value === 'number' ? config.value : 0,
3212
+ config?.target ?? 0,
3213
+ config?.total ?? 0,
3214
+ ...this.bulletThresholds().map((threshold) => threshold.value),
3215
+ ].filter((value) => Number.isFinite(value) && value > 0);
3216
+ return Math.max(...values, 100);
3217
+ }
3218
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisMicroVisualizationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3219
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PraxisMicroVisualizationComponent, isStandalone: true, selector: "praxis-micro-visualization", inputs: { visualizationInput: { classPropertyName: "visualizationInput", publicName: "visualization", isSignal: true, isRequired: false, transformFunction: null }, fallbackInput: { classPropertyName: "fallbackInput", publicName: "fallbackText", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "attr.data-kind": "kind()", "attr.data-surface": "surface()", "attr.data-size": "size()", "class.prx-micro-visualization--table-cell": "surface() === \"table-cell\"" } }, ngImport: i0, template: `
3220
+ @if (visualization(); as config) {
3221
+ <figure
3222
+ class="prx-micro-visualization"
3223
+ [attr.aria-label]="ariaLabel()"
3224
+ role="img"
3225
+ >
3226
+ @switch (config.kind) {
3227
+ @case ('comparison') {
3228
+ <div class="prx-micro-comparison">
3229
+ @for (item of comparisonItems(); track item.label ?? $index) {
3230
+ <div class="prx-micro-comparison__row">
3231
+ @if (item.label) {
3232
+ <span class="prx-micro-comparison__label">{{ item.label }}</span>
3233
+ }
3234
+ <span class="prx-micro-comparison__track" aria-hidden="true">
3235
+ <span
3236
+ class="prx-micro-comparison__bar"
3237
+ [attr.data-tone]="item.tone || null"
3238
+ [style.width.%]="itemPercent(item.value)"
3239
+ ></span>
3240
+ </span>
3241
+ @if (item.value !== undefined) {
3242
+ <span class="prx-micro-comparison__value">{{ formatNumber(item.value) }}</span>
3243
+ }
3244
+ </div>
3245
+ }
3246
+ </div>
3247
+ }
3248
+
3249
+ @case ('stackedBar') {
3250
+ <div class="prx-micro-stacked">
3251
+ <div class="prx-micro-stacked__track" aria-hidden="true">
3252
+ @for (segment of stackedSegments(); track segment.label ?? $index) {
3253
+ <span
3254
+ class="prx-micro-stacked__segment"
3255
+ [attr.data-tone]="segment.tone || null"
3256
+ [style.width.%]="segmentPercent(segment.value)"
3257
+ ></span>
3258
+ }
3259
+ </div>
3260
+ @if (!isTableCell() && config.fallbackText) {
3261
+ <figcaption class="prx-micro-visualization__caption">{{ config.fallbackText }}</figcaption>
3262
+ }
3263
+ </div>
3264
+ }
3265
+
3266
+ @case ('bullet') {
3267
+ <div class="prx-micro-bullet-container">
3268
+ @if (!isTableCell()) {
3269
+ <div class="prx-micro-bullet__top">
3270
+ <span class="prx-micro-bullet__label">{{ config.fallbackText }}</span>
3271
+ <span class="prx-micro-bullet__value" [attr.data-tone]="config.tone || null">
3272
+ {{ formatNumber(config.value) }}
3273
+ @if (config.target !== undefined) {
3274
+ <span class="prx-micro-bullet__target-val">/ Target: {{ formatNumber(config.target) }}</span>
3275
+ }
3276
+ </span>
3277
+ </div>
3278
+ }
3279
+
3280
+ <div class="prx-micro-bullet__track" aria-hidden="true">
3281
+ @for (band of bulletBands(); track band.label ?? $index) {
3282
+ <span
3283
+ class="prx-micro-bullet__range"
3284
+ [attr.data-tone]="band.tone || null"
3285
+ [style.left.%]="band.left"
3286
+ [style.width.%]="band.width"
3287
+ ></span>
3288
+ }
3289
+ <span
3290
+ class="prx-micro-bullet__actual"
3291
+ [attr.data-tone]="config.tone || null"
3292
+ [style.width.%]="valuePercent(config.value)"
3293
+ ></span>
3294
+ @if (config.target !== undefined) {
3295
+ <span
3296
+ class="prx-micro-bullet__target"
3297
+ [style.left.%]="valuePercent(config.target)"
3298
+ ></span>
3299
+ }
3300
+ </div>
3301
+
3302
+ @if (!isTableCell()) {
3303
+ <div class="prx-micro-bullet__bottom">
3304
+ <span class="prx-micro-bullet__scale-min">{{ formatNumber(config.baseline ?? 0) }}</span>
3305
+ <span class="prx-micro-bullet__scale-max">{{ formatNumber(config.total ?? 100) }}</span>
3306
+ </div>
3307
+ }
3308
+ </div>
3309
+ }
3310
+
3311
+ @case ('delta') {
3312
+ <div
3313
+ class="prx-micro-delta"
3314
+ [class.prx-micro-delta--positive]="deltaValue() > 0"
3315
+ [class.prx-micro-delta--negative]="deltaValue() < 0"
3316
+ >
3317
+ @if (deltaIcon(); as icon) {
3318
+ <span class="prx-micro-delta__icon" aria-hidden="true">{{ icon }}</span>
3319
+ }
3320
+ <span class="prx-micro-delta__value">{{ deltaText() }}</span>
3321
+ </div>
3322
+ }
3323
+
3324
+ @case ('radial') {
3325
+ <div class="prx-micro-radial" [attr.data-tone]="config.tone || null">
3326
+ <svg class="prx-micro-radial__svg" viewBox="0 0 36 36">
3327
+ <circle class="prx-micro-radial__track" cx="18" cy="18" r="15.9155" />
3328
+ <circle
3329
+ class="prx-micro-radial__bar"
3330
+ cx="18"
3331
+ cy="18"
3332
+ r="15.9155"
3333
+ [style.strokeDasharray]="radialDashArray()"
3334
+ />
3335
+ <text x="18" y="21" class="prx-micro-radial__svg-text prx-micro-radial__value">{{ radialText() }}</text>
3336
+ </svg>
3337
+ </div>
3338
+ }
3339
+
3340
+ @case ('harveyBall') {
3341
+ <div class="prx-micro-harvey" [attr.data-tone]="config.tone || null">
3342
+ <svg class="prx-micro-harvey__svg" viewBox="0 0 36 36">
3343
+ <circle class="prx-micro-harvey__track" cx="18" cy="18" r="16" />
3344
+ <circle
3345
+ class="prx-micro-harvey__bar"
3346
+ cx="18"
3347
+ cy="18"
3348
+ r="8"
3349
+ [style.strokeDasharray]="harveyDashArray()"
3350
+ />
3351
+ </svg>
3352
+ <span class="prx-micro-harvey__fraction">
3353
+ <strong class="prx-micro-harvey__value">{{ formatNumber(config.value) }}</strong>
3354
+ <span class="prx-micro-harvey__separator">/</span>
3355
+ <span class="prx-micro-harvey__total">{{ formatNumber(config.total) }}</span>
3356
+ </span>
3357
+ </div>
3358
+ }
3359
+
3360
+ @case ('line') {
3361
+ <div class="prx-micro-trend-container">
3362
+ @if (!isTableCell() && firstPoint()) {
3363
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--start">
3364
+ <span class="prx-micro-trend__value">{{ formatNumber(firstPoint()?.value) }}</span>
3365
+ <span class="prx-micro-trend__label">{{ firstPoint()?.label }}</span>
3366
+ </div>
3367
+ }
3368
+
3369
+ <div class="prx-micro-trend__chart">
3370
+ <div class="prx-micro-line" [attr.data-tone]="config.tone || null">
3371
+ <svg class="prx-micro-line__svg" viewBox="0 0 100 30">
3372
+ <path
3373
+ class="prx-micro-line__path"
3374
+ [attr.d]="trendPathD()"
3375
+ fill="none"
3376
+ stroke="currentColor"
3377
+ stroke-width="2"
3378
+ stroke-linecap="round"
3379
+ stroke-linejoin="round"
3380
+ />
3381
+ @for (marker of trendMarkers(); track $index) {
3382
+ <circle
3383
+ [attr.cx]="marker.x"
3384
+ [attr.cy]="marker.y"
3385
+ r="2.5"
3386
+ class="prx-micro-trend__marker"
3387
+ [attr.data-tone]="marker.tone || null"
3388
+ [attr.title]="marker.label"
3389
+ />
3390
+ }
3391
+ </svg>
3392
+ </div>
3393
+ </div>
3394
+
3395
+ @if (!isTableCell() && lastPoint()) {
3396
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--end">
3397
+ <span class="prx-micro-trend__value">{{ formatNumber(lastPoint()?.value) }}</span>
3398
+ <span class="prx-micro-trend__label">{{ lastPoint()?.label }}</span>
3399
+ </div>
3400
+ }
3401
+ </div>
3402
+ }
3403
+
3404
+ @case ('area') {
3405
+ <div class="prx-micro-trend-container">
3406
+ @if (!isTableCell() && firstPoint()) {
3407
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--start">
3408
+ <span class="prx-micro-trend__value">{{ formatNumber(firstPoint()?.value) }}</span>
3409
+ <span class="prx-micro-trend__label">{{ firstPoint()?.label }}</span>
3410
+ </div>
3411
+ }
3412
+
3413
+ <div class="prx-micro-trend__chart">
3414
+ <div class="prx-micro-area" [attr.data-tone]="config.tone || null">
3415
+ <svg class="prx-micro-area__svg" viewBox="0 0 100 30">
3416
+ <path
3417
+ class="prx-micro-area__fill"
3418
+ [attr.d]="trendAreaD()"
3419
+ fill="currentColor"
3420
+ fill-opacity="0.15"
3421
+ />
3422
+ <path
3423
+ class="prx-micro-area__path"
3424
+ [attr.d]="trendPathD()"
3425
+ fill="none"
3426
+ stroke="currentColor"
3427
+ stroke-width="2"
3428
+ stroke-linecap="round"
3429
+ stroke-linejoin="round"
3430
+ />
3431
+ @for (marker of trendMarkers(); track $index) {
3432
+ <circle
3433
+ [attr.cx]="marker.x"
3434
+ [attr.cy]="marker.y"
3435
+ r="2.5"
3436
+ class="prx-micro-trend__marker"
3437
+ [attr.data-tone]="marker.tone || null"
3438
+ [attr.title]="marker.label"
3439
+ />
3440
+ }
3441
+ </svg>
3442
+ </div>
3443
+ </div>
3444
+
3445
+ @if (!isTableCell() && lastPoint()) {
3446
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--end">
3447
+ <span class="prx-micro-trend__value">{{ formatNumber(lastPoint()?.value) }}</span>
3448
+ <span class="prx-micro-trend__label">{{ lastPoint()?.label }}</span>
3449
+ </div>
3450
+ }
3451
+ </div>
3452
+ }
3453
+
3454
+ @case ('column') {
3455
+ <div class="prx-micro-trend-container">
3456
+ @if (!isTableCell() && firstPoint()) {
3457
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--start">
3458
+ <span class="prx-micro-trend__value">{{ formatNumber(firstPoint()?.value) }}</span>
3459
+ <span class="prx-micro-trend__label">{{ firstPoint()?.label }}</span>
3460
+ </div>
3461
+ }
3462
+
3463
+ <div class="prx-micro-trend__chart">
3464
+ <div class="prx-micro-column" [attr.data-tone]="config.tone || null">
3465
+ <svg class="prx-micro-column__svg" viewBox="0 0 100 30">
3466
+ @for (col of trendColumns(); track $index) {
3467
+ <rect
3468
+ class="prx-micro-column__bar"
3469
+ [attr.x]="col.x"
3470
+ [attr.y]="col.y"
3471
+ [attr.width]="col.width"
3472
+ [attr.height]="col.height"
3473
+ [attr.data-tone]="col.tone || null"
3474
+ />
3475
+ }
3476
+ </svg>
3477
+ </div>
3478
+ </div>
3479
+
3480
+ @if (!isTableCell() && lastPoint()) {
3481
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--end">
3482
+ <span class="prx-micro-trend__value">{{ formatNumber(lastPoint()?.value) }}</span>
3483
+ <span class="prx-micro-trend__label">{{ lastPoint()?.label }}</span>
3484
+ </div>
3485
+ }
3486
+ </div>
3487
+ }
3488
+
3489
+ @case ('processFlow') {
3490
+ <div class="prx-micro-process">
3491
+ @for (item of processSteps(); track item.id ?? $index) {
3492
+ <div class="prx-micro-process__step" [class.prx-micro-process__step--last]="$last">
3493
+ <div class="prx-micro-process__node-wrapper">
3494
+ <span
3495
+ class="prx-micro-process__node"
3496
+ [attr.data-tone]="item.tone || null"
3497
+ [attr.title]="item.label || null"
3498
+ >
3499
+ @if (item.icon) {
3500
+ <span class="material-icons prx-micro-process__icon" aria-hidden="true">{{ item.icon }}</span>
3501
+ } @else {
3502
+ {{ $index + 1 }}
3503
+ }
3504
+ </span>
3505
+ @if (item.label) {
3506
+ <span class="prx-micro-process__label" [attr.title]="item.label">{{ item.label }}</span>
3507
+ }
3508
+ </div>
3509
+ @if (!$last) {
3510
+ <span
3511
+ class="prx-micro-process__connector"
3512
+ [attr.data-tone]="item.tone || null"
3513
+ ></span>
3514
+ }
3515
+ </div>
3516
+ }
3517
+ </div>
3518
+ }
3519
+ }
3520
+ </figure>
3521
+ } @else {
3522
+ <span class="prx-micro-visualization-fallback">{{ fallbackText() }}</span>
3523
+ }
3524
+ `, isInline: true, styles: [":host{display:inline-block;min-width:0;max-width:100%;color:var(--prx-micro-text-color, var(--md-sys-color-on-surface, #1f2937))}.prx-micro-visualization{display:block;min-width:0;margin:0}:host([data-size=\"xs\"]) .prx-micro-visualization{inline-size:var(--prx-micro-xs-width, 96px)}:host([data-size=\"sm\"]) .prx-micro-visualization{inline-size:var(--prx-micro-sm-width, 136px)}:host([data-size=\"md\"]) .prx-micro-visualization,:host([data-size=\"responsive\"]) .prx-micro-visualization{inline-size:100%}:host(.prx-micro-visualization--table-cell) .prx-micro-visualization{inline-size:var(--prx-micro-table-cell-width, 112px)}.prx-micro-comparison{display:grid;gap:3px}.prx-micro-comparison__row{display:grid;grid-template-columns:minmax(0,52px) minmax(32px,1fr) auto;align-items:center;gap:6px;min-block-size:12px}.prx-micro-comparison__label,.prx-micro-comparison__value,.prx-micro-visualization__caption,.prx-micro-visualization-fallback{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--prx-micro-font-size, 11px);line-height:1.2}.prx-micro-comparison__label{color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563))}.prx-micro-comparison__value{justify-self:end;font-variant-numeric:tabular-nums}.prx-micro-comparison__track,.prx-micro-stacked__track,.prx-micro-bullet__track{position:relative;display:block;overflow:hidden;border-radius:var(--prx-micro-track-radius, 999px);background:var(--prx-micro-track-color, var(--md-sys-color-surface-container-high, #e5e7eb))}.prx-micro-comparison__track{block-size:5px}.prx-micro-comparison__bar,.prx-micro-stacked__segment,.prx-micro-bullet__range,.prx-micro-bullet__actual{display:block;min-inline-size:1px;background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-tone-neutral, var(--md-sys-color-secondary, #5c6b73)) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-neutral, var(--md-sys-color-secondary, #5c6b73)) 84%,#111827))}.prx-micro-comparison__bar{block-size:100%}.prx-micro-stacked__track{display:flex;block-size:8px}.prx-micro-stacked__segment{block-size:100%}.prx-micro-bullet__track{block-size:10px}.prx-micro-bullet__range{position:absolute;inset-block:0;display:block;block-size:100%;opacity:.32}.prx-micro-bullet__actual{position:absolute;inset-block-start:3px;inset-inline-start:0;block-size:4px;border-radius:inherit}.prx-micro-bullet__target{position:absolute;inset-block:0;inline-size:2px;background:var(--prx-micro-target-color, var(--md-sys-color-on-surface, #111827))}.prx-micro-delta{display:inline-flex;align-items:center;gap:4px;min-inline-size:0;font-size:var(--prx-micro-font-size, 12px);line-height:1.2;font-variant-numeric:tabular-nums}.prx-micro-delta__icon{flex:0 0 auto}.prx-micro-delta__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.prx-micro-visualization__caption{display:block;margin-block-start:4px;color:var(--prx-micro-caption-color, var(--md-sys-color-on-surface-variant, #4b5563))}.prx-micro-bullet-container{display:flex;flex-direction:column;gap:4px;width:100%}.prx-micro-bullet__top{display:flex;justify-content:space-between;align-items:baseline;font-size:var(--prx-micro-font-size, 11px)}.prx-micro-bullet__label{color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563));font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.prx-micro-bullet__value{font-weight:700;color:currentColor;font-variant-numeric:tabular-nums;flex-shrink:0}.prx-micro-bullet__target-val{font-weight:400;font-size:10px;color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563));margin-left:4px}.prx-micro-bullet__bottom{display:flex;justify-content:space-between;font-size:9px;color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563))}[data-tone=info]{color:var(--prx-micro-tone-info-text, var(--md-sys-color-primary, #0a6eb4))}.prx-micro-comparison__bar[data-tone=info],.prx-micro-stacked__segment[data-tone=info],.prx-micro-bullet__range[data-tone=info],.prx-micro-bullet__actual[data-tone=info],.prx-micro-process__node[data-tone=info],.prx-micro-process__connector[data-tone=info]{background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)) 84%,#111827))}[data-tone=success]{color:var(--prx-micro-tone-success-text, #1b7a43)}.prx-micro-comparison__bar[data-tone=success],.prx-micro-stacked__segment[data-tone=success],.prx-micro-bullet__range[data-tone=success],.prx-micro-bullet__actual[data-tone=success],.prx-micro-process__node[data-tone=success],.prx-micro-process__connector[data-tone=success]{background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-tone-success, #1b7a43) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-success, #1b7a43) 84%,#111827))}[data-tone=warning]{color:var(--prx-micro-tone-warning-text, #d97706)}.prx-micro-comparison__bar[data-tone=warning],.prx-micro-stacked__segment[data-tone=warning],.prx-micro-bullet__range[data-tone=warning],.prx-micro-bullet__actual[data-tone=warning],.prx-micro-process__node[data-tone=warning],.prx-micro-process__connector[data-tone=warning]{background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-tone-warning, #d97706) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-warning, #d97706) 84%,#111827))}[data-tone=danger],[data-tone=critical]{color:var(--prx-micro-tone-danger-text, var(--md-sys-color-error, #c62828))}.prx-micro-comparison__bar[data-tone=danger],.prx-micro-comparison__bar[data-tone=critical],.prx-micro-stacked__segment[data-tone=danger],.prx-micro-stacked__segment[data-tone=critical],.prx-micro-bullet__range[data-tone=danger],.prx-micro-bullet__range[data-tone=critical],.prx-micro-bullet__actual[data-tone=danger],.prx-micro-bullet__actual[data-tone=critical],.prx-micro-process__node[data-tone=danger],.prx-micro-process__node[data-tone=critical],.prx-micro-process__connector[data-tone=danger],.prx-micro-process__connector[data-tone=critical]{background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)) 84%,#111827))}.prx-micro-delta--positive{color:var(--prx-micro-tone-success-text, #1b7a43)}.prx-micro-delta--negative{color:var(--prx-micro-tone-danger-text, var(--md-sys-color-error, #c62828))}.prx-micro-radial{display:inline-flex;align-items:center;justify-content:center;position:relative}.prx-micro-radial__svg{width:24px;height:24px;overflow:visible;flex-shrink:0;display:block}.prx-micro-radial__track{fill:none;stroke:var(--prx-micro-track-color, var(--md-sys-color-surface-container-high, #e5e7eb));stroke-width:3}.prx-micro-radial__bar{fill:none;stroke:currentColor;stroke-width:3;stroke-linecap:round;transform:rotate(-90deg);transform-origin:50% 50%;transition:stroke-dasharray .35s ease}.prx-micro-radial__svg-text{font-size:8px;font-weight:700;text-anchor:middle;fill:currentColor;font-family:var(--md-sys-typescale-body-medium-font-family, sans-serif)}.prx-micro-harvey{display:inline-flex;align-items:center;gap:0}.prx-micro-harvey__svg{width:18px;height:18px;overflow:visible;flex-shrink:0}.prx-micro-harvey__track{fill:none;stroke:var(--prx-micro-track-color, var(--md-sys-color-surface-container-high, #e5e7eb));stroke-width:2}.prx-micro-harvey__bar{fill:none;stroke:currentColor;stroke-width:16;transform:rotate(-90deg);transform-origin:50% 50%;transition:stroke-dasharray .35s ease}.prx-micro-harvey__fraction{display:inline-flex;align-items:center;font-size:var(--prx-micro-font-size, 11px);font-variant-numeric:tabular-nums;margin-left:6px;font-family:var(--md-sys-typescale-body-medium-font-family, sans-serif)}.prx-micro-harvey__value{color:currentColor;font-weight:700}.prx-micro-harvey__separator{opacity:.6;color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563));margin-inline:2px}.prx-micro-harvey__total{color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563))}.prx-micro-trend-container{display:flex;align-items:center;gap:8px;width:100%}.prx-micro-trend__label-col{display:flex;flex-direction:column;justify-content:center;font-size:var(--prx-micro-font-size, 11px);line-height:1.2;flex-shrink:0;min-width:24px;font-family:var(--md-sys-typescale-body-medium-font-family, sans-serif)}.prx-micro-trend__label-col--start{align-items:flex-end;text-align:right}.prx-micro-trend__label-col--end{align-items:flex-start;text-align:left}.prx-micro-trend__value{font-weight:700;color:var(--md-sys-color-on-surface, #1f2937)}.prx-micro-trend__label{color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563));font-size:9px}.prx-micro-trend__chart{flex:1 1 auto;height:30px;min-width:48px;overflow:visible}.prx-micro-line,.prx-micro-area,.prx-micro-column{display:block;width:100%;height:30px;overflow:visible}.prx-micro-line__svg,.prx-micro-area__svg,.prx-micro-column__svg{width:100%;height:100%;display:block;overflow:visible}.prx-micro-line__path,.prx-micro-area__path{stroke:currentColor}.prx-micro-area__fill,.prx-micro-column__bar{fill:currentColor}.prx-micro-trend__marker{fill:currentColor;stroke:var(--md-sys-color-surface, #ffffff);stroke-width:1.5px}.prx-micro-process{display:flex;align-items:flex-start;width:100%;min-width:0;padding-block:6px 2px;overflow-x:auto;-webkit-overflow-scrolling:touch}.prx-micro-process__step{display:grid;grid-template-columns:minmax(42px,auto) minmax(14px,1fr);align-items:start;flex:1 1 0%;min-width:0}.prx-micro-process__step--last{grid-template-columns:minmax(42px,auto);flex:0 0 auto}.prx-micro-process__node-wrapper{display:flex;flex-direction:column;align-items:center;position:relative;flex-shrink:0;min-width:42px}.prx-micro-process__node{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;font-size:12px;font-weight:700;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-surface-container-high, #e5e7eb) 92%,#ffffff),color-mix(in srgb,var(--md-sys-color-surface-container-high, #e5e7eb) 82%,#111827));color:var(--md-sys-color-on-surface, #1f2937);box-shadow:inset 0 0 0 1px color-mix(in srgb,currentColor 16%,transparent);transition:background-color .2s ease,color .2s ease}.prx-micro-process__icon{font-size:14px;line-height:1}.prx-micro-process__label{display:-webkit-box;inline-size:56px;max-width:56px;margin-top:5px;overflow:hidden;overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2;color:var(--md-sys-color-on-surface-variant, #4b5563);font-size:9px;font-weight:600;line-height:1.15;text-align:center}.prx-micro-process__connector{flex:1 1 auto;height:2px;background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-track-color, var(--md-sys-color-surface-container-high, #e5e7eb)) 78%,transparent),color-mix(in srgb,var(--prx-micro-track-color, var(--md-sys-color-surface-container-high, #e5e7eb)) 42%,transparent));margin-block-start:11px;margin-inline:6px;min-width:14px;border-radius:999px;opacity:.85}:host(.prx-micro-visualization--table-cell) .prx-micro-process{align-items:center;min-width:112px;padding-block:0;overflow:hidden}:host(.prx-micro-visualization--table-cell) .prx-micro-process__step{display:flex;align-items:center;flex:0 1 auto}:host(.prx-micro-visualization--table-cell) .prx-micro-process__node-wrapper{min-width:0}:host(.prx-micro-visualization--table-cell) .prx-micro-process__node{width:22px;height:22px}:host(.prx-micro-visualization--table-cell) .prx-micro-process__label{display:none}:host(.prx-micro-visualization--table-cell) .prx-micro-process__connector{flex:0 1 22px;min-width:10px;max-width:26px;margin-block-start:0;margin-inline:5px}.prx-micro-process__node[data-tone=info]{background:linear-gradient(135deg,color-mix(in srgb,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)) 82%,#111827));color:#fff}.prx-micro-process__node[data-tone=success]{background:linear-gradient(135deg,color-mix(in srgb,var(--prx-micro-tone-success, #1b7a43) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-success, #1b7a43) 82%,#111827));color:#fff}.prx-micro-process__node[data-tone=warning]{background:linear-gradient(135deg,color-mix(in srgb,var(--prx-micro-tone-warning, #d97706) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-warning, #d97706) 82%,#111827));color:#fff}.prx-micro-process__node[data-tone=danger],.prx-micro-process__node[data-tone=critical]{background:linear-gradient(135deg,color-mix(in srgb,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)) 82%,#111827));color:#fff}.prx-micro-process__connector[data-tone=info]{background:linear-gradient(90deg,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)),color-mix(in srgb,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)) 38%,transparent))}.prx-micro-process__connector[data-tone=success]{background:linear-gradient(90deg,var(--prx-micro-tone-success, #1b7a43),color-mix(in srgb,var(--prx-micro-tone-success, #1b7a43) 38%,transparent))}.prx-micro-process__connector[data-tone=warning]{background:linear-gradient(90deg,var(--prx-micro-tone-warning, #d97706),color-mix(in srgb,var(--prx-micro-tone-warning, #d97706) 38%,transparent))}.prx-micro-process__connector[data-tone=danger],.prx-micro-process__connector[data-tone=critical]{background:linear-gradient(90deg,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)),color-mix(in srgb,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)) 38%,transparent))}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3525
+ }
3526
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisMicroVisualizationComponent, decorators: [{
3527
+ type: Component,
3528
+ args: [{ selector: 'praxis-micro-visualization', changeDetection: ChangeDetectionStrategy.OnPush, host: {
3529
+ '[attr.data-kind]': 'kind()',
3530
+ '[attr.data-surface]': 'surface()',
3531
+ '[attr.data-size]': 'size()',
3532
+ '[class.prx-micro-visualization--table-cell]': 'surface() === "table-cell"',
3533
+ }, template: `
3534
+ @if (visualization(); as config) {
3535
+ <figure
3536
+ class="prx-micro-visualization"
3537
+ [attr.aria-label]="ariaLabel()"
3538
+ role="img"
3539
+ >
3540
+ @switch (config.kind) {
3541
+ @case ('comparison') {
3542
+ <div class="prx-micro-comparison">
3543
+ @for (item of comparisonItems(); track item.label ?? $index) {
3544
+ <div class="prx-micro-comparison__row">
3545
+ @if (item.label) {
3546
+ <span class="prx-micro-comparison__label">{{ item.label }}</span>
3547
+ }
3548
+ <span class="prx-micro-comparison__track" aria-hidden="true">
3549
+ <span
3550
+ class="prx-micro-comparison__bar"
3551
+ [attr.data-tone]="item.tone || null"
3552
+ [style.width.%]="itemPercent(item.value)"
3553
+ ></span>
3554
+ </span>
3555
+ @if (item.value !== undefined) {
3556
+ <span class="prx-micro-comparison__value">{{ formatNumber(item.value) }}</span>
3557
+ }
3558
+ </div>
3559
+ }
3560
+ </div>
3561
+ }
3562
+
3563
+ @case ('stackedBar') {
3564
+ <div class="prx-micro-stacked">
3565
+ <div class="prx-micro-stacked__track" aria-hidden="true">
3566
+ @for (segment of stackedSegments(); track segment.label ?? $index) {
3567
+ <span
3568
+ class="prx-micro-stacked__segment"
3569
+ [attr.data-tone]="segment.tone || null"
3570
+ [style.width.%]="segmentPercent(segment.value)"
3571
+ ></span>
3572
+ }
3573
+ </div>
3574
+ @if (!isTableCell() && config.fallbackText) {
3575
+ <figcaption class="prx-micro-visualization__caption">{{ config.fallbackText }}</figcaption>
3576
+ }
3577
+ </div>
3578
+ }
3579
+
3580
+ @case ('bullet') {
3581
+ <div class="prx-micro-bullet-container">
3582
+ @if (!isTableCell()) {
3583
+ <div class="prx-micro-bullet__top">
3584
+ <span class="prx-micro-bullet__label">{{ config.fallbackText }}</span>
3585
+ <span class="prx-micro-bullet__value" [attr.data-tone]="config.tone || null">
3586
+ {{ formatNumber(config.value) }}
3587
+ @if (config.target !== undefined) {
3588
+ <span class="prx-micro-bullet__target-val">/ Target: {{ formatNumber(config.target) }}</span>
3589
+ }
3590
+ </span>
3591
+ </div>
3592
+ }
3593
+
3594
+ <div class="prx-micro-bullet__track" aria-hidden="true">
3595
+ @for (band of bulletBands(); track band.label ?? $index) {
3596
+ <span
3597
+ class="prx-micro-bullet__range"
3598
+ [attr.data-tone]="band.tone || null"
3599
+ [style.left.%]="band.left"
3600
+ [style.width.%]="band.width"
3601
+ ></span>
3602
+ }
3603
+ <span
3604
+ class="prx-micro-bullet__actual"
3605
+ [attr.data-tone]="config.tone || null"
3606
+ [style.width.%]="valuePercent(config.value)"
3607
+ ></span>
3608
+ @if (config.target !== undefined) {
3609
+ <span
3610
+ class="prx-micro-bullet__target"
3611
+ [style.left.%]="valuePercent(config.target)"
3612
+ ></span>
3613
+ }
3614
+ </div>
3615
+
3616
+ @if (!isTableCell()) {
3617
+ <div class="prx-micro-bullet__bottom">
3618
+ <span class="prx-micro-bullet__scale-min">{{ formatNumber(config.baseline ?? 0) }}</span>
3619
+ <span class="prx-micro-bullet__scale-max">{{ formatNumber(config.total ?? 100) }}</span>
3620
+ </div>
3621
+ }
3622
+ </div>
3623
+ }
3624
+
3625
+ @case ('delta') {
3626
+ <div
3627
+ class="prx-micro-delta"
3628
+ [class.prx-micro-delta--positive]="deltaValue() > 0"
3629
+ [class.prx-micro-delta--negative]="deltaValue() < 0"
3630
+ >
3631
+ @if (deltaIcon(); as icon) {
3632
+ <span class="prx-micro-delta__icon" aria-hidden="true">{{ icon }}</span>
3633
+ }
3634
+ <span class="prx-micro-delta__value">{{ deltaText() }}</span>
3635
+ </div>
3636
+ }
3637
+
3638
+ @case ('radial') {
3639
+ <div class="prx-micro-radial" [attr.data-tone]="config.tone || null">
3640
+ <svg class="prx-micro-radial__svg" viewBox="0 0 36 36">
3641
+ <circle class="prx-micro-radial__track" cx="18" cy="18" r="15.9155" />
3642
+ <circle
3643
+ class="prx-micro-radial__bar"
3644
+ cx="18"
3645
+ cy="18"
3646
+ r="15.9155"
3647
+ [style.strokeDasharray]="radialDashArray()"
3648
+ />
3649
+ <text x="18" y="21" class="prx-micro-radial__svg-text prx-micro-radial__value">{{ radialText() }}</text>
3650
+ </svg>
3651
+ </div>
3652
+ }
3653
+
3654
+ @case ('harveyBall') {
3655
+ <div class="prx-micro-harvey" [attr.data-tone]="config.tone || null">
3656
+ <svg class="prx-micro-harvey__svg" viewBox="0 0 36 36">
3657
+ <circle class="prx-micro-harvey__track" cx="18" cy="18" r="16" />
3658
+ <circle
3659
+ class="prx-micro-harvey__bar"
3660
+ cx="18"
3661
+ cy="18"
3662
+ r="8"
3663
+ [style.strokeDasharray]="harveyDashArray()"
3664
+ />
3665
+ </svg>
3666
+ <span class="prx-micro-harvey__fraction">
3667
+ <strong class="prx-micro-harvey__value">{{ formatNumber(config.value) }}</strong>
3668
+ <span class="prx-micro-harvey__separator">/</span>
3669
+ <span class="prx-micro-harvey__total">{{ formatNumber(config.total) }}</span>
3670
+ </span>
3671
+ </div>
3672
+ }
3673
+
3674
+ @case ('line') {
3675
+ <div class="prx-micro-trend-container">
3676
+ @if (!isTableCell() && firstPoint()) {
3677
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--start">
3678
+ <span class="prx-micro-trend__value">{{ formatNumber(firstPoint()?.value) }}</span>
3679
+ <span class="prx-micro-trend__label">{{ firstPoint()?.label }}</span>
3680
+ </div>
3681
+ }
3682
+
3683
+ <div class="prx-micro-trend__chart">
3684
+ <div class="prx-micro-line" [attr.data-tone]="config.tone || null">
3685
+ <svg class="prx-micro-line__svg" viewBox="0 0 100 30">
3686
+ <path
3687
+ class="prx-micro-line__path"
3688
+ [attr.d]="trendPathD()"
3689
+ fill="none"
3690
+ stroke="currentColor"
3691
+ stroke-width="2"
3692
+ stroke-linecap="round"
3693
+ stroke-linejoin="round"
3694
+ />
3695
+ @for (marker of trendMarkers(); track $index) {
3696
+ <circle
3697
+ [attr.cx]="marker.x"
3698
+ [attr.cy]="marker.y"
3699
+ r="2.5"
3700
+ class="prx-micro-trend__marker"
3701
+ [attr.data-tone]="marker.tone || null"
3702
+ [attr.title]="marker.label"
3703
+ />
3704
+ }
3705
+ </svg>
3706
+ </div>
3707
+ </div>
3708
+
3709
+ @if (!isTableCell() && lastPoint()) {
3710
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--end">
3711
+ <span class="prx-micro-trend__value">{{ formatNumber(lastPoint()?.value) }}</span>
3712
+ <span class="prx-micro-trend__label">{{ lastPoint()?.label }}</span>
3713
+ </div>
3714
+ }
3715
+ </div>
3716
+ }
3717
+
3718
+ @case ('area') {
3719
+ <div class="prx-micro-trend-container">
3720
+ @if (!isTableCell() && firstPoint()) {
3721
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--start">
3722
+ <span class="prx-micro-trend__value">{{ formatNumber(firstPoint()?.value) }}</span>
3723
+ <span class="prx-micro-trend__label">{{ firstPoint()?.label }}</span>
3724
+ </div>
3725
+ }
3726
+
3727
+ <div class="prx-micro-trend__chart">
3728
+ <div class="prx-micro-area" [attr.data-tone]="config.tone || null">
3729
+ <svg class="prx-micro-area__svg" viewBox="0 0 100 30">
3730
+ <path
3731
+ class="prx-micro-area__fill"
3732
+ [attr.d]="trendAreaD()"
3733
+ fill="currentColor"
3734
+ fill-opacity="0.15"
3735
+ />
3736
+ <path
3737
+ class="prx-micro-area__path"
3738
+ [attr.d]="trendPathD()"
3739
+ fill="none"
3740
+ stroke="currentColor"
3741
+ stroke-width="2"
3742
+ stroke-linecap="round"
3743
+ stroke-linejoin="round"
3744
+ />
3745
+ @for (marker of trendMarkers(); track $index) {
3746
+ <circle
3747
+ [attr.cx]="marker.x"
3748
+ [attr.cy]="marker.y"
3749
+ r="2.5"
3750
+ class="prx-micro-trend__marker"
3751
+ [attr.data-tone]="marker.tone || null"
3752
+ [attr.title]="marker.label"
3753
+ />
3754
+ }
3755
+ </svg>
3756
+ </div>
3757
+ </div>
3758
+
3759
+ @if (!isTableCell() && lastPoint()) {
3760
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--end">
3761
+ <span class="prx-micro-trend__value">{{ formatNumber(lastPoint()?.value) }}</span>
3762
+ <span class="prx-micro-trend__label">{{ lastPoint()?.label }}</span>
3763
+ </div>
3764
+ }
3765
+ </div>
3766
+ }
3767
+
3768
+ @case ('column') {
3769
+ <div class="prx-micro-trend-container">
3770
+ @if (!isTableCell() && firstPoint()) {
3771
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--start">
3772
+ <span class="prx-micro-trend__value">{{ formatNumber(firstPoint()?.value) }}</span>
3773
+ <span class="prx-micro-trend__label">{{ firstPoint()?.label }}</span>
3774
+ </div>
3775
+ }
3776
+
3777
+ <div class="prx-micro-trend__chart">
3778
+ <div class="prx-micro-column" [attr.data-tone]="config.tone || null">
3779
+ <svg class="prx-micro-column__svg" viewBox="0 0 100 30">
3780
+ @for (col of trendColumns(); track $index) {
3781
+ <rect
3782
+ class="prx-micro-column__bar"
3783
+ [attr.x]="col.x"
3784
+ [attr.y]="col.y"
3785
+ [attr.width]="col.width"
3786
+ [attr.height]="col.height"
3787
+ [attr.data-tone]="col.tone || null"
3788
+ />
3789
+ }
3790
+ </svg>
3791
+ </div>
3792
+ </div>
3793
+
3794
+ @if (!isTableCell() && lastPoint()) {
3795
+ <div class="prx-micro-trend__label-col prx-micro-trend__label-col--end">
3796
+ <span class="prx-micro-trend__value">{{ formatNumber(lastPoint()?.value) }}</span>
3797
+ <span class="prx-micro-trend__label">{{ lastPoint()?.label }}</span>
3798
+ </div>
3799
+ }
3800
+ </div>
3801
+ }
3802
+
3803
+ @case ('processFlow') {
3804
+ <div class="prx-micro-process">
3805
+ @for (item of processSteps(); track item.id ?? $index) {
3806
+ <div class="prx-micro-process__step" [class.prx-micro-process__step--last]="$last">
3807
+ <div class="prx-micro-process__node-wrapper">
3808
+ <span
3809
+ class="prx-micro-process__node"
3810
+ [attr.data-tone]="item.tone || null"
3811
+ [attr.title]="item.label || null"
3812
+ >
3813
+ @if (item.icon) {
3814
+ <span class="material-icons prx-micro-process__icon" aria-hidden="true">{{ item.icon }}</span>
3815
+ } @else {
3816
+ {{ $index + 1 }}
3817
+ }
3818
+ </span>
3819
+ @if (item.label) {
3820
+ <span class="prx-micro-process__label" [attr.title]="item.label">{{ item.label }}</span>
3821
+ }
3822
+ </div>
3823
+ @if (!$last) {
3824
+ <span
3825
+ class="prx-micro-process__connector"
3826
+ [attr.data-tone]="item.tone || null"
3827
+ ></span>
3828
+ }
3829
+ </div>
3830
+ }
3831
+ </div>
3832
+ }
3833
+ }
3834
+ </figure>
3835
+ } @else {
3836
+ <span class="prx-micro-visualization-fallback">{{ fallbackText() }}</span>
3837
+ }
3838
+ `, styles: [":host{display:inline-block;min-width:0;max-width:100%;color:var(--prx-micro-text-color, var(--md-sys-color-on-surface, #1f2937))}.prx-micro-visualization{display:block;min-width:0;margin:0}:host([data-size=\"xs\"]) .prx-micro-visualization{inline-size:var(--prx-micro-xs-width, 96px)}:host([data-size=\"sm\"]) .prx-micro-visualization{inline-size:var(--prx-micro-sm-width, 136px)}:host([data-size=\"md\"]) .prx-micro-visualization,:host([data-size=\"responsive\"]) .prx-micro-visualization{inline-size:100%}:host(.prx-micro-visualization--table-cell) .prx-micro-visualization{inline-size:var(--prx-micro-table-cell-width, 112px)}.prx-micro-comparison{display:grid;gap:3px}.prx-micro-comparison__row{display:grid;grid-template-columns:minmax(0,52px) minmax(32px,1fr) auto;align-items:center;gap:6px;min-block-size:12px}.prx-micro-comparison__label,.prx-micro-comparison__value,.prx-micro-visualization__caption,.prx-micro-visualization-fallback{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:var(--prx-micro-font-size, 11px);line-height:1.2}.prx-micro-comparison__label{color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563))}.prx-micro-comparison__value{justify-self:end;font-variant-numeric:tabular-nums}.prx-micro-comparison__track,.prx-micro-stacked__track,.prx-micro-bullet__track{position:relative;display:block;overflow:hidden;border-radius:var(--prx-micro-track-radius, 999px);background:var(--prx-micro-track-color, var(--md-sys-color-surface-container-high, #e5e7eb))}.prx-micro-comparison__track{block-size:5px}.prx-micro-comparison__bar,.prx-micro-stacked__segment,.prx-micro-bullet__range,.prx-micro-bullet__actual{display:block;min-inline-size:1px;background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-tone-neutral, var(--md-sys-color-secondary, #5c6b73)) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-neutral, var(--md-sys-color-secondary, #5c6b73)) 84%,#111827))}.prx-micro-comparison__bar{block-size:100%}.prx-micro-stacked__track{display:flex;block-size:8px}.prx-micro-stacked__segment{block-size:100%}.prx-micro-bullet__track{block-size:10px}.prx-micro-bullet__range{position:absolute;inset-block:0;display:block;block-size:100%;opacity:.32}.prx-micro-bullet__actual{position:absolute;inset-block-start:3px;inset-inline-start:0;block-size:4px;border-radius:inherit}.prx-micro-bullet__target{position:absolute;inset-block:0;inline-size:2px;background:var(--prx-micro-target-color, var(--md-sys-color-on-surface, #111827))}.prx-micro-delta{display:inline-flex;align-items:center;gap:4px;min-inline-size:0;font-size:var(--prx-micro-font-size, 12px);line-height:1.2;font-variant-numeric:tabular-nums}.prx-micro-delta__icon{flex:0 0 auto}.prx-micro-delta__value{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.prx-micro-visualization__caption{display:block;margin-block-start:4px;color:var(--prx-micro-caption-color, var(--md-sys-color-on-surface-variant, #4b5563))}.prx-micro-bullet-container{display:flex;flex-direction:column;gap:4px;width:100%}.prx-micro-bullet__top{display:flex;justify-content:space-between;align-items:baseline;font-size:var(--prx-micro-font-size, 11px)}.prx-micro-bullet__label{color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563));font-weight:500;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.prx-micro-bullet__value{font-weight:700;color:currentColor;font-variant-numeric:tabular-nums;flex-shrink:0}.prx-micro-bullet__target-val{font-weight:400;font-size:10px;color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563));margin-left:4px}.prx-micro-bullet__bottom{display:flex;justify-content:space-between;font-size:9px;color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563))}[data-tone=info]{color:var(--prx-micro-tone-info-text, var(--md-sys-color-primary, #0a6eb4))}.prx-micro-comparison__bar[data-tone=info],.prx-micro-stacked__segment[data-tone=info],.prx-micro-bullet__range[data-tone=info],.prx-micro-bullet__actual[data-tone=info],.prx-micro-process__node[data-tone=info],.prx-micro-process__connector[data-tone=info]{background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)) 84%,#111827))}[data-tone=success]{color:var(--prx-micro-tone-success-text, #1b7a43)}.prx-micro-comparison__bar[data-tone=success],.prx-micro-stacked__segment[data-tone=success],.prx-micro-bullet__range[data-tone=success],.prx-micro-bullet__actual[data-tone=success],.prx-micro-process__node[data-tone=success],.prx-micro-process__connector[data-tone=success]{background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-tone-success, #1b7a43) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-success, #1b7a43) 84%,#111827))}[data-tone=warning]{color:var(--prx-micro-tone-warning-text, #d97706)}.prx-micro-comparison__bar[data-tone=warning],.prx-micro-stacked__segment[data-tone=warning],.prx-micro-bullet__range[data-tone=warning],.prx-micro-bullet__actual[data-tone=warning],.prx-micro-process__node[data-tone=warning],.prx-micro-process__connector[data-tone=warning]{background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-tone-warning, #d97706) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-warning, #d97706) 84%,#111827))}[data-tone=danger],[data-tone=critical]{color:var(--prx-micro-tone-danger-text, var(--md-sys-color-error, #c62828))}.prx-micro-comparison__bar[data-tone=danger],.prx-micro-comparison__bar[data-tone=critical],.prx-micro-stacked__segment[data-tone=danger],.prx-micro-stacked__segment[data-tone=critical],.prx-micro-bullet__range[data-tone=danger],.prx-micro-bullet__range[data-tone=critical],.prx-micro-bullet__actual[data-tone=danger],.prx-micro-bullet__actual[data-tone=critical],.prx-micro-process__node[data-tone=danger],.prx-micro-process__node[data-tone=critical],.prx-micro-process__connector[data-tone=danger],.prx-micro-process__connector[data-tone=critical]{background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)) 84%,#111827))}.prx-micro-delta--positive{color:var(--prx-micro-tone-success-text, #1b7a43)}.prx-micro-delta--negative{color:var(--prx-micro-tone-danger-text, var(--md-sys-color-error, #c62828))}.prx-micro-radial{display:inline-flex;align-items:center;justify-content:center;position:relative}.prx-micro-radial__svg{width:24px;height:24px;overflow:visible;flex-shrink:0;display:block}.prx-micro-radial__track{fill:none;stroke:var(--prx-micro-track-color, var(--md-sys-color-surface-container-high, #e5e7eb));stroke-width:3}.prx-micro-radial__bar{fill:none;stroke:currentColor;stroke-width:3;stroke-linecap:round;transform:rotate(-90deg);transform-origin:50% 50%;transition:stroke-dasharray .35s ease}.prx-micro-radial__svg-text{font-size:8px;font-weight:700;text-anchor:middle;fill:currentColor;font-family:var(--md-sys-typescale-body-medium-font-family, sans-serif)}.prx-micro-harvey{display:inline-flex;align-items:center;gap:0}.prx-micro-harvey__svg{width:18px;height:18px;overflow:visible;flex-shrink:0}.prx-micro-harvey__track{fill:none;stroke:var(--prx-micro-track-color, var(--md-sys-color-surface-container-high, #e5e7eb));stroke-width:2}.prx-micro-harvey__bar{fill:none;stroke:currentColor;stroke-width:16;transform:rotate(-90deg);transform-origin:50% 50%;transition:stroke-dasharray .35s ease}.prx-micro-harvey__fraction{display:inline-flex;align-items:center;font-size:var(--prx-micro-font-size, 11px);font-variant-numeric:tabular-nums;margin-left:6px;font-family:var(--md-sys-typescale-body-medium-font-family, sans-serif)}.prx-micro-harvey__value{color:currentColor;font-weight:700}.prx-micro-harvey__separator{opacity:.6;color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563));margin-inline:2px}.prx-micro-harvey__total{color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563))}.prx-micro-trend-container{display:flex;align-items:center;gap:8px;width:100%}.prx-micro-trend__label-col{display:flex;flex-direction:column;justify-content:center;font-size:var(--prx-micro-font-size, 11px);line-height:1.2;flex-shrink:0;min-width:24px;font-family:var(--md-sys-typescale-body-medium-font-family, sans-serif)}.prx-micro-trend__label-col--start{align-items:flex-end;text-align:right}.prx-micro-trend__label-col--end{align-items:flex-start;text-align:left}.prx-micro-trend__value{font-weight:700;color:var(--md-sys-color-on-surface, #1f2937)}.prx-micro-trend__label{color:var(--prx-micro-label-color, var(--md-sys-color-on-surface-variant, #4b5563));font-size:9px}.prx-micro-trend__chart{flex:1 1 auto;height:30px;min-width:48px;overflow:visible}.prx-micro-line,.prx-micro-area,.prx-micro-column{display:block;width:100%;height:30px;overflow:visible}.prx-micro-line__svg,.prx-micro-area__svg,.prx-micro-column__svg{width:100%;height:100%;display:block;overflow:visible}.prx-micro-line__path,.prx-micro-area__path{stroke:currentColor}.prx-micro-area__fill,.prx-micro-column__bar{fill:currentColor}.prx-micro-trend__marker{fill:currentColor;stroke:var(--md-sys-color-surface, #ffffff);stroke-width:1.5px}.prx-micro-process{display:flex;align-items:flex-start;width:100%;min-width:0;padding-block:6px 2px;overflow-x:auto;-webkit-overflow-scrolling:touch}.prx-micro-process__step{display:grid;grid-template-columns:minmax(42px,auto) minmax(14px,1fr);align-items:start;flex:1 1 0%;min-width:0}.prx-micro-process__step--last{grid-template-columns:minmax(42px,auto);flex:0 0 auto}.prx-micro-process__node-wrapper{display:flex;flex-direction:column;align-items:center;position:relative;flex-shrink:0;min-width:42px}.prx-micro-process__node{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;border-radius:50%;font-size:12px;font-weight:700;background:linear-gradient(135deg,color-mix(in srgb,var(--md-sys-color-surface-container-high, #e5e7eb) 92%,#ffffff),color-mix(in srgb,var(--md-sys-color-surface-container-high, #e5e7eb) 82%,#111827));color:var(--md-sys-color-on-surface, #1f2937);box-shadow:inset 0 0 0 1px color-mix(in srgb,currentColor 16%,transparent);transition:background-color .2s ease,color .2s ease}.prx-micro-process__icon{font-size:14px;line-height:1}.prx-micro-process__label{display:-webkit-box;inline-size:56px;max-width:56px;margin-top:5px;overflow:hidden;overflow-wrap:anywhere;-webkit-box-orient:vertical;-webkit-line-clamp:2;color:var(--md-sys-color-on-surface-variant, #4b5563);font-size:9px;font-weight:600;line-height:1.15;text-align:center}.prx-micro-process__connector{flex:1 1 auto;height:2px;background:linear-gradient(90deg,color-mix(in srgb,var(--prx-micro-track-color, var(--md-sys-color-surface-container-high, #e5e7eb)) 78%,transparent),color-mix(in srgb,var(--prx-micro-track-color, var(--md-sys-color-surface-container-high, #e5e7eb)) 42%,transparent));margin-block-start:11px;margin-inline:6px;min-width:14px;border-radius:999px;opacity:.85}:host(.prx-micro-visualization--table-cell) .prx-micro-process{align-items:center;min-width:112px;padding-block:0;overflow:hidden}:host(.prx-micro-visualization--table-cell) .prx-micro-process__step{display:flex;align-items:center;flex:0 1 auto}:host(.prx-micro-visualization--table-cell) .prx-micro-process__node-wrapper{min-width:0}:host(.prx-micro-visualization--table-cell) .prx-micro-process__node{width:22px;height:22px}:host(.prx-micro-visualization--table-cell) .prx-micro-process__label{display:none}:host(.prx-micro-visualization--table-cell) .prx-micro-process__connector{flex:0 1 22px;min-width:10px;max-width:26px;margin-block-start:0;margin-inline:5px}.prx-micro-process__node[data-tone=info]{background:linear-gradient(135deg,color-mix(in srgb,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)) 82%,#111827));color:#fff}.prx-micro-process__node[data-tone=success]{background:linear-gradient(135deg,color-mix(in srgb,var(--prx-micro-tone-success, #1b7a43) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-success, #1b7a43) 82%,#111827));color:#fff}.prx-micro-process__node[data-tone=warning]{background:linear-gradient(135deg,color-mix(in srgb,var(--prx-micro-tone-warning, #d97706) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-warning, #d97706) 82%,#111827));color:#fff}.prx-micro-process__node[data-tone=danger],.prx-micro-process__node[data-tone=critical]{background:linear-gradient(135deg,color-mix(in srgb,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)) 88%,#ffffff),color-mix(in srgb,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)) 82%,#111827));color:#fff}.prx-micro-process__connector[data-tone=info]{background:linear-gradient(90deg,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)),color-mix(in srgb,var(--prx-micro-tone-info, var(--md-sys-color-primary, #0a6eb4)) 38%,transparent))}.prx-micro-process__connector[data-tone=success]{background:linear-gradient(90deg,var(--prx-micro-tone-success, #1b7a43),color-mix(in srgb,var(--prx-micro-tone-success, #1b7a43) 38%,transparent))}.prx-micro-process__connector[data-tone=warning]{background:linear-gradient(90deg,var(--prx-micro-tone-warning, #d97706),color-mix(in srgb,var(--prx-micro-tone-warning, #d97706) 38%,transparent))}.prx-micro-process__connector[data-tone=danger],.prx-micro-process__connector[data-tone=critical]{background:linear-gradient(90deg,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)),color-mix(in srgb,var(--prx-micro-tone-danger, var(--md-sys-color-error, #c62828)) 38%,transparent))}\n"] }]
3839
+ }], propDecorators: { visualizationInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "visualization", required: false }] }], fallbackInput: [{ type: i0.Input, args: [{ isSignal: true, alias: "fallbackText", required: false }] }] } });
3840
+ function clampPercent(value) {
3841
+ if (!Number.isFinite(value)) {
3842
+ return 0;
3843
+ }
3844
+ return Math.min(Math.max(value, 0), 100);
3845
+ }
3846
+
2932
3847
  const PRAXIS_CHART_DRILLDOWN_DATA_BY_MONTH = {
2933
3848
  Jan: [
2934
3849
  { segment: 'Enterprise', total: 52000 },
@@ -5019,7 +5934,7 @@ class PraxisChartShowcaseWidgetComponent {
5019
5934
  (rowClick)="handleRowClick($event)"
5020
5935
  ></praxis-table>
5021
5936
  }
5022
- `, 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", "data", "chartDocument", "filterCriteria", "queryContext", "remoteDataResolver", "enableCustomization", "availableResources", "availableFields", "availableTargets"], outputs: ["pointClick", "selectionChange", "crossFilter", "queryRequest", "loadStateChange", "chartDocumentApplied", "chartDocumentSaved"] }, { kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "dense"], outputs: ["rowClick", "widgetEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5937
+ `, 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", "data", "chartDocument", "filterCriteria", "queryContext", "remoteDataResolver", "enableCustomization", "availableResources", "availableFields", "availableTargets"], outputs: ["pointClick", "selectionChange", "crossFilter", "queryRequest", "loadStateChange", "chartDocumentApplied", "chartDocumentSaved"] }, { kind: "component", type: PraxisTable, selector: "praxis-table", inputs: ["config", "resourcePath", "data", "tableId", "componentInstanceId", "configPersistenceStrategy", "title", "subtitle", "icon", "autoDelete", "notifyIfOutdated", "snoozeMs", "autoOpenSettingsOnOutdated", "crudContext", "filterCriteria", "queryContext", "aiContext", "aiAssistantVoiceInputMode", "aiAssistantVoiceLanguage", "horizontalScroll", "enableCustomization", "dense"], outputs: ["rowClick", "widgetEvent", "resourceEvent", "rowDoubleClick", "rowExpansionChange", "rowAction", "toolbarAction", "bulkAction", "exportAction", "columnReorder", "columnReorderAttempt", "columnResize", "beforeDelete", "afterDelete", "deleteError", "beforeBulkDelete", "afterBulkDelete", "bulkDeleteError", "schemaStatusChange", "configChange", "metadataChange", "loadingStateChange", "collectionLinksChange", "selectionChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5023
5938
  }
5024
5939
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PraxisChartShowcaseWidgetComponent, decorators: [{
5025
5940
  type: Component,
@@ -5274,6 +6189,20 @@ function providePraxisChartShowcaseWidgetMetadata() {
5274
6189
  };
5275
6190
  }
5276
6191
 
6192
+ const PRAXIS_TABLE_CHART_DETAIL_RENDERER = {
6193
+ nodeType: 'chartRef',
6194
+ renderMode: 'inline',
6195
+ component: PraxisChartComponent,
6196
+ buildInputs: ({ node }) => {
6197
+ if (!node.chartDocument || typeof node.chartDocument !== 'object') {
6198
+ return null;
6199
+ }
6200
+ return {
6201
+ ...(node.inputs && typeof node.inputs === 'object' ? node.inputs : {}),
6202
+ chartDocument: node.chartDocument,
6203
+ };
6204
+ },
6205
+ };
5277
6206
  function providePraxisCharts() {
5278
6207
  return [
5279
6208
  EChartsEngineAdapter,
@@ -5285,6 +6214,11 @@ function providePraxisCharts() {
5285
6214
  providePraxisChartDrilldownPanelMetadata(),
5286
6215
  providePraxisChartStateProbeMetadata(),
5287
6216
  providePraxisChartShowcaseWidgetMetadata(),
6217
+ {
6218
+ provide: PRAXIS_TABLE_DETAIL_INLINE_RENDERERS,
6219
+ multi: true,
6220
+ useValue: PRAXIS_TABLE_CHART_DETAIL_RENDERER,
6221
+ },
5288
6222
  ];
5289
6223
  }
5290
6224
 
@@ -7113,7 +8047,7 @@ const PRAXIS_CHARTS_AUTHORING_MANIFEST = {
7113
8047
  requiresConfirmation: false,
7114
8048
  validators: ['query-context-structured', 'query-context-fields-exist', 'query-context-safe-values', 'editor-runtime-round-trip'],
7115
8049
  affectedPaths: ['queryContext'],
7116
- submissionImpact: 'config-only',
8050
+ submissionImpact: 'affects-schema-backed-data',
7117
8051
  preconditions: ['config-initialized'],
7118
8052
  },
7119
8053
  {
@@ -7135,7 +8069,7 @@ const PRAXIS_CHARTS_AUTHORING_MANIFEST = {
7135
8069
  requiresConfirmation: false,
7136
8070
  validators: ['cross-filter-output-structured', 'event-target-governed', 'event-mapping-fields-exist', 'editor-runtime-round-trip'],
7137
8071
  affectedPaths: ['chartDocument.events.crossFilter'],
7138
- submissionImpact: 'config-only',
8072
+ submissionImpact: 'affects-schema-backed-data',
7139
8073
  preconditions: ['config-initialized'],
7140
8074
  },
7141
8075
  {
@@ -7172,7 +8106,7 @@ const PRAXIS_CHARTS_AUTHORING_MANIFEST = {
7172
8106
  requiresConfirmation: false,
7173
8107
  validators: ['selection-output-structured', 'event-mapping-fields-exist', 'event-action-supported', 'editor-runtime-round-trip'],
7174
8108
  affectedPaths: ['chartDocument.events.selectionChange'],
7175
- submissionImpact: 'config-only',
8109
+ submissionImpact: 'affects-schema-backed-data',
7176
8110
  preconditions: ['config-initialized'],
7177
8111
  },
7178
8112
  {
@@ -7270,4 +8204,4 @@ const PRAXIS_CHARTS_AUTHORING_MANIFEST = {
7270
8204
  * Generated bundle index. Do not edit.
7271
8205
  */
7272
8206
 
7273
- export { AnalyticsChartConfigAdapterService, AnalyticsChartContractService, ChartContractNormalizerService, ChartContractValidationService, ChartEditorDefaultsService, ChartEditorPreviewMapperService, PRAXIS_CHARTS_AUTHORING_MANIFEST, PRAXIS_CHARTS_I18N, PRAXIS_CHART_BACKEND_MOCK_BAR, PRAXIS_CHART_BACKEND_MOCK_COMBO, PRAXIS_CHART_BACKEND_MOCK_DONUT, PRAXIS_CHART_BACKEND_MOCK_HORIZONTAL_BAR, PRAXIS_CHART_BACKEND_MOCK_MULTI_METRIC_BAR, PRAXIS_CHART_BACKEND_MOCK_SCATTER, PRAXIS_CHART_BACKEND_MOCK_STACKED_AREA, PRAXIS_CHART_BACKEND_MOCK_TIMESERIES, PRAXIS_CHART_COMPONENT_METADATA, PRAXIS_CHART_DRILLDOWN_DATA_BY_MONTH, PRAXIS_CHART_DRILLDOWN_PANEL_METADATA, PRAXIS_CHART_ENGINE, PRAXIS_CHART_PALETTE_TOKENS, PRAXIS_CHART_STATE_PROBE_COMPONENT_METADATA, PRAXIS_CHART_THEME_VARIANTS, PraxisChartBackendPayloadAdapterService, PraxisChartCanonicalContractMapperService, PraxisChartComponent, PraxisChartCompositionShowcaseComponent, PraxisChartConfigEditor, PraxisChartDataTransformerService, PraxisChartDrilldownPanelComponent, PraxisChartOptionBuilderService, PraxisChartSchemaMapperService, PraxisChartStateProbeComponent, PraxisChartStatsApiService, PraxisChartWidgetConfigEditor, buildPraxisChartInteractiveCanvasPage, buildPraxisChartInteractiveWidgetPage, buildPraxisChartMockCanvasPage, buildPraxisChartMockWidgetPage, createPraxisChartsI18nConfig, isPraxisChartPaletteToken, providePraxisChartDrilldownPanelMetadata, providePraxisChartStateProbeMetadata, providePraxisCharts, providePraxisChartsI18n, providePraxisChartsMetadata, resolvePraxisChartPaletteToken, resolvePraxisChartsText };
8207
+ export { AnalyticsChartConfigAdapterService, AnalyticsChartContractService, ChartContractNormalizerService, ChartContractValidationService, ChartEditorDefaultsService, ChartEditorPreviewMapperService, PRAXIS_CHARTS_AUTHORING_MANIFEST, PRAXIS_CHARTS_I18N, PRAXIS_CHART_BACKEND_MOCK_BAR, PRAXIS_CHART_BACKEND_MOCK_COMBO, PRAXIS_CHART_BACKEND_MOCK_DONUT, PRAXIS_CHART_BACKEND_MOCK_HORIZONTAL_BAR, PRAXIS_CHART_BACKEND_MOCK_MULTI_METRIC_BAR, PRAXIS_CHART_BACKEND_MOCK_SCATTER, PRAXIS_CHART_BACKEND_MOCK_STACKED_AREA, PRAXIS_CHART_BACKEND_MOCK_TIMESERIES, PRAXIS_CHART_COMPONENT_METADATA, PRAXIS_CHART_DRILLDOWN_DATA_BY_MONTH, PRAXIS_CHART_DRILLDOWN_PANEL_METADATA, PRAXIS_CHART_ENGINE, PRAXIS_CHART_PALETTE_TOKENS, PRAXIS_CHART_STATE_PROBE_COMPONENT_METADATA, PRAXIS_CHART_THEME_VARIANTS, PraxisChartBackendPayloadAdapterService, PraxisChartCanonicalContractMapperService, PraxisChartComponent, PraxisChartCompositionShowcaseComponent, PraxisChartConfigEditor, PraxisChartDataTransformerService, PraxisChartDrilldownPanelComponent, PraxisChartOptionBuilderService, PraxisChartSchemaMapperService, PraxisChartStateProbeComponent, PraxisChartStatsApiService, PraxisChartWidgetConfigEditor, PraxisMicroVisualizationComponent, buildPraxisChartInteractiveCanvasPage, buildPraxisChartInteractiveWidgetPage, buildPraxisChartMockCanvasPage, buildPraxisChartMockWidgetPage, createPraxisChartsI18nConfig, isPraxisChartPaletteToken, providePraxisChartDrilldownPanelMetadata, providePraxisChartStateProbeMetadata, providePraxisCharts, providePraxisChartsI18n, providePraxisChartsMetadata, resolvePraxisChartPaletteToken, resolvePraxisChartsText };