@oicl/openbridge-webcomponents 2.0.0-next.101 → 2.0.0-next.103
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/bundle/openbridge-webcomponents.bundle.js +580 -143
- package/bundle/openbridge-webcomponents.bundle.js.map +1 -1
- package/custom-elements.json +629 -407
- package/dist/bars-graphs/donut-chart/donut-chart.d.ts +18 -16
- package/dist/bars-graphs/donut-chart/donut-chart.d.ts.map +1 -1
- package/dist/bars-graphs/donut-chart/donut-chart.js.map +1 -1
- package/dist/bars-graphs/pie-chart/pie-chart.d.ts +14 -12
- package/dist/bars-graphs/pie-chart/pie-chart.d.ts.map +1 -1
- package/dist/bars-graphs/pie-chart/pie-chart.js.map +1 -1
- package/dist/bars-graphs/polar-chart/polar-chart.d.ts +19 -16
- package/dist/bars-graphs/polar-chart/polar-chart.d.ts.map +1 -1
- package/dist/bars-graphs/polar-chart/polar-chart.js.map +1 -1
- package/dist/bars-graphs/radial-bar-chart/radial-bar-chart.d.ts +8 -8
- package/dist/bars-graphs/radial-bar-chart/radial-bar-chart.d.ts.map +1 -1
- package/dist/bars-graphs/radial-bar-chart/radial-bar-chart.js.map +1 -1
- package/dist/building-blocks/chart-line/chart-line-base.d.ts +8 -25
- package/dist/building-blocks/chart-line/chart-line-base.d.ts.map +1 -1
- package/dist/building-blocks/chart-line/chart-line-base.js.map +1 -1
- package/dist/building-blocks/instrument-radial/instrument-radial.d.ts +22 -2
- package/dist/building-blocks/instrument-radial/instrument-radial.d.ts.map +1 -1
- package/dist/building-blocks/instrument-radial/instrument-radial.js +61 -37
- package/dist/building-blocks/instrument-radial/instrument-radial.js.map +1 -1
- package/dist/integration-systems/integration-bar/integration-bar.d.ts +20 -24
- package/dist/integration-systems/integration-bar/integration-bar.d.ts.map +1 -1
- package/dist/integration-systems/integration-bar/integration-bar.js.map +1 -1
- package/dist/integration-systems/integration-button/integration-button.d.ts +15 -13
- package/dist/integration-systems/integration-button/integration-button.d.ts.map +1 -1
- package/dist/integration-systems/integration-button/integration-button.js.map +1 -1
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.d.ts +14 -0
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.d.ts.map +1 -1
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js +30 -11
- package/dist/navigation-instruments/azimuth-thruster/azimuth-thruster.js.map +1 -1
- package/dist/navigation-instruments/compass/compass.d.ts +68 -31
- package/dist/navigation-instruments/compass/compass.d.ts.map +1 -1
- package/dist/navigation-instruments/compass/compass.js +36 -16
- package/dist/navigation-instruments/compass/compass.js.map +1 -1
- package/dist/navigation-instruments/compass-flat/compass-flat.d.ts +8 -9
- package/dist/navigation-instruments/compass-flat/compass-flat.d.ts.map +1 -1
- package/dist/navigation-instruments/compass-flat/compass-flat.js.map +1 -1
- package/dist/navigation-instruments/compass-sector/compass-sector.d.ts.map +1 -1
- package/dist/navigation-instruments/compass-sector/compass-sector.js.map +1 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js +34 -2
- package/dist/navigation-instruments/gauge-radial/gauge-radial.css.js.map +1 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts +15 -0
- package/dist/navigation-instruments/gauge-radial/gauge-radial.d.ts.map +1 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.js +35 -1
- package/dist/navigation-instruments/gauge-radial/gauge-radial.js.map +1 -1
- package/dist/navigation-instruments/gauge-trend/gauge-trend.d.ts +0 -5
- package/dist/navigation-instruments/gauge-trend/gauge-trend.d.ts.map +1 -1
- package/dist/navigation-instruments/gauge-trend/gauge-trend.js.map +1 -1
- package/dist/navigation-instruments/graph-mini/graph-mini.d.ts +1 -1
- package/dist/navigation-instruments/graph-mini/graph-mini.d.ts.map +1 -1
- package/dist/navigation-instruments/graph-mini/graph-mini.js.map +1 -1
- package/dist/navigation-instruments/heading/heading.d.ts +19 -1
- package/dist/navigation-instruments/heading/heading.d.ts.map +1 -1
- package/dist/navigation-instruments/heading/heading.js +34 -16
- package/dist/navigation-instruments/heading/heading.js.map +1 -1
- package/dist/navigation-instruments/indicator-graph/indicator-graph.d.ts +1 -1
- package/dist/navigation-instruments/indicator-graph/indicator-graph.d.ts.map +1 -1
- package/dist/navigation-instruments/indicator-graph/indicator-graph.js.map +1 -1
- package/dist/navigation-instruments/rudder/rudder.d.ts +15 -2
- package/dist/navigation-instruments/rudder/rudder.d.ts.map +1 -1
- package/dist/navigation-instruments/rudder/rudder.js +36 -26
- package/dist/navigation-instruments/rudder/rudder.js.map +1 -1
- package/dist/navigation-instruments/speed-gauge/speed-gauge.d.ts +15 -1
- package/dist/navigation-instruments/speed-gauge/speed-gauge.d.ts.map +1 -1
- package/dist/navigation-instruments/speed-gauge/speed-gauge.js +31 -3
- package/dist/navigation-instruments/speed-gauge/speed-gauge.js.map +1 -1
- package/dist/navigation-instruments/watch/watch.d.ts +45 -17
- package/dist/navigation-instruments/watch/watch.d.ts.map +1 -1
- package/dist/navigation-instruments/watch/watch.js +53 -38
- package/dist/navigation-instruments/watch/watch.js.map +1 -1
- package/dist/svghelpers/radial-frame.d.ts +122 -0
- package/dist/svghelpers/radial-frame.d.ts.map +1 -0
- package/dist/svghelpers/radial-frame.js +259 -0
- package/dist/svghelpers/radial-frame.js.map +1 -0
- package/package.json +1 -1
|
@@ -70,40 +70,42 @@ export type DonutChartDataItem = {
|
|
|
70
70
|
* </script>
|
|
71
71
|
* ```
|
|
72
72
|
*
|
|
73
|
-
* @property {Array<{label: string, value: number}>} data - Chart data segments (set via JavaScript)
|
|
74
|
-
* @property {string[]} colors - Custom segment colors (set via JavaScript) with fallback to theme palette
|
|
75
|
-
* @property {boolean} half - Whether to display as half-circle (180°) or full circle (360°), default: false
|
|
76
|
-
* @property {boolean} showOuterLabels - Show outer labels, default: false
|
|
77
|
-
* @property {boolean} showUnit - Whether to show unit in labels, default: false
|
|
78
|
-
* @property {string} outerLabelUnit - Unit string to append to outer labels, default: "%"
|
|
79
|
-
* @property {number} outerLabelMaxLength - Maximum character length for labels before trim (0 = no limit), default: 0
|
|
80
|
-
* @property {number} outerLabelDecimalPlaces - Number of decimal places in labels, default: 0
|
|
81
|
-
* @property {string} centerReadoutLabel - Text label shown below the center total value, default: "Total"
|
|
82
|
-
* @property {string} centerReadoutUnit - Unit string shown inline after the label in the center readout, default: "%"
|
|
83
|
-
* @property {number} max - Maximum value for calculating remaining empty sector, default: 100
|
|
84
|
-
* @property {number} thickness - Donut ring thickness in pixels, default: 24
|
|
85
|
-
* @property {boolean} showDebugOverlay - Show debug overlay for development, default: false
|
|
86
|
-
* @property {number} fixedHeight - Fixed height of the chart in pixels (mandatory, determines chart circumference), default: 320. The chart's circumference is always based on this fixed height to match other radial instruments.
|
|
87
|
-
* @property {boolean} legend - Whether to display the legend below the chart, default: false
|
|
88
73
|
* @beta
|
|
89
74
|
*/
|
|
90
75
|
export declare class ObcDonutChart extends LitElement {
|
|
76
|
+
/** Chart data segments (set via JavaScript) */
|
|
91
77
|
data: DonutChartDataItem[];
|
|
78
|
+
/** Custom segment colors (set via JavaScript) with fallback to theme palette */
|
|
92
79
|
colors: string[];
|
|
93
80
|
priority: Priority;
|
|
81
|
+
/** Whether to display as half-circle (180°) or full circle (360°), default: false */
|
|
94
82
|
half: boolean;
|
|
83
|
+
/** Show outer labels, default: false */
|
|
95
84
|
showOuterLabels: boolean;
|
|
85
|
+
/** Whether to show unit in labels, default: false */
|
|
96
86
|
showUnit: boolean;
|
|
87
|
+
/** Unit string to append to outer labels, default: "%" */
|
|
97
88
|
outerLabelUnit: string;
|
|
98
|
-
/**
|
|
89
|
+
/**
|
|
90
|
+
* Maximum character length for labels before trim (0 = no limit), default: 0
|
|
91
|
+
* @availableWhen showOuterLabels==true
|
|
92
|
+
*/
|
|
99
93
|
outerLabelMaxLength: number;
|
|
94
|
+
/** Number of decimal places in labels, default: 0 */
|
|
100
95
|
outerLabelDecimalPlaces: number;
|
|
96
|
+
/** Text label shown below the center total value, default: "Total" */
|
|
101
97
|
centerReadoutLabel: string;
|
|
98
|
+
/** Unit string shown inline after the label in the center readout, default: "%" */
|
|
102
99
|
centerReadoutUnit: string;
|
|
100
|
+
/** Maximum value for calculating remaining empty sector, default: 100 */
|
|
103
101
|
max: number;
|
|
102
|
+
/** Donut ring thickness in pixels, default: 24 */
|
|
104
103
|
thickness: number;
|
|
104
|
+
/** Whether to display the legend below the chart, default: false */
|
|
105
105
|
legend: boolean;
|
|
106
|
+
/** Show debug overlay for development, default: false */
|
|
106
107
|
showDebugOverlay: boolean;
|
|
108
|
+
/** Fixed height of the chart in pixels (determines chart circumference), default: 320. The chart's circumference is always based on this fixed height to match other radial instruments. */
|
|
107
109
|
fixedHeight: number;
|
|
108
110
|
/** @internal */
|
|
109
111
|
private total;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"donut-chart.d.ts","sourceRoot":"","sources":["../../../src/bars-graphs/donut-chart/donut-chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAkB,MAAM,KAAK,CAAC;AAOhE,OAAO,EAAC,QAAQ,EAAC,MAAM,uCAAuC,CAAC;AA8D/D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"donut-chart.d.ts","sourceRoot":"","sources":["../../../src/bars-graphs/donut-chart/donut-chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAkB,MAAM,KAAK,CAAC;AAOhE,OAAO,EAAC,QAAQ,EAAC,MAAM,uCAAuC,CAAC;AA8D/D,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,qBACa,aAAc,SAAQ,UAAU;IAC3C,+CAA+C;IAE/C,IAAI,EAAE,kBAAkB,EAAE,CAAM;IAEhC,gFAAgF;IAEhF,MAAM,EAAE,MAAM,EAAE,CAAM;IAGtB,QAAQ,EAAE,QAAQ,CAAoB;IAEtC,qFAAqF;IAErF,IAAI,UAAS;IAEb,wCAAwC;IAExC,eAAe,UAAS;IAExB,qDAAqD;IAErD,QAAQ,UAAS;IAEjB,0DAA0D;IAE1D,cAAc,SAAO;IAErB;;;OAGG;IAIH,mBAAmB,SAAK;IAExB,qDAAqD;IAIrD,uBAAuB,SAAK;IAE5B,sEAAsE;IAEtE,kBAAkB,SAAW;IAE7B,mFAAmF;IAEnF,iBAAiB,SAAO;IAExB,yEAAyE;IAEzE,GAAG,SAAO;IAEV,kDAAkD;IAElD,SAAS,SAAM;IAEf,oEAAoE;IAEpE,MAAM,UAAS;IAEf,yDAAyD;IAEzD,gBAAgB,UAAS;IAEzB,4LAA4L;IAE5L,WAAW,SAAO;IAElB,gBAAgB;IACP,OAAO,CAAC,KAAK,CAAK;IAE3B,iEAAiE;IACxD,OAAO,CAAC,eAAe,CAAgB;IAEhD,gBAAgB;IACC,OAAO,CAAC,QAAQ,CAAC,CAAoB;IAEtD,gBAAgB;IACE,OAAO,CAAC,SAAS,CAAC,CAAiB;IAErD,gBAAgB;IAChB,OAAO,CAAC,KAAK,CAAC,CAAQ;IAEtB,gBAAgB;IAChB,OAAO,CAAC,aAAa,CAAC,CAAmB;IAEzC,+GAA+G;IAC/G,OAAO,CAAC,cAAc,CAAC,CAAiB;IAExC,oEAAoE;IACpE,OAAO,CAAC,iBAAiB,CAAS;IAElC,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAgBd,UAAU,CAAC,OAAO,EAAE,cAAc;IAOlC,OAAO,CAAC,OAAO,EAAE,cAAc;IAoB/B,YAAY;IAMZ,oBAAoB;IAO7B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IA4B3B,OAAO,CAAC,gBAAgB;IA2BxB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAiB3B;;OAEG;IACH,OAAO,CAAC,eAAe;IAoFvB,OAAO,CAAC,2BAA2B;IAqBnC,OAAO,CAAC,8BAA8B;IA6KtC,OAAO,CAAC,eAAe;IAyCvB,OAAO,CAAC,WAAW;IA2BnB,OAAO,CAAC,WAAW;IAoBnB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAoBzB;;OAEG;IACH,OAAO,CAAC,YAAY;IAuDX,MAAM;IASf,OAAgB,MAAM,4BAKpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,iBAAiB,EAAE,aAAa,CAAC;KAClC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"donut-chart.js","sources":["../../../src/bars-graphs/donut-chart/donut-chart.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, unsafeCSS} from 'lit';\nimport {property, query, state} from 'lit/decorators.js';\nimport componentStyle from './donut-chart.css?inline';\nimport chartCommonStyle from '../../charthelpers/chart-common.css?inline';\nimport chartDebugStyle from '../../charthelpers/chart-debug.css?inline';\nimport chartLegendStyle from '../../charthelpers/chart-legend.css?inline';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../../navigation-instruments/types.js';\nimport {Chart, DoughnutController, ArcElement, Tooltip} from 'chart.js';\nimport type {Plugin, ChartOptions, ChartDataset} from 'chart.js';\nimport {\n CHART_SECTOR_DEFAULT_COLORS,\n CHART_SECTOR_ENHANCED_COLORS,\n CHART_DIMENSIONS,\n OUTER_LABEL_CONFIG,\n CENTER_READOUT_CONFIG,\n getCssVariableValue,\n getChartColorsOrDefault,\n observeThemeChanges,\n calculateSumTotal,\n formatNumericValue,\n createArcOuterLabelPlugin,\n calculateFixedHeightChartLayout,\n getChartTooltipOptions,\n generateLegendHTML,\n} from '../../charthelpers/index.js';\n\n// Register Chart.js components\nChart.register(DoughnutController, ArcElement, Tooltip);\n\n// Donut-specific dimension constants (extends shared CHART_DIMENSIONS)\nconst DONUT_DIMENSIONS = {\n ...CHART_DIMENSIONS,\n GAP_WIDTH: 0,\n GAP_AND_BORDER_COLOR: '--container-section-color',\n REMAINING_COLOR: '--border-outline-color',\n BORDER_RADIUS: 4,\n} as const;\n\nconst DONUT_RECREATE_PROP_NAMES = [\n 'half',\n 'showOuterLabels',\n 'showUnit',\n 'outerLabelUnit',\n 'outerLabelMaxLength',\n 'outerLabelDecimalPlaces',\n 'showDebugOverlay',\n 'fixedHeight',\n] as const;\n\nconst DONUT_WATCHED_PROP_NAMES = [\n 'legend',\n 'data',\n 'colors',\n 'priority',\n 'half',\n 'thickness',\n 'max',\n 'showOuterLabels',\n 'showUnit',\n 'centerReadoutLabel',\n 'centerReadoutUnit',\n 'outerLabelUnit',\n 'outerLabelMaxLength',\n 'outerLabelDecimalPlaces',\n 'showDebugOverlay',\n 'fixedHeight',\n] as const;\n\nexport type DonutChartDataItem = {\n label: string;\n value: number;\n};\n\n/**\n * `<obc-donut-chart>` – A customizable donut chart component for visualizing proportional data with a center total readout.\n *\n * This component renders an interactive donut chart powered by Chart.js, displaying data segments as arcs with optional outer labels and a centered total value. It supports both full-circle (360°) and half-circle (180°) layouts, making it versatile for dashboards, analytics, and data visualization interfaces.\n *\n * The chart automatically calculates percentages, handles remaining/unfilled capacity, and adapts its layout based on available space. Labels and center readouts are hidden when the chart is too small (< 192px height), ensuring visual clarity at all sizes.\n *\n * ## Features\n * - **Fixed Height ⇒ Fixed Circumference:** The chart's circumference is determined by the `fixedHeight` property (default: 320px). This ensures the donut's circumference remains consistent and matches other radial instruments, regardless of the available browser or container width. The chart does not scale to fill the width; instead, it always uses the specified fixed height to define its size and circumference.\n * - **Layout Modes:**\n * - `Full Circle` (default): Complete 360° donut chart.\n * - `Half Circle`: Semicircular 180° layout, useful for gauges or space-constrained displays.\n * - **Center Readout:**\n * - Displays the sum total of all data values with a customizable label (e.g., \"Total\", \"Power\", \"Usage\").\n * - **Outer Labels:**\n * - Optional labels positioned outside the chart showing segment names and values.\n * - Supports percentage or custom units (e.g., \"kW\", \"kg\", \"MB\").\n * - Configurable decimal places and maximum label length (with trimming).\n * - **Capacity Visualization:**\n * - Optionally show remaining/unfilled capacity when `max` is set higher than the total.\n * - Remaining sector uses a distinct color to indicate available space.\n * - **Customization:**\n * - Custom segment colors (with automatic fallback to theme palette).\n * - Adjustable ring thickness (default 24px).\n * - **Color Priority:** Set `priority` to `Priority.enhanced` to use the blue/enhanced\n * color palette instead of the default gray/regular palette (default: `Priority.regular`).\n * - **Responsive Behavior:**\n * - Automatically hides labels and center readout when height < 192px.\n * - Maintains aspect ratio and adjusts padding for optimal label positioning.\n * - **Theme Integration:**\n * - Colors update automatically when the `data-obc-theme` attribute changes on the `<html>` element.\n * - Example:\n * ```\n * <html lang=\"en\" data-obc-theme=\"day\"></html>\n * ```\n *\n * ## Example\n *\n * **Basic Usage (Half Circle)**\n * ```html\n * <obc-donut-chart\n * half\n * ></obc-donut-chart>\n * <script>\n * document.querySelector('obc-donut-chart').data = [\n * {label: 'Engine', value: 75.5},\n * {label: 'HVAC', value: 42.3},\n * {label: 'Lights', value: 12.8}\n * ];\n * </script>\n * ```\n *\n * **Custom Colors**\n * ```html\n * <obc-donut-chart></obc-donut-chart>\n * <script>\n * const chart = document.querySelector('obc-donut-chart');\n * chart.data = [\n * {label: 'Critical', value: 20},\n * {label: 'Warning', value: 35},\n * {label: 'Normal', value: 45}\n * ];\n * chart.colors = ['#e74c3c', '#f39c12', '#2ecc71'];\n * </script>\n * ```\n *\n * @property {Array<{label: string, value: number}>} data - Chart data segments (set via JavaScript)\n * @property {string[]} colors - Custom segment colors (set via JavaScript) with fallback to theme palette\n * @property {boolean} half - Whether to display as half-circle (180°) or full circle (360°), default: false\n * @property {boolean} showOuterLabels - Show outer labels, default: false\n * @property {boolean} showUnit - Whether to show unit in labels, default: false\n * @property {string} outerLabelUnit - Unit string to append to outer labels, default: \"%\"\n * @property {number} outerLabelMaxLength - Maximum character length for labels before trim (0 = no limit), default: 0\n * @property {number} outerLabelDecimalPlaces - Number of decimal places in labels, default: 0\n * @property {string} centerReadoutLabel - Text label shown below the center total value, default: \"Total\"\n * @property {string} centerReadoutUnit - Unit string shown inline after the label in the center readout, default: \"%\"\n * @property {number} max - Maximum value for calculating remaining empty sector, default: 100\n * @property {number} thickness - Donut ring thickness in pixels, default: 24\n * @property {boolean} showDebugOverlay - Show debug overlay for development, default: false\n * @property {number} fixedHeight - Fixed height of the chart in pixels (mandatory, determines chart circumference), default: 320. The chart's circumference is always based on this fixed height to match other radial instruments.\n * @property {boolean} legend - Whether to display the legend below the chart, default: false\n * @beta\n */\n@customElement('obc-donut-chart')\nexport class ObcDonutChart extends LitElement {\n @property({type: Array, attribute: false})\n data: DonutChartDataItem[] = [];\n\n @property({type: Array, attribute: false})\n colors: string[] = [];\n\n @property({type: String})\n priority: Priority = Priority.regular;\n\n @property({type: Boolean, reflect: true})\n half = false;\n\n @property({type: Boolean})\n showOuterLabels = false;\n\n @property({type: Boolean})\n showUnit = false;\n\n @property({type: String})\n outerLabelUnit = '%';\n\n /** @availableWhen showOuterLabels==true */\n @property({\n type: Number,\n })\n outerLabelMaxLength = 0;\n\n @property({\n type: Number,\n })\n outerLabelDecimalPlaces = 0;\n\n @property({type: String})\n centerReadoutLabel = 'Total';\n\n @property({type: String})\n centerReadoutUnit = '%';\n\n @property({type: Number})\n max = 100;\n\n @property({type: Number})\n thickness = 24;\n\n @property({type: Boolean, reflect: true})\n legend = false;\n\n @property({type: Boolean, reflect: true})\n showDebugOverlay = false;\n\n @property({type: Number, reflect: true})\n fixedHeight = 320;\n\n /** @internal */\n @state() private total = 0;\n\n /** @internal - Pre-formatted labels for outer label rendering */\n @state() private formattedLabels: string[] = [];\n\n /** @internal */\n @query('canvas') private canvasEl?: HTMLCanvasElement;\n\n /** @internal */\n @query('.legend') private legendDiv?: HTMLDivElement;\n\n /** @internal */\n private chart?: Chart;\n\n /** @internal */\n private themeObserver?: MutationObserver;\n\n /** @internal - ResizeObserver for tracking height threshold crossings (e.g. MIN_HEIGHT_WITH_LABELS = 192px) */\n private resizeObserver?: ResizeObserver;\n\n /** @internal - Track previous state to detect threshold crossing */\n private wasAboveThreshold = false;\n\n private hasAnyChanged(\n changed: PropertyValues,\n props: readonly (keyof ObcDonutChart)[]\n ): boolean {\n return props.some((prop) => changed.has(prop));\n }\n\n /**\n * Get layout configuration for canvas calculation\n */\n private getLayoutConfig() {\n // Denominator: use max if set, otherwise total, with minimum of 1\n const denominator =\n this.max > 0 ? this.max : this.total > 0 ? this.total : 1;\n\n return {\n unit: this.outerLabelUnit,\n showUnit: this.showUnit,\n outerLabelMaxLength: this.outerLabelMaxLength,\n decimalPlaces: this.outerLabelDecimalPlaces,\n data: this.data,\n denominator,\n };\n }\n\n // Calculate derived state BEFORE render\n override willUpdate(changed: PropertyValues) {\n if (changed.has('data')) {\n this.total = calculateSumTotal(this.data);\n }\n }\n\n // Update external library AFTER render\n override updated(changed: PropertyValues) {\n super.updated(changed);\n\n if (this.hasAnyChanged(changed, DONUT_WATCHED_PROP_NAMES)) {\n // Recreate chart when major layout properties change or when plugin configuration changes\n // These properties affect aspect ratio calculation, plugin registration, or outer label rendering\n const needsRecreation = this.hasAnyChanged(\n changed,\n DONUT_RECREATE_PROP_NAMES\n );\n\n if (needsRecreation) {\n this.chart?.destroy();\n this.createChart();\n } else {\n this.updateChart();\n }\n }\n }\n\n override firstUpdated() {\n this.createChart();\n this.themeObserver = observeThemeChanges(() => this.updateChartColors());\n this.setupResizeObserver();\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.chart?.destroy();\n this.themeObserver?.disconnect();\n this.resizeObserver?.disconnect();\n }\n\n /**\n * Setup resize observer to detect height threshold crossings\n * Recreates chart when crossing MIN_HEIGHT_WITH_LABELS (192px) to show/hide labels\n * Detect when fixedHeight property changes programmatically (e.g., via Storybook controls or user code)\n */\n private setupResizeObserver() {\n if (!this.canvasEl) return;\n\n this.resizeObserver = new ResizeObserver(() => {\n if (!this.chart) return;\n\n const height = this.canvasEl?.clientHeight ?? 0;\n const isAboveThreshold =\n height >= CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n\n // Only recreate chart if we crossed the threshold\n if (isAboveThreshold !== this.wasAboveThreshold) {\n this.wasAboveThreshold = isAboveThreshold;\n this.chart.destroy();\n this.createChart();\n } else {\n // Height changed but didn't cross threshold - just update\n this.updateChart();\n }\n });\n\n this.resizeObserver.observe(this.canvasEl);\n\n // Initialize threshold state\n const height = this.canvasEl.clientHeight;\n this.wasAboveThreshold = height >= CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n }\n\n private prepareChartData() {\n const values = this.data.map((d) => d.value);\n const labels = this.data.map((d) => d.label);\n const remaining = Math.max(0, this.max - this.total);\n const chartColors = getChartColorsOrDefault(\n this,\n this.colors,\n this.priority === Priority.enhanced\n ? CHART_SECTOR_ENHANCED_COLORS\n : CHART_SECTOR_DEFAULT_COLORS\n );\n const segmentColors = values.map(\n (_, index) =>\n chartColors[index % chartColors.length] ??\n getCssVariableValue(this, DONUT_DIMENSIONS.REMAINING_COLOR)\n );\n\n return {\n values: [...values, remaining],\n labels: [...labels, 'Remaining'],\n colors: [\n ...segmentColors,\n getCssVariableValue(this, DONUT_DIMENSIONS.REMAINING_COLOR),\n ],\n };\n }\n\n /**\n * Build a dataset configuration object shared by both createChart and updateChart\n */\n private createDatasetConfig(\n values: number[],\n colors: (string | CanvasGradient | CanvasPattern)[]\n ): ChartDataset<'doughnut', number[]> {\n return {\n data: values,\n backgroundColor: colors,\n borderWidth: 1,\n borderColor: getCssVariableValue(\n this,\n DONUT_DIMENSIONS.GAP_AND_BORDER_COLOR\n ),\n borderRadius: this.getBorderRadius(values),\n spacing: DONUT_DIMENSIONS.GAP_WIDTH,\n };\n }\n\n /**\n * Get Chart.js options using centralized fixed height layout calculation\n */\n private getChartOptions(): ChartOptions<'doughnut'> {\n // Use centralized layout calculation helper\n const dimensions = calculateFixedHeightChartLayout({\n fixedHeight: this.fixedHeight,\n isHalfMode: this.half,\n showOuterLabels: this.showOuterLabels,\n canvasEl: this.canvasEl,\n layoutConfig: this.getLayoutConfig(),\n host: this,\n });\n\n // Store formatted labels for use in plugins\n this.formattedLabels = dimensions.formattedLabels;\n\n // Set CSS variables for wrapper and canvas sizing\n this.style.setProperty('--chart-width', `${dimensions.calculatedWidth}px`);\n this.style.setProperty('--chart-height', `${dimensions.actualHeight}px`);\n\n // Calculate dynamic padding for Chart.js layout\n const dynamicPadding = dimensions.isTooSmall\n ? {top: 0, right: 0, bottom: 0, left: 0}\n : {\n top: dimensions.topPadding,\n right: dimensions.rightPadding,\n bottom: dimensions.bottomPadding,\n left: dimensions.leftPadding,\n };\n\n return {\n responsive: true,\n maintainAspectRatio: true,\n aspectRatio: dimensions.aspectRatio,\n rotation: this.half ? -90 : 0,\n circumference: this.half ? 180 : 360,\n cutout: `${((DONUT_DIMENSIONS.CHART_WIDTH - this.thickness * 2) / DONUT_DIMENSIONS.CHART_WIDTH) * 100}%`,\n layout: {\n padding: dynamicPadding ?? DONUT_DIMENSIONS.CANVAS_PADDING,\n },\n plugins: {\n legend: {\n display: false,\n labels: {\n generateLabels: () => [], // Prevent Chart.js from generating labels internally\n },\n onClick: () => {}, // Disable legend click handler\n },\n tooltip: {\n ...getChartTooltipOptions(this),\n enabled: !dimensions.isTooSmall,\n filter: (tooltipItem) => tooltipItem.label !== 'Remaining',\n callbacks: {\n title: () => '', // No title line\n label: (context) => {\n const label = context.label ?? '';\n const value = context.parsed;\n // Denominator: use max if set, otherwise total, with minimum of 1\n const denominator =\n this.max > 0 ? this.max : this.total > 0 ? this.total : 1;\n // Calculate percentage if unit is \"%\", otherwise use raw value\n const isPercentage = this.outerLabelUnit === '%';\n const numericValue = formatNumericValue(\n value,\n denominator,\n isPercentage,\n this.outerLabelDecimalPlaces\n );\n const showUnit = this.showUnit && this.outerLabelUnit;\n // Chart.js core only supports string/array-of-string for label callback\n // For now, return a single string (styled via global tooltip options)\n // To support per-span styling, a custom HTML tooltip plugin is needed\n return showUnit\n ? `${label} ${numericValue}${this.outerLabelUnit}`\n : `${label} ${numericValue}`;\n },\n },\n },\n },\n animation: {\n animateRotate: false,\n animateScale: false,\n },\n };\n }\n\n private createOuterLabelDonutPlugin(): Plugin<'doughnut'> {\n const basePlugin = createArcOuterLabelPlugin(this, {\n formattedLabels: this.formattedLabels,\n }) as Plugin<'doughnut'>;\n\n // Wrap the afterDatasetsDraw to check height first\n const originalAfterDatasetsDraw = basePlugin.afterDatasetsDraw;\n if (originalAfterDatasetsDraw) {\n basePlugin.afterDatasetsDraw = (chart, args, pluginOptions, options) => {\n // Check height before drawing labels\n const canvasHeight = this.canvasEl?.clientHeight ?? 0;\n if (canvasHeight < CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS) {\n return;\n }\n originalAfterDatasetsDraw(chart, args, pluginOptions, options);\n };\n }\n\n return basePlugin;\n }\n\n private createCenterReadoutDonutPlugin(): Plugin<'doughnut'> {\n return {\n id: 'centerText',\n beforeDraw: (chart) => {\n const {ctx, chartArea} = chart;\n const {width, height, left, top} = chartArea;\n\n // Hide center readout if canvas is too small\n const canvasHeight = this.canvasEl?.clientHeight ?? 0;\n if (canvasHeight < CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS) {\n return;\n }\n\n ctx.save();\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n\n const centerX = left + width / 2;\n const fontFamily = getCssVariableValue(\n this,\n OUTER_LABEL_CONFIG.fontFamily\n );\n const lineGap = 4;\n\n // Setup and measure centered readout value text\n const valueFontWeight = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.value.fontWeightVar\n );\n const valueFontSize = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.value.fontSizeVar\n );\n const valueColor = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.value.fontColorVar\n );\n ctx.font = `${valueFontWeight} ${valueFontSize} ${fontFamily}`;\n // Center readout always shows raw total value without decimal places\n const centerValueText = this.total.toFixed(0);\n const valueMetrics = ctx.measureText(centerValueText);\n const valueHeight =\n valueMetrics.actualBoundingBoxAscent +\n valueMetrics.actualBoundingBoxDescent;\n\n // Setup and measure centered readout label and unit text (inline, different styles)\n const labelFontWeight = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.label.fontWeightVar\n );\n const labelFontSize = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.label.fontSizeVar\n );\n const labelColor = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.label.fontColorVar\n );\n const unitFontWeight = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.unit.fontWeightVar\n );\n const unitFontSize = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.unit.fontSizeVar\n );\n const unitColor = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.unit.fontColorVar\n );\n const centerReadoutLabelText = this.centerReadoutLabel;\n const centerReadoutUnitText = this.centerReadoutUnit;\n const space = centerReadoutUnitText ? ' ' : '';\n ctx.font = `${labelFontWeight} ${labelFontSize} ${fontFamily}`;\n const labelMetrics = ctx.measureText(centerReadoutLabelText);\n const spaceMetrics = ctx.measureText(space);\n ctx.font = `${unitFontWeight} ${unitFontSize} ${fontFamily}`;\n const unitMetrics = ctx.measureText(centerReadoutUnitText);\n // Height is max of label and unit\n const labelHeight = Math.max(\n labelMetrics.actualBoundingBoxAscent +\n labelMetrics.actualBoundingBoxDescent,\n unitMetrics.actualBoundingBoxAscent +\n unitMetrics.actualBoundingBoxDescent\n );\n\n // Calculate Y positions\n let valueY: number;\n let labelY: number;\n\n if (this.half) {\n // For half donut: Get the actual arc center Y position from the chart metadata\n const meta = chart.getDatasetMeta(0);\n const arcCenterY = meta.data[0]\n ? (meta.data[0] as ArcElement).y\n : top + height;\n labelY =\n arcCenterY -\n Math.max(\n labelMetrics.actualBoundingBoxDescent,\n unitMetrics.actualBoundingBoxDescent\n );\n valueY =\n labelY -\n labelHeight -\n lineGap -\n valueHeight +\n valueMetrics.actualBoundingBoxAscent;\n } else {\n // For full donut: center both lines vertically as a unit\n const totalTextHeight = valueHeight + lineGap + labelHeight;\n const centerY = top + height / 2;\n valueY =\n centerY -\n totalTextHeight / 2 +\n valueMetrics.actualBoundingBoxAscent;\n labelY =\n valueY +\n valueMetrics.actualBoundingBoxDescent +\n lineGap +\n Math.max(\n labelMetrics.actualBoundingBoxAscent,\n unitMetrics.actualBoundingBoxAscent\n );\n }\n\n // Draw centered readout value\n ctx.font = `${valueFontWeight} ${valueFontSize} ${fontFamily}`;\n ctx.fillStyle = valueColor;\n ctx.fillText(centerValueText, centerX, valueY);\n\n // Draw centered readout label and unit inline, with different styles\n // Measure total width for centering\n ctx.font = `${labelFontWeight} ${labelFontSize} ${fontFamily}`;\n const labelWidth = labelMetrics.width;\n const spaceWidth = spaceMetrics.width;\n ctx.font = `${unitFontWeight} ${unitFontSize} ${fontFamily}`;\n const unitWidth = unitMetrics.width;\n const totalWidth =\n labelWidth + (centerReadoutUnitText ? spaceWidth + unitWidth : 0);\n // Draw label\n ctx.font = `${labelFontWeight} ${labelFontSize} ${fontFamily}`;\n ctx.fillStyle = labelColor;\n ctx.fillText(\n centerReadoutLabelText,\n centerX - totalWidth / 2 + labelWidth / 2,\n labelY\n );\n // Draw space and unit (if present)\n if (centerReadoutUnitText) {\n // Draw space (in label font)\n ctx.font = `${labelFontWeight} ${labelFontSize} ${fontFamily}`;\n ctx.fillStyle = labelColor;\n ctx.fillText(\n space,\n centerX - totalWidth / 2 + labelWidth + spaceWidth / 2,\n labelY\n );\n // Draw unit (in unit font)\n ctx.font = `${unitFontWeight} ${unitFontSize} ${fontFamily}`;\n ctx.fillStyle = unitColor;\n ctx.fillText(\n centerReadoutUnitText,\n centerX + totalWidth / 2 - unitWidth / 2,\n labelY\n );\n }\n\n ctx.restore();\n },\n };\n }\n\n private getBorderRadius(values: number[]) {\n // Full donuts don't need border radius (from Figma design)\n if (!this.half) {\n return undefined;\n }\n\n // For half donuts, apply different radius to first and last segments (detail from Figma)\n const remaining = Math.max(0, this.max - this.total);\n const hasRemainingSegment = remaining > 0;\n\n return values.map((_value, index) => {\n // First segment gets left-side radius\n if (index === 0) {\n return {\n outerStart: DONUT_DIMENSIONS.BORDER_RADIUS,\n outerEnd: 0,\n innerStart: DONUT_DIMENSIONS.BORDER_RADIUS,\n innerEnd: 0,\n };\n }\n\n // Last visible segment gets right-side radius\n // If there's a remaining segment, it's always last; otherwise the last data segment is last\n const isLastVisibleSegment = hasRemainingSegment\n ? index === values.length - 1\n : index === values.length - 2;\n\n if (isLastVisibleSegment) {\n return {\n outerStart: 0,\n outerEnd: DONUT_DIMENSIONS.BORDER_RADIUS,\n innerStart: 0,\n innerEnd: DONUT_DIMENSIONS.BORDER_RADIUS,\n };\n }\n\n // Middle segments don't need radius\n return 0;\n });\n }\n\n private createChart() {\n // Guard: Verify canvas exists and is connected to DOM\n if (!this.canvasEl || !this.canvasEl.isConnected) return;\n\n const ctx = this.canvasEl.getContext('2d');\n if (!ctx) return;\n\n const {values, labels, colors} = this.prepareChartData();\n\n this.chart = new Chart(ctx, {\n type: 'doughnut',\n data: {\n labels,\n datasets: [this.createDatasetConfig(values, colors)],\n },\n options: this.getChartOptions(),\n plugins: [\n // Always include plugins; they check height internally during rendering\n ...(this.showOuterLabels ? [this.createOuterLabelDonutPlugin()] : []),\n this.createCenterReadoutDonutPlugin(),\n ],\n });\n\n // Defer legend update to next tick to ensure Chart.js metadata is initialized\n requestAnimationFrame(() => this.updateLegend());\n }\n\n private updateChart() {\n // Guard: Verify chart and canvas still exist and are connected\n if (!this.chart || !this.canvasEl || !this.canvasEl.isConnected) return;\n\n const {values, labels, colors} = this.prepareChartData();\n\n this.chart.data.labels = labels;\n this.chart.data.datasets = [this.createDatasetConfig(values, colors)];\n\n const latestOptions = this.getChartOptions();\n if (this.chart.options) {\n Object.assign(this.chart.options, latestOptions);\n }\n\n this.chart.update();\n\n // Update legend after chart update completes to ensure metadata is ready\n requestAnimationFrame(() => this.updateLegend());\n }\n\n /**\n * Update only chart colors without recalculating layout\n * Used by theme observer for efficient theme changes\n */\n private updateChartColors() {\n if (!this.chart) return;\n\n const {colors} = this.prepareChartData();\n\n // Update dataset colors\n if (this.chart.data.datasets[0]) {\n this.chart.data.datasets[0].backgroundColor = colors;\n this.chart.data.datasets[0].borderColor = getCssVariableValue(\n this,\n DONUT_DIMENSIONS.GAP_AND_BORDER_COLOR\n );\n }\n\n // Update without animation for instant theme change\n this.chart.update('none');\n\n this.updateLegend();\n }\n\n /**\n * Update the legend HTML content\n */\n private updateLegend() {\n // Guard: Check if legend should be shown and chart is ready\n if (!this.legend || !this.legendDiv || !this.chart) return;\n\n // Guard: Check if chart metadata is available\n const meta = this.chart.getDatasetMeta(0);\n if (!meta || !meta.controller) {\n // console.debug('[obc-donut-chart] updateLegend: skipped - chart metadata not yet initialized');\n return;\n }\n\n // Guard: Check if dataset has data\n if (!this.data || this.data.length === 0) {\n // console.debug('[obc-donut-chart] updateLegend: skipped - no data available');\n this.legendDiv.innerHTML = '';\n return;\n }\n\n // Denominator: use max if set, otherwise total, with minimum of 1\n const denominator =\n this.max > 0 ? this.max : this.total > 0 ? this.total : 1;\n const isPercentage = this.outerLabelUnit === '%';\n\n try {\n const legendItems = this.data.map((item, i) => {\n const style = meta.controller.getStyle(i, false);\n const numericValue = formatNumericValue(\n item.value,\n denominator,\n isPercentage,\n this.outerLabelDecimalPlaces\n );\n const showUnit = this.showUnit && this.outerLabelUnit;\n const value = `${numericValue}`;\n const unit = showUnit ? `${this.outerLabelUnit}` : '';\n\n return {\n fillStyle: style.backgroundColor as string,\n label: item.label as string,\n value: value as string,\n unit: unit as string,\n };\n });\n\n const legendHTML = generateLegendHTML(legendItems);\n this.legendDiv.innerHTML = legendHTML;\n } catch (error) {\n console.debug(\n '[obc-donut-chart] updateLegend: error generating legend HTML',\n error\n );\n // Silent failure - don't throw, just skip legend update this time\n }\n }\n\n override render() {\n return html`\n <div class=\"wrapper\">\n <canvas></canvas>\n ${this.legend ? html`<div class=\"legend\"></div>` : ''}\n </div>\n `;\n }\n\n static override styles = [\n unsafeCSS(componentStyle),\n unsafeCSS(chartCommonStyle),\n unsafeCSS(chartLegendStyle),\n unsafeCSS(chartDebugStyle),\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-donut-chart': ObcDonutChart;\n }\n}\n"],"names":["height"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAM,SAAS,oBAAoB,YAAY,OAAO;AAGtD,MAAM,mBAAmB;AAAA,EACvB,GAAG;AAAA,EACH,WAAW;AAAA,EACX,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EACjB,eAAe;AACjB;AAEA,MAAM,4BAA4B;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,2BAA2B;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AA2FO,IAAM,gBAAN,cAA4B,WAAW;AAAA,EAAvC,cAAA;AAAA,UAAA,GAAA,SAAA;AAEL,SAAA,OAA6B,CAAA;AAG7B,SAAA,SAAmB,CAAA;AAGnB,SAAA,WAAqB,SAAS;AAG9B,SAAA,OAAO;AAGP,SAAA,kBAAkB;AAGlB,SAAA,WAAW;AAGX,SAAA,iBAAiB;AAMjB,SAAA,sBAAsB;AAKtB,SAAA,0BAA0B;AAG1B,SAAA,qBAAqB;AAGrB,SAAA,oBAAoB;AAGpB,SAAA,MAAM;AAGN,SAAA,YAAY;AAGZ,SAAA,SAAS;AAGT,SAAA,mBAAmB;AAGnB,SAAA,cAAc;AAGL,SAAQ,QAAQ;AAGhB,SAAQ,kBAA4B,CAAA;AAkB7C,SAAQ,oBAAoB;AAAA,EAAA;AAAA,EAEpB,cACN,SACA,OACS;AACT,WAAO,MAAM,KAAK,CAAC,SAAS,QAAQ,IAAI,IAAI,CAAC;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAAkB;AAExB,UAAM,cACJ,KAAK,MAAM,IAAI,KAAK,MAAM,KAAK,QAAQ,IAAI,KAAK,QAAQ;AAE1D,WAAO;AAAA,MACL,MAAM,KAAK;AAAA,MACX,UAAU,KAAK;AAAA,MACf,qBAAqB,KAAK;AAAA,MAC1B,eAAe,KAAK;AAAA,MACpB,MAAM,KAAK;AAAA,MACX;AAAA,IAAA;AAAA,EAEJ;AAAA;AAAA,EAGS,WAAW,SAAyB;AAC3C,QAAI,QAAQ,IAAI,MAAM,GAAG;AACvB,WAAK,QAAQ,kBAAkB,KAAK,IAAI;AAAA,IAC1C;AAAA,EACF;AAAA;AAAA,EAGS,QAAQ,SAAyB;AACxC,UAAM,QAAQ,OAAO;AAErB,QAAI,KAAK,cAAc,SAAS,wBAAwB,GAAG;AAGzD,YAAM,kBAAkB,KAAK;AAAA,QAC3B;AAAA,QACA;AAAA,MAAA;AAGF,UAAI,iBAAiB;AACnB,aAAK,OAAO,QAAA;AACZ,aAAK,YAAA;AAAA,MACP,OAAO;AACL,aAAK,YAAA;AAAA,MACP;AAAA,IACF;AAAA,EACF;AAAA,EAES,eAAe;AACtB,SAAK,YAAA;AACL,SAAK,gBAAgB,oBAAoB,MAAM,KAAK,mBAAmB;AACvE,SAAK,oBAAA;AAAA,EACP;AAAA,EAES,uBAAuB;AAC9B,UAAM,qBAAA;AACN,SAAK,OAAO,QAAA;AACZ,SAAK,eAAe,WAAA;AACpB,SAAK,gBAAgB,WAAA;AAAA,EACvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,sBAAsB;AAC5B,QAAI,CAAC,KAAK,SAAU;AAEpB,SAAK,iBAAiB,IAAI,eAAe,MAAM;AAC7C,UAAI,CAAC,KAAK,MAAO;AAEjB,YAAMA,UAAS,KAAK,UAAU,gBAAgB;AAC9C,YAAM,mBACJA,WAAU,iBAAiB;AAG7B,UAAI,qBAAqB,KAAK,mBAAmB;AAC/C,aAAK,oBAAoB;AACzB,aAAK,MAAM,QAAA;AACX,aAAK,YAAA;AAAA,MACP,OAAO;AAEL,aAAK,YAAA;AAAA,MACP;AAAA,IACF,CAAC;AAED,SAAK,eAAe,QAAQ,KAAK,QAAQ;AAGzC,UAAM,SAAS,KAAK,SAAS;AAC7B,SAAK,oBAAoB,UAAU,iBAAiB;AAAA,EACtD;AAAA,EAEQ,mBAAmB;AACzB,UAAM,SAAS,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE,KAAK;AAC3C,UAAM,SAAS,KAAK,KAAK,IAAI,CAAC,MAAM,EAAE,KAAK;AAC3C,UAAM,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK;AACnD,UAAM,cAAc;AAAA,MAClB;AAAA,MACA,KAAK;AAAA,MACL,KAAK,aAAa,SAAS,WACvB,+BACA;AAAA,IAAA;AAEN,UAAM,gBAAgB,OAAO;AAAA,MAC3B,CAAC,GAAG,UACF,YAAY,QAAQ,YAAY,MAAM,KACtC,oBAAoB,MAAM,iBAAiB,eAAe;AAAA,IAAA;AAG9D,WAAO;AAAA,MACL,QAAQ,CAAC,GAAG,QAAQ,SAAS;AAAA,MAC7B,QAAQ,CAAC,GAAG,QAAQ,WAAW;AAAA,MAC/B,QAAQ;AAAA,QACN,GAAG;AAAA,QACH,oBAAoB,MAAM,iBAAiB,eAAe;AAAA,MAAA;AAAA,IAC5D;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA,EAKQ,oBACN,QACA,QACoC;AACpC,WAAO;AAAA,MACL,MAAM;AAAA,MACN,iBAAiB;AAAA,MACjB,aAAa;AAAA,MACb,aAAa;AAAA,QACX;AAAA,QACA,iBAAiB;AAAA,MAAA;AAAA,MAEnB,cAAc,KAAK,gBAAgB,MAAM;AAAA,MACzC,SAAS,iBAAiB;AAAA,IAAA;AAAA,EAE9B;AAAA;AAAA;AAAA;AAAA,EAKQ,kBAA4C;AAElD,UAAM,aAAa,gCAAgC;AAAA,MACjD,aAAa,KAAK;AAAA,MAClB,YAAY,KAAK;AAAA,MACjB,iBAAiB,KAAK;AAAA,MACtB,UAAU,KAAK;AAAA,MACf,cAAc,KAAK,gBAAA;AAAA,MACnB,MAAM;AAAA,IAAA,CACP;AAGD,SAAK,kBAAkB,WAAW;AAGlC,SAAK,MAAM,YAAY,iBAAiB,GAAG,WAAW,eAAe,IAAI;AACzE,SAAK,MAAM,YAAY,kBAAkB,GAAG,WAAW,YAAY,IAAI;AAGvE,UAAM,iBAAiB,WAAW,aAC9B,EAAC,KAAK,GAAG,OAAO,GAAG,QAAQ,GAAG,MAAM,EAAA,IACpC;AAAA,MACE,KAAK,WAAW;AAAA,MAChB,OAAO,WAAW;AAAA,MAClB,QAAQ,WAAW;AAAA,MACnB,MAAM,WAAW;AAAA,IAAA;AAGvB,WAAO;AAAA,MACL,YAAY;AAAA,MACZ,qBAAqB;AAAA,MACrB,aAAa,WAAW;AAAA,MACxB,UAAU,KAAK,OAAO,MAAM;AAAA,MAC5B,eAAe,KAAK,OAAO,MAAM;AAAA,MACjC,QAAQ,IAAK,iBAAiB,cAAc,KAAK,YAAY,KAAK,iBAAiB,cAAe,GAAG;AAAA,MACrG,QAAQ;AAAA,QACN,SAAS,kBAAkB,iBAAiB;AAAA,MAAA;AAAA,MAE9C,SAAS;AAAA,QACP,QAAQ;AAAA,UACN,SAAS;AAAA,UACT,QAAQ;AAAA,YACN,gBAAgB,MAAM,CAAA;AAAA;AAAA,UAAC;AAAA,UAEzB,SAAS,MAAM;AAAA,UAAC;AAAA;AAAA,QAAA;AAAA,QAElB,SAAS;AAAA,UACP,GAAG,uBAAuB,IAAI;AAAA,UAC9B,SAAS,CAAC,WAAW;AAAA,UACrB,QAAQ,CAAC,gBAAgB,YAAY,UAAU;AAAA,UAC/C,WAAW;AAAA,YACT,OAAO,MAAM;AAAA;AAAA,YACb,OAAO,CAAC,YAAY;AAClB,oBAAM,QAAQ,QAAQ,SAAS;AAC/B,oBAAM,QAAQ,QAAQ;AAEtB,oBAAM,cACJ,KAAK,MAAM,IAAI,KAAK,MAAM,KAAK,QAAQ,IAAI,KAAK,QAAQ;AAE1D,oBAAM,eAAe,KAAK,mBAAmB;AAC7C,oBAAM,eAAe;AAAA,gBACnB;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA,KAAK;AAAA,cAAA;AAEP,oBAAM,WAAW,KAAK,YAAY,KAAK;AAIvC,qBAAO,WACH,GAAG,KAAK,IAAI,YAAY,GAAG,KAAK,cAAc,KAC9C,GAAG,KAAK,IAAI,YAAY;AAAA,YAC9B;AAAA,UAAA;AAAA,QACF;AAAA,MACF;AAAA,MAEF,WAAW;AAAA,QACT,eAAe;AAAA,QACf,cAAc;AAAA,MAAA;AAAA,IAChB;AAAA,EAEJ;AAAA,EAEQ,8BAAkD;AACxD,UAAM,aAAa,0BAA0B,MAAM;AAAA,MACjD,iBAAiB,KAAK;AAAA,IAAA,CACvB;AAGD,UAAM,4BAA4B,WAAW;AAC7C,QAAI,2BAA2B;AAC7B,iBAAW,oBAAoB,CAAC,OAAO,MAAM,eAAe,YAAY;AAEtE,cAAM,eAAe,KAAK,UAAU,gBAAgB;AACpD,YAAI,eAAe,iBAAiB,wBAAwB;AAC1D;AAAA,QACF;AACA,kCAA0B,OAAO,MAAM,eAAe,OAAO;AAAA,MAC/D;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,iCAAqD;AAC3D,WAAO;AAAA,MACL,IAAI;AAAA,MACJ,YAAY,CAAC,UAAU;AACrB,cAAM,EAAC,KAAK,UAAA,IAAa;AACzB,cAAM,EAAC,OAAO,QAAQ,MAAM,QAAO;AAGnC,cAAM,eAAe,KAAK,UAAU,gBAAgB;AACpD,YAAI,eAAe,iBAAiB,wBAAwB;AAC1D;AAAA,QACF;AAEA,YAAI,KAAA;AACJ,YAAI,YAAY;AAChB,YAAI,eAAe;AAEnB,cAAM,UAAU,OAAO,QAAQ;AAC/B,cAAM,aAAa;AAAA,UACjB;AAAA,UACA,mBAAmB;AAAA,QAAA;AAErB,cAAM,UAAU;AAGhB,cAAM,kBAAkB;AAAA,UACtB;AAAA,UACA,sBAAsB,MAAM;AAAA,QAAA;AAE9B,cAAM,gBAAgB;AAAA,UACpB;AAAA,UACA,sBAAsB,MAAM;AAAA,QAAA;AAE9B,cAAM,aAAa;AAAA,UACjB;AAAA,UACA,sBAAsB,MAAM;AAAA,QAAA;AAE9B,YAAI,OAAO,GAAG,eAAe,IAAI,aAAa,IAAI,UAAU;AAE5D,cAAM,kBAAkB,KAAK,MAAM,QAAQ,CAAC;AAC5C,cAAM,eAAe,IAAI,YAAY,eAAe;AACpD,cAAM,cACJ,aAAa,0BACb,aAAa;AAGf,cAAM,kBAAkB;AAAA,UACtB;AAAA,UACA,sBAAsB,MAAM;AAAA,QAAA;AAE9B,cAAM,gBAAgB;AAAA,UACpB;AAAA,UACA,sBAAsB,MAAM;AAAA,QAAA;AAE9B,cAAM,aAAa;AAAA,UACjB;AAAA,UACA,sBAAsB,MAAM;AAAA,QAAA;AAE9B,cAAM,iBAAiB;AAAA,UACrB;AAAA,UACA,sBAAsB,KAAK;AAAA,QAAA;AAE7B,cAAM,eAAe;AAAA,UACnB;AAAA,UACA,sBAAsB,KAAK;AAAA,QAAA;AAE7B,cAAM,YAAY;AAAA,UAChB;AAAA,UACA,sBAAsB,KAAK;AAAA,QAAA;AAE7B,cAAM,yBAAyB,KAAK;AACpC,cAAM,wBAAwB,KAAK;AACnC,cAAM,QAAQ,wBAAwB,MAAM;AAC5C,YAAI,OAAO,GAAG,eAAe,IAAI,aAAa,IAAI,UAAU;AAC5D,cAAM,eAAe,IAAI,YAAY,sBAAsB;AAC3D,cAAM,eAAe,IAAI,YAAY,KAAK;AAC1C,YAAI,OAAO,GAAG,cAAc,IAAI,YAAY,IAAI,UAAU;AAC1D,cAAM,cAAc,IAAI,YAAY,qBAAqB;AAEzD,cAAM,cAAc,KAAK;AAAA,UACvB,aAAa,0BACX,aAAa;AAAA,UACf,YAAY,0BACV,YAAY;AAAA,QAAA;AAIhB,YAAI;AACJ,YAAI;AAEJ,YAAI,KAAK,MAAM;AAEb,gBAAM,OAAO,MAAM,eAAe,CAAC;AACnC,gBAAM,aAAa,KAAK,KAAK,CAAC,IACzB,KAAK,KAAK,CAAC,EAAiB,IAC7B,MAAM;AACV,mBACE,aACA,KAAK;AAAA,YACH,aAAa;AAAA,YACb,YAAY;AAAA,UAAA;AAEhB,mBACE,SACA,cACA,UACA,cACA,aAAa;AAAA,QACjB,OAAO;AAEL,gBAAM,kBAAkB,cAAc,UAAU;AAChD,gBAAM,UAAU,MAAM,SAAS;AAC/B,mBACE,UACA,kBAAkB,IAClB,aAAa;AACf,mBACE,SACA,aAAa,2BACb,UACA,KAAK;AAAA,YACH,aAAa;AAAA,YACb,YAAY;AAAA,UAAA;AAAA,QAElB;AAGA,YAAI,OAAO,GAAG,eAAe,IAAI,aAAa,IAAI,UAAU;AAC5D,YAAI,YAAY;AAChB,YAAI,SAAS,iBAAiB,SAAS,MAAM;AAI7C,YAAI,OAAO,GAAG,eAAe,IAAI,aAAa,IAAI,UAAU;AAC5D,cAAM,aAAa,aAAa;AAChC,cAAM,aAAa,aAAa;AAChC,YAAI,OAAO,GAAG,cAAc,IAAI,YAAY,IAAI,UAAU;AAC1D,cAAM,YAAY,YAAY;AAC9B,cAAM,aACJ,cAAc,wBAAwB,aAAa,YAAY;AAEjE,YAAI,OAAO,GAAG,eAAe,IAAI,aAAa,IAAI,UAAU;AAC5D,YAAI,YAAY;AAChB,YAAI;AAAA,UACF;AAAA,UACA,UAAU,aAAa,IAAI,aAAa;AAAA,UACxC;AAAA,QAAA;AAGF,YAAI,uBAAuB;AAEzB,cAAI,OAAO,GAAG,eAAe,IAAI,aAAa,IAAI,UAAU;AAC5D,cAAI,YAAY;AAChB,cAAI;AAAA,YACF;AAAA,YACA,UAAU,aAAa,IAAI,aAAa,aAAa;AAAA,YACrD;AAAA,UAAA;AAGF,cAAI,OAAO,GAAG,cAAc,IAAI,YAAY,IAAI,UAAU;AAC1D,cAAI,YAAY;AAChB,cAAI;AAAA,YACF;AAAA,YACA,UAAU,aAAa,IAAI,YAAY;AAAA,YACvC;AAAA,UAAA;AAAA,QAEJ;AAEA,YAAI,QAAA;AAAA,MACN;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEQ,gBAAgB,QAAkB;AAExC,QAAI,CAAC,KAAK,MAAM;AACd,aAAO;AAAA,IACT;AAGA,UAAM,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK;AACnD,UAAM,sBAAsB,YAAY;AAExC,WAAO,OAAO,IAAI,CAAC,QAAQ,UAAU;AAEnC,UAAI,UAAU,GAAG;AACf,eAAO;AAAA,UACL,YAAY,iBAAiB;AAAA,UAC7B,UAAU;AAAA,UACV,YAAY,iBAAiB;AAAA,UAC7B,UAAU;AAAA,QAAA;AAAA,MAEd;AAIA,YAAM,uBAAuB,sBACzB,UAAU,OAAO,SAAS,IAC1B,UAAU,OAAO,SAAS;AAE9B,UAAI,sBAAsB;AACxB,eAAO;AAAA,UACL,YAAY;AAAA,UACZ,UAAU,iBAAiB;AAAA,UAC3B,YAAY;AAAA,UACZ,UAAU,iBAAiB;AAAA,QAAA;AAAA,MAE/B;AAGA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEQ,cAAc;AAEpB,QAAI,CAAC,KAAK,YAAY,CAAC,KAAK,SAAS,YAAa;AAElD,UAAM,MAAM,KAAK,SAAS,WAAW,IAAI;AACzC,QAAI,CAAC,IAAK;AAEV,UAAM,EAAC,QAAQ,QAAQ,OAAA,IAAU,KAAK,iBAAA;AAEtC,SAAK,QAAQ,IAAI,MAAM,KAAK;AAAA,MAC1B,MAAM;AAAA,MACN,MAAM;AAAA,QACJ;AAAA,QACA,UAAU,CAAC,KAAK,oBAAoB,QAAQ,MAAM,CAAC;AAAA,MAAA;AAAA,MAErD,SAAS,KAAK,gBAAA;AAAA,MACd,SAAS;AAAA;AAAA,QAEP,GAAI,KAAK,kBAAkB,CAAC,KAAK,4BAAA,CAA6B,IAAI,CAAA;AAAA,QAClE,KAAK,+BAAA;AAAA,MAA+B;AAAA,IACtC,CACD;AAGD,0BAAsB,MAAM,KAAK,cAAc;AAAA,EACjD;AAAA,EAEQ,cAAc;AAEpB,QAAI,CAAC,KAAK,SAAS,CAAC,KAAK,YAAY,CAAC,KAAK,SAAS,YAAa;AAEjE,UAAM,EAAC,QAAQ,QAAQ,OAAA,IAAU,KAAK,iBAAA;AAEtC,SAAK,MAAM,KAAK,SAAS;AACzB,SAAK,MAAM,KAAK,WAAW,CAAC,KAAK,oBAAoB,QAAQ,MAAM,CAAC;AAEpE,UAAM,gBAAgB,KAAK,gBAAA;AAC3B,QAAI,KAAK,MAAM,SAAS;AACtB,aAAO,OAAO,KAAK,MAAM,SAAS,aAAa;AAAA,IACjD;AAEA,SAAK,MAAM,OAAA;AAGX,0BAAsB,MAAM,KAAK,cAAc;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,oBAAoB;AAC1B,QAAI,CAAC,KAAK,MAAO;AAEjB,UAAM,EAAC,OAAA,IAAU,KAAK,iBAAA;AAGtB,QAAI,KAAK,MAAM,KAAK,SAAS,CAAC,GAAG;AAC/B,WAAK,MAAM,KAAK,SAAS,CAAC,EAAE,kBAAkB;AAC9C,WAAK,MAAM,KAAK,SAAS,CAAC,EAAE,cAAc;AAAA,QACxC;AAAA,QACA,iBAAiB;AAAA,MAAA;AAAA,IAErB;AAGA,SAAK,MAAM,OAAO,MAAM;AAExB,SAAK,aAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe;AAErB,QAAI,CAAC,KAAK,UAAU,CAAC,KAAK,aAAa,CAAC,KAAK,MAAO;AAGpD,UAAM,OAAO,KAAK,MAAM,eAAe,CAAC;AACxC,QAAI,CAAC,QAAQ,CAAC,KAAK,YAAY;AAE7B;AAAA,IACF;AAGA,QAAI,CAAC,KAAK,QAAQ,KAAK,KAAK,WAAW,GAAG;AAExC,WAAK,UAAU,YAAY;AAC3B;AAAA,IACF;AAGA,UAAM,cACJ,KAAK,MAAM,IAAI,KAAK,MAAM,KAAK,QAAQ,IAAI,KAAK,QAAQ;AAC1D,UAAM,eAAe,KAAK,mBAAmB;AAE7C,QAAI;AACF,YAAM,cAAc,KAAK,KAAK,IAAI,CAAC,MAAM,MAAM;AAC7C,cAAM,QAAQ,KAAK,WAAW,SAAS,GAAG,KAAK;AAC/C,cAAM,eAAe;AAAA,UACnB,KAAK;AAAA,UACL;AAAA,UACA;AAAA,UACA,KAAK;AAAA,QAAA;AAEP,cAAM,WAAW,KAAK,YAAY,KAAK;AACvC,cAAM,QAAQ,GAAG,YAAY;AAC7B,cAAM,OAAO,WAAW,GAAG,KAAK,cAAc,KAAK;AAEnD,eAAO;AAAA,UACL,WAAW,MAAM;AAAA,UACjB,OAAO,KAAK;AAAA,UACZ;AAAA,UACA;AAAA,QAAA;AAAA,MAEJ,CAAC;AAED,YAAM,aAAa,mBAAmB,WAAW;AACjD,WAAK,UAAU,YAAY;AAAA,IAC7B,SAAS,OAAO;AACd,cAAQ;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,IAGJ;AAAA,EACF;AAAA,EAES,SAAS;AAChB,WAAO;AAAA;AAAA;AAAA,UAGD,KAAK,SAAS,mCAAmC,EAAE;AAAA;AAAA;AAAA,EAG3D;AAQF;AAlrBa,cA4qBK,SAAS;AAAA,EACvB,UAAU,cAAc;AAAA,EACxB,UAAU,gBAAgB;AAAA,EAC1B,UAAU,gBAAgB;AAAA,EAC1B,UAAU,eAAe;AAC3B;AA/qBA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAO,WAAW,OAAM;AAAA,GAD9B,cAEX,WAAA,QAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAO,WAAW,OAAM;AAAA,GAJ9B,cAKX,WAAA,UAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAPb,cAQX,WAAA,YAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,SAAS,SAAS,MAAK;AAAA,GAV7B,cAWX,WAAA,QAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAbd,cAcX,WAAA,mBAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,QAAA,CAAQ;AAAA,GAhBd,cAiBX,WAAA,YAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAnBb,cAoBX,WAAA,kBAAA,CAAA;AAMA,gBAAA;AAAA,EAHC,SAAS;AAAA,IACR,MAAM;AAAA,EAAA,CACP;AAAA,GAzBU,cA0BX,WAAA,uBAAA,CAAA;AAKA,gBAAA;AAAA,EAHC,SAAS;AAAA,IACR,MAAM;AAAA,EAAA,CACP;AAAA,GA9BU,cA+BX,WAAA,2BAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAjCb,cAkCX,WAAA,sBAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GApCb,cAqCX,WAAA,qBAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GAvCb,cAwCX,WAAA,OAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,OAAA,CAAO;AAAA,GA1Cb,cA2CX,WAAA,aAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,SAAS,SAAS,MAAK;AAAA,GA7C7B,cA8CX,WAAA,UAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,SAAS,SAAS,MAAK;AAAA,GAhD7B,cAiDX,WAAA,oBAAA,CAAA;AAGA,gBAAA;AAAA,EADC,SAAS,EAAC,MAAM,QAAQ,SAAS,MAAK;AAAA,GAnD5B,cAoDX,WAAA,eAAA,CAAA;AAGiB,gBAAA;AAAA,EAAhB,MAAA;AAAM,GAvDI,cAuDM,WAAA,SAAA,CAAA;AAGA,gBAAA;AAAA,EAAhB,MAAA;AAAM,GA1DI,cA0DM,WAAA,mBAAA,CAAA;AAGQ,gBAAA;AAAA,EAAxB,MAAM,QAAQ;AAAA,GA7DJ,cA6Dc,WAAA,YAAA,CAAA;AAGC,gBAAA;AAAA,EAAzB,MAAM,SAAS;AAAA,GAhEL,cAgEe,WAAA,aAAA,CAAA;AAhEf,gBAAN,gBAAA;AAAA,EADN,cAAc,iBAAiB;AAAA,GACnB,aAAA;"}
|
|
1
|
+
{"version":3,"file":"donut-chart.js","sources":["../../../src/bars-graphs/donut-chart/donut-chart.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, unsafeCSS} from 'lit';\nimport {property, query, state} from 'lit/decorators.js';\nimport componentStyle from './donut-chart.css?inline';\nimport chartCommonStyle from '../../charthelpers/chart-common.css?inline';\nimport chartDebugStyle from '../../charthelpers/chart-debug.css?inline';\nimport chartLegendStyle from '../../charthelpers/chart-legend.css?inline';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../../navigation-instruments/types.js';\nimport {Chart, DoughnutController, ArcElement, Tooltip} from 'chart.js';\nimport type {Plugin, ChartOptions, ChartDataset} from 'chart.js';\nimport {\n CHART_SECTOR_DEFAULT_COLORS,\n CHART_SECTOR_ENHANCED_COLORS,\n CHART_DIMENSIONS,\n OUTER_LABEL_CONFIG,\n CENTER_READOUT_CONFIG,\n getCssVariableValue,\n getChartColorsOrDefault,\n observeThemeChanges,\n calculateSumTotal,\n formatNumericValue,\n createArcOuterLabelPlugin,\n calculateFixedHeightChartLayout,\n getChartTooltipOptions,\n generateLegendHTML,\n} from '../../charthelpers/index.js';\n\n// Register Chart.js components\nChart.register(DoughnutController, ArcElement, Tooltip);\n\n// Donut-specific dimension constants (extends shared CHART_DIMENSIONS)\nconst DONUT_DIMENSIONS = {\n ...CHART_DIMENSIONS,\n GAP_WIDTH: 0,\n GAP_AND_BORDER_COLOR: '--container-section-color',\n REMAINING_COLOR: '--border-outline-color',\n BORDER_RADIUS: 4,\n} as const;\n\nconst DONUT_RECREATE_PROP_NAMES = [\n 'half',\n 'showOuterLabels',\n 'showUnit',\n 'outerLabelUnit',\n 'outerLabelMaxLength',\n 'outerLabelDecimalPlaces',\n 'showDebugOverlay',\n 'fixedHeight',\n] as const;\n\nconst DONUT_WATCHED_PROP_NAMES = [\n 'legend',\n 'data',\n 'colors',\n 'priority',\n 'half',\n 'thickness',\n 'max',\n 'showOuterLabels',\n 'showUnit',\n 'centerReadoutLabel',\n 'centerReadoutUnit',\n 'outerLabelUnit',\n 'outerLabelMaxLength',\n 'outerLabelDecimalPlaces',\n 'showDebugOverlay',\n 'fixedHeight',\n] as const;\n\nexport type DonutChartDataItem = {\n label: string;\n value: number;\n};\n\n/**\n * `<obc-donut-chart>` – A customizable donut chart component for visualizing proportional data with a center total readout.\n *\n * This component renders an interactive donut chart powered by Chart.js, displaying data segments as arcs with optional outer labels and a centered total value. It supports both full-circle (360°) and half-circle (180°) layouts, making it versatile for dashboards, analytics, and data visualization interfaces.\n *\n * The chart automatically calculates percentages, handles remaining/unfilled capacity, and adapts its layout based on available space. Labels and center readouts are hidden when the chart is too small (< 192px height), ensuring visual clarity at all sizes.\n *\n * ## Features\n * - **Fixed Height ⇒ Fixed Circumference:** The chart's circumference is determined by the `fixedHeight` property (default: 320px). This ensures the donut's circumference remains consistent and matches other radial instruments, regardless of the available browser or container width. The chart does not scale to fill the width; instead, it always uses the specified fixed height to define its size and circumference.\n * - **Layout Modes:**\n * - `Full Circle` (default): Complete 360° donut chart.\n * - `Half Circle`: Semicircular 180° layout, useful for gauges or space-constrained displays.\n * - **Center Readout:**\n * - Displays the sum total of all data values with a customizable label (e.g., \"Total\", \"Power\", \"Usage\").\n * - **Outer Labels:**\n * - Optional labels positioned outside the chart showing segment names and values.\n * - Supports percentage or custom units (e.g., \"kW\", \"kg\", \"MB\").\n * - Configurable decimal places and maximum label length (with trimming).\n * - **Capacity Visualization:**\n * - Optionally show remaining/unfilled capacity when `max` is set higher than the total.\n * - Remaining sector uses a distinct color to indicate available space.\n * - **Customization:**\n * - Custom segment colors (with automatic fallback to theme palette).\n * - Adjustable ring thickness (default 24px).\n * - **Color Priority:** Set `priority` to `Priority.enhanced` to use the blue/enhanced\n * color palette instead of the default gray/regular palette (default: `Priority.regular`).\n * - **Responsive Behavior:**\n * - Automatically hides labels and center readout when height < 192px.\n * - Maintains aspect ratio and adjusts padding for optimal label positioning.\n * - **Theme Integration:**\n * - Colors update automatically when the `data-obc-theme` attribute changes on the `<html>` element.\n * - Example:\n * ```\n * <html lang=\"en\" data-obc-theme=\"day\"></html>\n * ```\n *\n * ## Example\n *\n * **Basic Usage (Half Circle)**\n * ```html\n * <obc-donut-chart\n * half\n * ></obc-donut-chart>\n * <script>\n * document.querySelector('obc-donut-chart').data = [\n * {label: 'Engine', value: 75.5},\n * {label: 'HVAC', value: 42.3},\n * {label: 'Lights', value: 12.8}\n * ];\n * </script>\n * ```\n *\n * **Custom Colors**\n * ```html\n * <obc-donut-chart></obc-donut-chart>\n * <script>\n * const chart = document.querySelector('obc-donut-chart');\n * chart.data = [\n * {label: 'Critical', value: 20},\n * {label: 'Warning', value: 35},\n * {label: 'Normal', value: 45}\n * ];\n * chart.colors = ['#e74c3c', '#f39c12', '#2ecc71'];\n * </script>\n * ```\n *\n * @beta\n */\n@customElement('obc-donut-chart')\nexport class ObcDonutChart extends LitElement {\n /** Chart data segments (set via JavaScript) */\n @property({type: Array, attribute: false})\n data: DonutChartDataItem[] = [];\n\n /** Custom segment colors (set via JavaScript) with fallback to theme palette */\n @property({type: Array, attribute: false})\n colors: string[] = [];\n\n @property({type: String})\n priority: Priority = Priority.regular;\n\n /** Whether to display as half-circle (180°) or full circle (360°), default: false */\n @property({type: Boolean, reflect: true})\n half = false;\n\n /** Show outer labels, default: false */\n @property({type: Boolean})\n showOuterLabels = false;\n\n /** Whether to show unit in labels, default: false */\n @property({type: Boolean})\n showUnit = false;\n\n /** Unit string to append to outer labels, default: \"%\" */\n @property({type: String})\n outerLabelUnit = '%';\n\n /**\n * Maximum character length for labels before trim (0 = no limit), default: 0\n * @availableWhen showOuterLabels==true\n */\n @property({\n type: Number,\n })\n outerLabelMaxLength = 0;\n\n /** Number of decimal places in labels, default: 0 */\n @property({\n type: Number,\n })\n outerLabelDecimalPlaces = 0;\n\n /** Text label shown below the center total value, default: \"Total\" */\n @property({type: String})\n centerReadoutLabel = 'Total';\n\n /** Unit string shown inline after the label in the center readout, default: \"%\" */\n @property({type: String})\n centerReadoutUnit = '%';\n\n /** Maximum value for calculating remaining empty sector, default: 100 */\n @property({type: Number})\n max = 100;\n\n /** Donut ring thickness in pixels, default: 24 */\n @property({type: Number})\n thickness = 24;\n\n /** Whether to display the legend below the chart, default: false */\n @property({type: Boolean, reflect: true})\n legend = false;\n\n /** Show debug overlay for development, default: false */\n @property({type: Boolean, reflect: true})\n showDebugOverlay = false;\n\n /** Fixed height of the chart in pixels (determines chart circumference), default: 320. The chart's circumference is always based on this fixed height to match other radial instruments. */\n @property({type: Number, reflect: true})\n fixedHeight = 320;\n\n /** @internal */\n @state() private total = 0;\n\n /** @internal - Pre-formatted labels for outer label rendering */\n @state() private formattedLabels: string[] = [];\n\n /** @internal */\n @query('canvas') private canvasEl?: HTMLCanvasElement;\n\n /** @internal */\n @query('.legend') private legendDiv?: HTMLDivElement;\n\n /** @internal */\n private chart?: Chart;\n\n /** @internal */\n private themeObserver?: MutationObserver;\n\n /** @internal - ResizeObserver for tracking height threshold crossings (e.g. MIN_HEIGHT_WITH_LABELS = 192px) */\n private resizeObserver?: ResizeObserver;\n\n /** @internal - Track previous state to detect threshold crossing */\n private wasAboveThreshold = false;\n\n private hasAnyChanged(\n changed: PropertyValues,\n props: readonly (keyof ObcDonutChart)[]\n ): boolean {\n return props.some((prop) => changed.has(prop));\n }\n\n /**\n * Get layout configuration for canvas calculation\n */\n private getLayoutConfig() {\n // Denominator: use max if set, otherwise total, with minimum of 1\n const denominator =\n this.max > 0 ? this.max : this.total > 0 ? this.total : 1;\n\n return {\n unit: this.outerLabelUnit,\n showUnit: this.showUnit,\n outerLabelMaxLength: this.outerLabelMaxLength,\n decimalPlaces: this.outerLabelDecimalPlaces,\n data: this.data,\n denominator,\n };\n }\n\n // Calculate derived state BEFORE render\n override willUpdate(changed: PropertyValues) {\n if (changed.has('data')) {\n this.total = calculateSumTotal(this.data);\n }\n }\n\n // Update external library AFTER render\n override updated(changed: PropertyValues) {\n super.updated(changed);\n\n if (this.hasAnyChanged(changed, DONUT_WATCHED_PROP_NAMES)) {\n // Recreate chart when major layout properties change or when plugin configuration changes\n // These properties affect aspect ratio calculation, plugin registration, or outer label rendering\n const needsRecreation = this.hasAnyChanged(\n changed,\n DONUT_RECREATE_PROP_NAMES\n );\n\n if (needsRecreation) {\n this.chart?.destroy();\n this.createChart();\n } else {\n this.updateChart();\n }\n }\n }\n\n override firstUpdated() {\n this.createChart();\n this.themeObserver = observeThemeChanges(() => this.updateChartColors());\n this.setupResizeObserver();\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.chart?.destroy();\n this.themeObserver?.disconnect();\n this.resizeObserver?.disconnect();\n }\n\n /**\n * Setup resize observer to detect height threshold crossings\n * Recreates chart when crossing MIN_HEIGHT_WITH_LABELS (192px) to show/hide labels\n * Detect when fixedHeight property changes programmatically (e.g., via Storybook controls or user code)\n */\n private setupResizeObserver() {\n if (!this.canvasEl) return;\n\n this.resizeObserver = new ResizeObserver(() => {\n if (!this.chart) return;\n\n const height = this.canvasEl?.clientHeight ?? 0;\n const isAboveThreshold =\n height >= CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n\n // Only recreate chart if we crossed the threshold\n if (isAboveThreshold !== this.wasAboveThreshold) {\n this.wasAboveThreshold = isAboveThreshold;\n this.chart.destroy();\n this.createChart();\n } else {\n // Height changed but didn't cross threshold - just update\n this.updateChart();\n }\n });\n\n this.resizeObserver.observe(this.canvasEl);\n\n // Initialize threshold state\n const height = this.canvasEl.clientHeight;\n this.wasAboveThreshold = height >= CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n }\n\n private prepareChartData() {\n const values = this.data.map((d) => d.value);\n const labels = this.data.map((d) => d.label);\n const remaining = Math.max(0, this.max - this.total);\n const chartColors = getChartColorsOrDefault(\n this,\n this.colors,\n this.priority === Priority.enhanced\n ? CHART_SECTOR_ENHANCED_COLORS\n : CHART_SECTOR_DEFAULT_COLORS\n );\n const segmentColors = values.map(\n (_, index) =>\n chartColors[index % chartColors.length] ??\n getCssVariableValue(this, DONUT_DIMENSIONS.REMAINING_COLOR)\n );\n\n return {\n values: [...values, remaining],\n labels: [...labels, 'Remaining'],\n colors: [\n ...segmentColors,\n getCssVariableValue(this, DONUT_DIMENSIONS.REMAINING_COLOR),\n ],\n };\n }\n\n /**\n * Build a dataset configuration object shared by both createChart and updateChart\n */\n private createDatasetConfig(\n values: number[],\n colors: (string | CanvasGradient | CanvasPattern)[]\n ): ChartDataset<'doughnut', number[]> {\n return {\n data: values,\n backgroundColor: colors,\n borderWidth: 1,\n borderColor: getCssVariableValue(\n this,\n DONUT_DIMENSIONS.GAP_AND_BORDER_COLOR\n ),\n borderRadius: this.getBorderRadius(values),\n spacing: DONUT_DIMENSIONS.GAP_WIDTH,\n };\n }\n\n /**\n * Get Chart.js options using centralized fixed height layout calculation\n */\n private getChartOptions(): ChartOptions<'doughnut'> {\n // Use centralized layout calculation helper\n const dimensions = calculateFixedHeightChartLayout({\n fixedHeight: this.fixedHeight,\n isHalfMode: this.half,\n showOuterLabels: this.showOuterLabels,\n canvasEl: this.canvasEl,\n layoutConfig: this.getLayoutConfig(),\n host: this,\n });\n\n // Store formatted labels for use in plugins\n this.formattedLabels = dimensions.formattedLabels;\n\n // Set CSS variables for wrapper and canvas sizing\n this.style.setProperty('--chart-width', `${dimensions.calculatedWidth}px`);\n this.style.setProperty('--chart-height', `${dimensions.actualHeight}px`);\n\n // Calculate dynamic padding for Chart.js layout\n const dynamicPadding = dimensions.isTooSmall\n ? {top: 0, right: 0, bottom: 0, left: 0}\n : {\n top: dimensions.topPadding,\n right: dimensions.rightPadding,\n bottom: dimensions.bottomPadding,\n left: dimensions.leftPadding,\n };\n\n return {\n responsive: true,\n maintainAspectRatio: true,\n aspectRatio: dimensions.aspectRatio,\n rotation: this.half ? -90 : 0,\n circumference: this.half ? 180 : 360,\n cutout: `${((DONUT_DIMENSIONS.CHART_WIDTH - this.thickness * 2) / DONUT_DIMENSIONS.CHART_WIDTH) * 100}%`,\n layout: {\n padding: dynamicPadding ?? DONUT_DIMENSIONS.CANVAS_PADDING,\n },\n plugins: {\n legend: {\n display: false,\n labels: {\n generateLabels: () => [], // Prevent Chart.js from generating labels internally\n },\n onClick: () => {}, // Disable legend click handler\n },\n tooltip: {\n ...getChartTooltipOptions(this),\n enabled: !dimensions.isTooSmall,\n filter: (tooltipItem) => tooltipItem.label !== 'Remaining',\n callbacks: {\n title: () => '', // No title line\n label: (context) => {\n const label = context.label ?? '';\n const value = context.parsed;\n // Denominator: use max if set, otherwise total, with minimum of 1\n const denominator =\n this.max > 0 ? this.max : this.total > 0 ? this.total : 1;\n // Calculate percentage if unit is \"%\", otherwise use raw value\n const isPercentage = this.outerLabelUnit === '%';\n const numericValue = formatNumericValue(\n value,\n denominator,\n isPercentage,\n this.outerLabelDecimalPlaces\n );\n const showUnit = this.showUnit && this.outerLabelUnit;\n // Chart.js core only supports string/array-of-string for label callback\n // For now, return a single string (styled via global tooltip options)\n // To support per-span styling, a custom HTML tooltip plugin is needed\n return showUnit\n ? `${label} ${numericValue}${this.outerLabelUnit}`\n : `${label} ${numericValue}`;\n },\n },\n },\n },\n animation: {\n animateRotate: false,\n animateScale: false,\n },\n };\n }\n\n private createOuterLabelDonutPlugin(): Plugin<'doughnut'> {\n const basePlugin = createArcOuterLabelPlugin(this, {\n formattedLabels: this.formattedLabels,\n }) as Plugin<'doughnut'>;\n\n // Wrap the afterDatasetsDraw to check height first\n const originalAfterDatasetsDraw = basePlugin.afterDatasetsDraw;\n if (originalAfterDatasetsDraw) {\n basePlugin.afterDatasetsDraw = (chart, args, pluginOptions, options) => {\n // Check height before drawing labels\n const canvasHeight = this.canvasEl?.clientHeight ?? 0;\n if (canvasHeight < CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS) {\n return;\n }\n originalAfterDatasetsDraw(chart, args, pluginOptions, options);\n };\n }\n\n return basePlugin;\n }\n\n private createCenterReadoutDonutPlugin(): Plugin<'doughnut'> {\n return {\n id: 'centerText',\n beforeDraw: (chart) => {\n const {ctx, chartArea} = chart;\n const {width, height, left, top} = chartArea;\n\n // Hide center readout if canvas is too small\n const canvasHeight = this.canvasEl?.clientHeight ?? 0;\n if (canvasHeight < CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS) {\n return;\n }\n\n ctx.save();\n ctx.textAlign = 'center';\n ctx.textBaseline = 'middle';\n\n const centerX = left + width / 2;\n const fontFamily = getCssVariableValue(\n this,\n OUTER_LABEL_CONFIG.fontFamily\n );\n const lineGap = 4;\n\n // Setup and measure centered readout value text\n const valueFontWeight = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.value.fontWeightVar\n );\n const valueFontSize = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.value.fontSizeVar\n );\n const valueColor = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.value.fontColorVar\n );\n ctx.font = `${valueFontWeight} ${valueFontSize} ${fontFamily}`;\n // Center readout always shows raw total value without decimal places\n const centerValueText = this.total.toFixed(0);\n const valueMetrics = ctx.measureText(centerValueText);\n const valueHeight =\n valueMetrics.actualBoundingBoxAscent +\n valueMetrics.actualBoundingBoxDescent;\n\n // Setup and measure centered readout label and unit text (inline, different styles)\n const labelFontWeight = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.label.fontWeightVar\n );\n const labelFontSize = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.label.fontSizeVar\n );\n const labelColor = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.label.fontColorVar\n );\n const unitFontWeight = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.unit.fontWeightVar\n );\n const unitFontSize = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.unit.fontSizeVar\n );\n const unitColor = getCssVariableValue(\n this,\n CENTER_READOUT_CONFIG.unit.fontColorVar\n );\n const centerReadoutLabelText = this.centerReadoutLabel;\n const centerReadoutUnitText = this.centerReadoutUnit;\n const space = centerReadoutUnitText ? ' ' : '';\n ctx.font = `${labelFontWeight} ${labelFontSize} ${fontFamily}`;\n const labelMetrics = ctx.measureText(centerReadoutLabelText);\n const spaceMetrics = ctx.measureText(space);\n ctx.font = `${unitFontWeight} ${unitFontSize} ${fontFamily}`;\n const unitMetrics = ctx.measureText(centerReadoutUnitText);\n // Height is max of label and unit\n const labelHeight = Math.max(\n labelMetrics.actualBoundingBoxAscent +\n labelMetrics.actualBoundingBoxDescent,\n unitMetrics.actualBoundingBoxAscent +\n unitMetrics.actualBoundingBoxDescent\n );\n\n // Calculate Y positions\n let valueY: number;\n let labelY: number;\n\n if (this.half) {\n // For half donut: Get the actual arc center Y position from the chart metadata\n const meta = chart.getDatasetMeta(0);\n const arcCenterY = meta.data[0]\n ? (meta.data[0] as ArcElement).y\n : top + height;\n labelY =\n arcCenterY -\n Math.max(\n labelMetrics.actualBoundingBoxDescent,\n unitMetrics.actualBoundingBoxDescent\n );\n valueY =\n labelY -\n labelHeight -\n lineGap -\n valueHeight +\n valueMetrics.actualBoundingBoxAscent;\n } else {\n // For full donut: center both lines vertically as a unit\n const totalTextHeight = valueHeight + lineGap + labelHeight;\n const centerY = top + height / 2;\n valueY =\n centerY -\n totalTextHeight / 2 +\n valueMetrics.actualBoundingBoxAscent;\n labelY =\n valueY +\n valueMetrics.actualBoundingBoxDescent +\n lineGap +\n Math.max(\n labelMetrics.actualBoundingBoxAscent,\n unitMetrics.actualBoundingBoxAscent\n );\n }\n\n // Draw centered readout value\n ctx.font = `${valueFontWeight} ${valueFontSize} ${fontFamily}`;\n ctx.fillStyle = valueColor;\n ctx.fillText(centerValueText, centerX, valueY);\n\n // Draw centered readout label and unit inline, with different styles\n // Measure total width for centering\n ctx.font = `${labelFontWeight} ${labelFontSize} ${fontFamily}`;\n const labelWidth = labelMetrics.width;\n const spaceWidth = spaceMetrics.width;\n ctx.font = `${unitFontWeight} ${unitFontSize} ${fontFamily}`;\n const unitWidth = unitMetrics.width;\n const totalWidth =\n labelWidth + (centerReadoutUnitText ? spaceWidth + unitWidth : 0);\n // Draw label\n ctx.font = `${labelFontWeight} ${labelFontSize} ${fontFamily}`;\n ctx.fillStyle = labelColor;\n ctx.fillText(\n centerReadoutLabelText,\n centerX - totalWidth / 2 + labelWidth / 2,\n labelY\n );\n // Draw space and unit (if present)\n if (centerReadoutUnitText) {\n // Draw space (in label font)\n ctx.font = `${labelFontWeight} ${labelFontSize} ${fontFamily}`;\n ctx.fillStyle = labelColor;\n ctx.fillText(\n space,\n centerX - totalWidth / 2 + labelWidth + spaceWidth / 2,\n labelY\n );\n // Draw unit (in unit font)\n ctx.font = `${unitFontWeight} ${unitFontSize} ${fontFamily}`;\n ctx.fillStyle = unitColor;\n ctx.fillText(\n centerReadoutUnitText,\n centerX + totalWidth / 2 - unitWidth / 2,\n labelY\n );\n }\n\n ctx.restore();\n },\n };\n }\n\n private getBorderRadius(values: number[]) {\n // Full donuts don't need border radius (from Figma design)\n if (!this.half) {\n return undefined;\n }\n\n // For half donuts, apply different radius to first and last segments (detail from Figma)\n const remaining = Math.max(0, this.max - this.total);\n const hasRemainingSegment = remaining > 0;\n\n return values.map((_value, index) => {\n // First segment gets left-side radius\n if (index === 0) {\n return {\n outerStart: DONUT_DIMENSIONS.BORDER_RADIUS,\n outerEnd: 0,\n innerStart: DONUT_DIMENSIONS.BORDER_RADIUS,\n innerEnd: 0,\n };\n }\n\n // Last visible segment gets right-side radius\n // If there's a remaining segment, it's always last; otherwise the last data segment is last\n const isLastVisibleSegment = hasRemainingSegment\n ? index === values.length - 1\n : index === values.length - 2;\n\n if (isLastVisibleSegment) {\n return {\n outerStart: 0,\n outerEnd: DONUT_DIMENSIONS.BORDER_RADIUS,\n innerStart: 0,\n innerEnd: DONUT_DIMENSIONS.BORDER_RADIUS,\n };\n }\n\n // Middle segments don't need radius\n return 0;\n });\n }\n\n private createChart() {\n // Guard: Verify canvas exists and is connected to DOM\n if (!this.canvasEl || !this.canvasEl.isConnected) return;\n\n const ctx = this.canvasEl.getContext('2d');\n if (!ctx) return;\n\n const {values, labels, colors} = this.prepareChartData();\n\n this.chart = new Chart(ctx, {\n type: 'doughnut',\n data: {\n labels,\n datasets: [this.createDatasetConfig(values, colors)],\n },\n options: this.getChartOptions(),\n plugins: [\n // Always include plugins; they check height internally during rendering\n ...(this.showOuterLabels ? [this.createOuterLabelDonutPlugin()] : []),\n this.createCenterReadoutDonutPlugin(),\n ],\n });\n\n // Defer legend update to next tick to ensure Chart.js metadata is initialized\n requestAnimationFrame(() => this.updateLegend());\n }\n\n private updateChart() {\n // Guard: Verify chart and canvas still exist and are connected\n if (!this.chart || !this.canvasEl || !this.canvasEl.isConnected) return;\n\n const {values, labels, colors} = this.prepareChartData();\n\n this.chart.data.labels = labels;\n this.chart.data.datasets = [this.createDatasetConfig(values, colors)];\n\n const latestOptions = this.getChartOptions();\n if (this.chart.options) {\n Object.assign(this.chart.options, latestOptions);\n }\n\n this.chart.update();\n\n // Update legend after chart update completes to ensure metadata is ready\n requestAnimationFrame(() => this.updateLegend());\n }\n\n /**\n * Update only chart colors without recalculating layout\n * Used by theme observer for efficient theme changes\n */\n private updateChartColors() {\n if (!this.chart) return;\n\n const {colors} = this.prepareChartData();\n\n // Update dataset colors\n if (this.chart.data.datasets[0]) {\n this.chart.data.datasets[0].backgroundColor = colors;\n this.chart.data.datasets[0].borderColor = getCssVariableValue(\n this,\n DONUT_DIMENSIONS.GAP_AND_BORDER_COLOR\n );\n }\n\n // Update without animation for instant theme change\n this.chart.update('none');\n\n this.updateLegend();\n }\n\n /**\n * Update the legend HTML content\n */\n private updateLegend() {\n // Guard: Check if legend should be shown and chart is ready\n if (!this.legend || !this.legendDiv || !this.chart) return;\n\n // Guard: Check if chart metadata is available\n const meta = this.chart.getDatasetMeta(0);\n if (!meta || !meta.controller) {\n // console.debug('[obc-donut-chart] updateLegend: skipped - chart metadata not yet initialized');\n return;\n }\n\n // Guard: Check if dataset has data\n if (!this.data || this.data.length === 0) {\n // console.debug('[obc-donut-chart] updateLegend: skipped - no data available');\n this.legendDiv.innerHTML = '';\n return;\n }\n\n // Denominator: use max if set, otherwise total, with minimum of 1\n const denominator =\n this.max > 0 ? this.max : this.total > 0 ? this.total : 1;\n const isPercentage = this.outerLabelUnit === '%';\n\n try {\n const legendItems = this.data.map((item, i) => {\n const style = meta.controller.getStyle(i, false);\n const numericValue = formatNumericValue(\n item.value,\n denominator,\n isPercentage,\n this.outerLabelDecimalPlaces\n );\n const showUnit = this.showUnit && this.outerLabelUnit;\n const value = `${numericValue}`;\n const unit = showUnit ? `${this.outerLabelUnit}` : '';\n\n return {\n fillStyle: style.backgroundColor as string,\n label: item.label as string,\n value: value as string,\n unit: unit as string,\n };\n });\n\n const legendHTML = generateLegendHTML(legendItems);\n this.legendDiv.innerHTML = legendHTML;\n } catch (error) {\n console.debug(\n '[obc-donut-chart] updateLegend: error generating legend HTML',\n error\n );\n // Silent failure - don't throw, just skip legend update this time\n }\n }\n\n override render() {\n return html`\n <div class=\"wrapper\">\n <canvas></canvas>\n ${this.legend ? html`<div class=\"legend\"></div>` : ''}\n </div>\n `;\n }\n\n static override styles = [\n unsafeCSS(componentStyle),\n unsafeCSS(chartCommonStyle),\n unsafeCSS(chartLegendStyle),\n unsafeCSS(chartDebugStyle),\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-donut-chart': ObcDonutChart;\n }\n}\n"],"names":["height"],"mappings":"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"}
|
|
@@ -87,32 +87,34 @@ export type PieChartDataItem = {
|
|
|
87
87
|
* </script>
|
|
88
88
|
* ```
|
|
89
89
|
*
|
|
90
|
-
* @property {Array<{label: string, value: number, children?: Array<{label: string, value: number}>}>} data - Chart data segments with optional children subsegments for sunburst mode (set via JavaScript)
|
|
91
|
-
* @property {string[]} colors - Custom segment colors (set via JavaScript) with fallback to theme palette
|
|
92
|
-
* @property {boolean} showOuterLabels - Show outer labels, default: false
|
|
93
|
-
* @property {boolean} showUnit - Whether to show unit in labels, default: false
|
|
94
|
-
* @property {boolean} sunburst - Enable sunburst mode with interactive children subsegments, default: false
|
|
95
|
-
* @property {string} outerLabelUnit - Unit string to append to outer labels, default: "%"
|
|
96
|
-
* @property {number} outerLabelMaxLength - Maximum character length for labels before trim (0 = no limit), default: 0
|
|
97
|
-
* @property {number} outerLabelDecimalPlaces - Number of decimal places in labels, default: 0
|
|
98
|
-
* @property {boolean} showDebugOverlay - Show debug overlay for development, default: false
|
|
99
|
-
* @property {number} fixedHeight - Fixed height of the chart in pixels (mandatory, determines chart circumference), default: 320. The chart's circumference is always based on this fixed height to match other radial instruments.
|
|
100
|
-
* @property {boolean} legend - Whether to display the legend below the chart, default: false
|
|
101
90
|
* @beta
|
|
102
91
|
*/
|
|
103
92
|
export declare class ObcPieChart extends LitElement {
|
|
93
|
+
/** Chart data segments with optional children subsegments for sunburst mode (set via JavaScript). */
|
|
104
94
|
data: PieChartDataItem[];
|
|
95
|
+
/** Custom segment colors (set via JavaScript) with fallback to theme palette */
|
|
105
96
|
colors: string[];
|
|
106
97
|
priority: Priority;
|
|
98
|
+
/** Show outer labels, default: false */
|
|
107
99
|
showOuterLabels: boolean;
|
|
100
|
+
/** Whether to show unit in labels, default: false */
|
|
108
101
|
showUnit: boolean;
|
|
102
|
+
/** Enable sunburst mode with interactive children subsegments, default: false */
|
|
109
103
|
sunburst: boolean;
|
|
104
|
+
/** Unit string to append to outer labels, default: "%" */
|
|
110
105
|
outerLabelUnit: string;
|
|
111
|
-
/**
|
|
106
|
+
/**
|
|
107
|
+
* Maximum character length for labels before trim (0 = no limit), default: 0
|
|
108
|
+
* @availableWhen showOuterLabels==true
|
|
109
|
+
*/
|
|
112
110
|
outerLabelMaxLength: number;
|
|
111
|
+
/** Number of decimal places in labels, default: 0 */
|
|
113
112
|
outerLabelDecimalPlaces: number;
|
|
113
|
+
/** Whether to display the legend below the chart, default: false */
|
|
114
114
|
legend: boolean;
|
|
115
|
+
/** Show debug overlay for development, default: false */
|
|
115
116
|
showDebugOverlay: boolean;
|
|
117
|
+
/** Fixed height of the chart in pixels (determines chart circumference), default: 320. The chart's circumference is always based on this fixed height to match other radial instruments. */
|
|
116
118
|
fixedHeight: number;
|
|
117
119
|
/** @internal */
|
|
118
120
|
private total;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie-chart.d.ts","sourceRoot":"","sources":["../../../src/bars-graphs/pie-chart/pie-chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAkB,MAAM,KAAK,CAAC;AAOhE,OAAO,EAAC,QAAQ,EAAC,MAAM,uCAAuC,CAAC;AA8D/D,KAAK,qBAAqB,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,qBAAqB,EAAE,CAAC;CACpC,CAAC;AAEF
|
|
1
|
+
{"version":3,"file":"pie-chart.d.ts","sourceRoot":"","sources":["../../../src/bars-graphs/pie-chart/pie-chart.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAE,cAAc,EAAkB,MAAM,KAAK,CAAC;AAOhE,OAAO,EAAC,QAAQ,EAAC,MAAM,uCAAuC,CAAC;AA8D/D,KAAK,qBAAqB,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,qBAAqB,EAAE,CAAC;CACpC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,qBACa,WAAY,SAAQ,UAAU;IACzC,qGAAqG;IAErG,IAAI,EAAE,gBAAgB,EAAE,CAAM;IAE9B,gFAAgF;IAEhF,MAAM,EAAE,MAAM,EAAE,CAAM;IAGtB,QAAQ,EAAE,QAAQ,CAAoB;IAEtC,wCAAwC;IAExC,eAAe,UAAS;IAExB,qDAAqD;IAErD,QAAQ,UAAS;IAEjB,iFAAiF;IAEjF,QAAQ,UAAS;IAEjB,0DAA0D;IAE1D,cAAc,SAAO;IAErB;;;OAGG;IAIH,mBAAmB,SAAK;IAExB,qDAAqD;IAIrD,uBAAuB,SAAK;IAE5B,oEAAoE;IAEpE,MAAM,UAAS;IAEf,yDAAyD;IAEzD,gBAAgB,UAAS;IAEzB,4LAA4L;IAE5L,WAAW,SAAO;IAElB,gBAAgB;IACP,OAAO,CAAC,KAAK,CAAK;IAE3B,iEAAiE;IACxD,OAAO,CAAC,eAAe,CAAgB;IAEhD,gBAAgB;IACP,OAAO,CAAC,kBAAkB,CAAuB;IAE1D,gBAAgB;IACC,OAAO,CAAC,QAAQ,CAAC,CAAoB;IAEtD,gBAAgB;IACE,OAAO,CAAC,SAAS,CAAC,CAAiB;IAErD,gBAAgB;IAChB,OAAO,CAAC,KAAK,CAAC,CAAQ;IAEtB,gBAAgB;IAChB,OAAO,CAAC,aAAa,CAAC,CAAmB;IAEzC,yEAAyE;IACzE,OAAO,CAAC,cAAc,CAAC,CAAiB;IAExC,oEAAoE;IACpE,OAAO,CAAC,iBAAiB,CAAS;IAElC,OAAO,CAAC,aAAa;IAOrB;;OAEG;IACH,OAAO,CAAC,eAAe;IAYd,UAAU,CAAC,OAAO,EAAE,cAAc;IAOlC,OAAO,CAAC,OAAO,EAAE,cAAc;IAwB/B,YAAY;IAWZ,oBAAoB;IAQ7B;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IA4B3B,gBAAgB;IAChB,OAAO,CAAC,iBAAiB,CAqBvB;IAEF,OAAO,CAAC,wBAAwB;IAMhC,OAAO,CAAC,yBAAyB;IAMjC,OAAO,CAAC,gBAAgB;IA6DxB;;OAEG;IACH,OAAO,CAAC,eAAe;IAwFvB,OAAO,CAAC,yBAAyB;IAOjC,OAAO,CAAC,WAAW;IA0DnB,OAAO,CAAC,oBAAoB;IA8J5B,OAAO,CAAC,WAAW;IAUnB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAuBzB;;OAEG;IACH,OAAO,CAAC,YAAY;IAsDX,MAAM;IASf,OAAgB,MAAM,4BAKpB;CACH;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,eAAe,EAAE,WAAW,CAAC;KAC9B;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pie-chart.js","sources":["../../../src/bars-graphs/pie-chart/pie-chart.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, unsafeCSS} from 'lit';\nimport {property, query, state} from 'lit/decorators.js';\nimport componentStyle from './pie-chart.css?inline';\nimport chartCommonStyle from '../../charthelpers/chart-common.css?inline';\nimport chartDebugStyle from '../../charthelpers/chart-debug.css?inline';\nimport chartLegendStyle from '../../charthelpers/chart-legend.css?inline';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../../navigation-instruments/types.js';\nimport {\n Chart,\n PieController,\n DoughnutController,\n ArcElement,\n Tooltip,\n} from 'chart.js';\nimport type {Plugin, ChartOptions, ChartDataset} from 'chart.js';\nimport {\n CHART_SECTOR_DEFAULT_COLORS,\n CHART_SECTOR_ENHANCED_COLORS,\n CHART_DIMENSIONS,\n OUTER_LABEL_CONFIG,\n getCssVariableValue,\n getChartColorsOrDefault,\n observeThemeChanges,\n calculateSumTotal,\n createArcOuterLabelPlugin,\n calculateFixedHeightChartLayout,\n formatSingleLabel,\n formatNumericValue,\n getChartTooltipOptions,\n generateLegendHTML,\n} from '../../charthelpers/index.js';\n\n// Register Chart.js components\nChart.register(PieController, DoughnutController, ArcElement, Tooltip);\n\n// Pie-specific dimension constants (extends shared CHART_DIMENSIONS)\nconst PIE_DIMENSIONS = {\n ...CHART_DIMENSIONS,\n GAP_AND_BORDER_COLOR: '--container-section-color',\n} as const;\n\nconst PIE_RECREATE_PROP_NAMES = [\n 'priority',\n 'sunburst',\n 'showOuterLabels',\n 'showUnit',\n 'outerLabelUnit',\n 'outerLabelMaxLength',\n 'outerLabelDecimalPlaces',\n 'showDebugOverlay',\n 'fixedHeight',\n] as const;\n\nconst PIE_WATCHED_PROP_NAMES = [\n 'legend',\n 'data',\n 'colors',\n 'priority',\n 'sunburst',\n 'showOuterLabels',\n 'showUnit',\n 'outerLabelUnit',\n 'outerLabelMaxLength',\n 'outerLabelDecimalPlaces',\n 'showDebugOverlay',\n 'fixedHeight',\n] as const;\n\ntype PieChartChildDataItem = {\n label: string;\n value: number;\n};\n\nexport type PieChartDataItem = {\n label: string;\n value: number;\n children?: PieChartChildDataItem[];\n};\n\n/**\n * `<obc-pie-chart>` – A customizable pie chart component for visualizing proportional data as segments, with optional sunburst subsegments and outer labels.\n *\n * This component renders an interactive pie chart powered by Chart.js, displaying data segments as arcs with optional outer labels and a sunburst mode for hierarchical data. It supports customizable colors, percentage or unit display, and adapts its layout based on available space. Labels are hidden when the chart is too small (< 192px height), ensuring clarity at all sizes.\n *\n * ## Features\n * - **Fixed Height ⇒ Fixed Circumference:** The chart's circumference is determined by the `fixedHeight` property (default: 320px). This ensures the donut's circumference remains consistent and matches other radial instruments, regardless of the available browser or container width. The chart does not scale to fill the width; instead, it always uses the specified fixed height to define its size and circumference.\n * - **Layout:**\n * - Full 360° pie chart layout.\n * - **Outer Labels:**\n * - Optional labels positioned outside the chart showing segment names and values.\n * - Supports percentage or custom units (e.g., \"kW\", \"kg\", \"MB\").\n * - Configurable decimal places and maximum label length (with trimming).\n * - **Sunburst Mode:**\n * - Enable hierarchical data display with interactive subsegments (children) as an outer ring.\n * - Click a segment to expand/collapse its children in the sunburst ring.\n * - **Customization:**\n * - Custom segment colors (with automatic fallback to theme palette).\n * - Adjustable outer label formatting and units.\n * - **Color Priority:** Set `priority` to `Priority.enhanced` to use the blue/enhanced\n * color palette instead of the default gray/regular palette (default: `Priority.regular`).\n * - **Responsive Behavior:**\n * - Automatically hides labels when height < 192px.\n * - Maintains aspect ratio and adjusts padding for optimal label positioning.\n * - **Theme Integration:**\n * - Colors update automatically when the `data-obc-theme` attribute changes on the `<html>` element.\n * - Example:\n * ```\n * <html lang=\"en\" data-obc-theme=\"day\"></html>\n * ```\n *\n * ## Example\n *\n * **Basic Usage**\n * ```html\n * <obc-pie-chart></obc-pie-chart>\n * <script>\n * document.querySelector('obc-pie-chart').data = [\n * {label: 'A', value: 50},\n * {label: 'B', value: 30},\n * {label: 'C', value: 20}\n * ];\n * </script>\n * ```\n *\n * **With Sunburst Subsegments**\n * ```html\n * <obc-pie-chart></obc-pie-chart>\n * <script>\n * const chart = document.querySelector('obc-pie-chart');\n * chart.sunburst = true;\n * chart.data = [\n * {label: 'A', value: 50, children: [\n * {label: 'A1', value: 30},\n * {label: 'A2', value: 20}\n * ]},\n * {label: 'B', value: 30}\n * ];\n * </script>\n * ```\n *\n * **Custom Colors and Units**\n * ```html\n * <obc-pie-chart></obc-pie-chart>\n * <script>\n * const chart = document.querySelector('obc-pie-chart');\n * chart.showOuterLabels = true;\n * chart.outerLabelUnit = 'kW';\n * chart.outerLabelDecimalPlaces = 2;\n * chart.data = [\n * {label: 'Critical', value: 20},\n * {label: 'Warning', value: 35},\n * {label: 'Normal', value: 45}\n * ];\n * chart.colors = ['#e74c3c', '#f39c12', '#2ecc71'];\n * </script>\n * ```\n *\n * @property {Array<{label: string, value: number, children?: Array<{label: string, value: number}>}>} data - Chart data segments with optional children subsegments for sunburst mode (set via JavaScript)\n * @property {string[]} colors - Custom segment colors (set via JavaScript) with fallback to theme palette\n * @property {boolean} showOuterLabels - Show outer labels, default: false\n * @property {boolean} showUnit - Whether to show unit in labels, default: false\n * @property {boolean} sunburst - Enable sunburst mode with interactive children subsegments, default: false\n * @property {string} outerLabelUnit - Unit string to append to outer labels, default: \"%\"\n * @property {number} outerLabelMaxLength - Maximum character length for labels before trim (0 = no limit), default: 0\n * @property {number} outerLabelDecimalPlaces - Number of decimal places in labels, default: 0\n * @property {boolean} showDebugOverlay - Show debug overlay for development, default: false\n * @property {number} fixedHeight - Fixed height of the chart in pixels (mandatory, determines chart circumference), default: 320. The chart's circumference is always based on this fixed height to match other radial instruments.\n * @property {boolean} legend - Whether to display the legend below the chart, default: false\n * @beta\n */\n@customElement('obc-pie-chart')\nexport class ObcPieChart extends LitElement {\n @property({type: Array, attribute: false})\n data: PieChartDataItem[] = [];\n\n @property({type: Array, attribute: false})\n colors: string[] = [];\n\n @property({type: String})\n priority: Priority = Priority.regular;\n\n @property({type: Boolean})\n showOuterLabels = false;\n\n @property({type: Boolean})\n showUnit = false;\n\n @property({type: Boolean})\n sunburst = false;\n\n @property({type: String})\n outerLabelUnit = '%';\n\n /** @availableWhen showOuterLabels==true */\n @property({\n type: Number,\n })\n outerLabelMaxLength = 0;\n\n @property({\n type: Number,\n })\n outerLabelDecimalPlaces = 0;\n\n @property({type: Boolean, reflect: true})\n legend = false;\n\n @property({type: Boolean, reflect: true})\n showDebugOverlay = false;\n\n @property({type: Number, reflect: true})\n fixedHeight = 320;\n\n /** @internal */\n @state() private total = 0;\n\n /** @internal - Pre-formatted labels for outer label rendering */\n @state() private formattedLabels: string[] = [];\n\n /** @internal */\n @state() private activeSegmentIndex: number | null = null;\n\n /** @internal */\n @query('canvas') private canvasEl?: HTMLCanvasElement;\n\n /** @internal */\n @query('.legend') private legendDiv?: HTMLDivElement;\n\n /** @internal */\n private chart?: Chart;\n\n /** @internal */\n private themeObserver?: MutationObserver;\n\n /** @internal - ResizeObserver for tracking height threshold crossings */\n private resizeObserver?: ResizeObserver;\n\n /** @internal - Track previous state to detect threshold crossing */\n private wasAboveThreshold = false;\n\n private hasAnyChanged(\n changed: PropertyValues,\n props: readonly (keyof ObcPieChart)[]\n ): boolean {\n return props.some((prop) => changed.has(prop));\n }\n\n /**\n * Get layout configuration for canvas calculation\n */\n private getLayoutConfig() {\n return {\n unit: this.outerLabelUnit,\n showUnit: this.showUnit,\n outerLabelMaxLength: this.outerLabelMaxLength,\n decimalPlaces: this.outerLabelDecimalPlaces,\n data: this.data,\n denominator: this.total > 0 ? this.total : 1,\n };\n }\n\n // Calculate derived state BEFORE render\n override willUpdate(changed: PropertyValues) {\n if (changed.has('data')) {\n this.total = calculateSumTotal(this.data);\n }\n }\n\n // Update external library AFTER render\n override updated(changed: PropertyValues) {\n super.updated(changed);\n\n if (this.hasAnyChanged(changed, PIE_WATCHED_PROP_NAMES)) {\n // Recreate chart when major layout properties change or when plugin configuration changes\n // These properties affect aspect ratio calculation, plugin registration, or outer label rendering\n const needsRecreation = this.hasAnyChanged(\n changed,\n PIE_RECREATE_PROP_NAMES\n );\n\n if (needsRecreation) {\n this.chart?.destroy();\n this.removeSunburstInteraction();\n this.createChart();\n if (this.sunburst) {\n this.setupSunburstInteraction();\n }\n } else {\n this.updateChart();\n }\n }\n }\n\n override firstUpdated() {\n this.createChart();\n this.themeObserver = observeThemeChanges(() => this.updateChartColors());\n this.setupResizeObserver();\n\n // Add click listeners for sunburst interaction\n if (this.sunburst) {\n this.setupSunburstInteraction();\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.chart?.destroy();\n this.themeObserver?.disconnect();\n this.resizeObserver?.disconnect();\n this.removeSunburstInteraction();\n }\n\n /**\n * Setup resize observer to detect when fixedHeight property changes programmatically\n * (e.g., via Storybook controls or user code)\n */\n private setupResizeObserver() {\n if (!this.canvasEl) return;\n\n this.resizeObserver = new ResizeObserver(() => {\n if (!this.chart) return;\n\n const height = this.canvasEl?.clientHeight ?? 0;\n const isAboveThreshold =\n height >= CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n\n // Only recreate chart if we crossed the threshold\n if (isAboveThreshold !== this.wasAboveThreshold) {\n this.wasAboveThreshold = isAboveThreshold;\n this.chart.destroy();\n this.createChart();\n } else {\n // Height changed but didn't cross threshold - just update\n this.updateChart();\n }\n });\n\n this.resizeObserver.observe(this.canvasEl);\n\n // Initialize threshold state\n const height = this.canvasEl.clientHeight;\n this.wasAboveThreshold = height >= CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n }\n\n /** @internal */\n private handleCanvasClick = (event: MouseEvent) => {\n if (!this.chart || !this.sunburst) return;\n\n const elements = this.chart.getElementsAtEventForMode(\n event as unknown as Event,\n 'nearest',\n {intersect: true},\n false\n );\n\n if (elements.length > 0) {\n const clickedIndex = elements[0].index;\n // Toggle: if already active, deactivate; otherwise activate\n const newIndex =\n this.activeSegmentIndex === clickedIndex ? null : clickedIndex;\n this.activeSegmentIndex = newIndex;\n\n // Recreate chart to update plugins with new hideIndex and radius\n this.chart.destroy();\n this.createChart();\n }\n };\n\n private setupSunburstInteraction() {\n if (!this.canvasEl) return;\n this.canvasEl.addEventListener('click', this.handleCanvasClick);\n this.canvasEl.style.cursor = 'pointer';\n }\n\n private removeSunburstInteraction() {\n if (!this.canvasEl) return;\n this.canvasEl.removeEventListener('click', this.handleCanvasClick);\n this.canvasEl.style.cursor = '';\n }\n\n private prepareChartData() {\n const values = this.data.map((d) => d.value);\n const labels = this.data.map((d) => d.label);\n const chartColors = getChartColorsOrDefault(\n this,\n this.colors,\n this.priority === Priority.enhanced\n ? CHART_SECTOR_ENHANCED_COLORS\n : CHART_SECTOR_DEFAULT_COLORS\n );\n const segmentColors = values.map(\n (_, index) => chartColors[index % chartColors.length]\n );\n\n if (!this.sunburst) {\n return {\n values,\n labels,\n colors: segmentColors,\n sunburstValues: [],\n sunburstColors: [],\n sunburstLabels: [],\n };\n }\n\n // Sunburst mode: create outer ring dataset and shrink the 'inner' pie chart radius\n const sunburstValues: number[] = [];\n const sunburstColors: string[] = [];\n const sunburstLabels: string[] = [];\n\n this.data.forEach((segment, parentIndex) => {\n const children = segment.children || [];\n\n if (children.length > 0) {\n // Add children to outer/sunburst ring\n children.forEach((child, childIndex) => {\n sunburstValues.push(child.value);\n sunburstLabels.push(child.label);\n // Use next colors in sequence after parent color\n const colorIndex =\n (parentIndex + childIndex + 1) % chartColors.length;\n sunburstColors.push(chartColors[colorIndex]);\n });\n } else {\n // No children: add transparent placeholder with same value as parent\n sunburstValues.push(segment.value);\n sunburstLabels.push('');\n sunburstColors.push('transparent');\n }\n });\n\n return {\n values,\n labels,\n colors: segmentColors,\n sunburstValues,\n sunburstColors,\n sunburstLabels,\n };\n }\n\n /**\n * Get Chart.js options using centralized fixed height layout calculation\n */\n private getChartOptions(): ChartOptions<'pie'> {\n // If sunburst mode and a segment is active, reduce the pie chart radius\n // to make room for the outer ring while keeping total size at CHART_WIDTH\n const radiusPercentage =\n this.sunburst && this.activeSegmentIndex !== null ? 75 : 100;\n\n // Use centralized layout calculation helper\n const dimensions = calculateFixedHeightChartLayout({\n fixedHeight: this.fixedHeight,\n isHalfMode: false, // Pie charts are always full circles\n showOuterLabels: this.showOuterLabels,\n canvasEl: this.canvasEl,\n layoutConfig: this.getLayoutConfig(),\n host: this,\n });\n\n // Store formatted labels for use in plugins\n this.formattedLabels = dimensions.formattedLabels;\n\n // Set CSS variables for wrapper and canvas sizing\n this.style.setProperty('--chart-width', `${dimensions.calculatedWidth}px`);\n this.style.setProperty('--chart-height', `${dimensions.actualHeight}px`);\n\n // Calculate dynamic padding for Chart.js layout\n const dynamicPadding = dimensions.isTooSmall\n ? {top: 0, right: 0, bottom: 0, left: 0}\n : {\n top: dimensions.topPadding,\n right: dimensions.rightPadding,\n bottom: dimensions.bottomPadding,\n left: dimensions.leftPadding,\n };\n\n return {\n responsive: true,\n maintainAspectRatio: true,\n aspectRatio: dimensions.aspectRatio,\n radius: `${radiusPercentage}%`,\n layout: {\n padding: dynamicPadding ?? PIE_DIMENSIONS.CANVAS_PADDING,\n },\n plugins: {\n legend: {\n display: false,\n labels: {\n generateLabels: () => [], // Prevent Chart.js from generating labels internally\n },\n onClick: () => {}, // Disable legend click handler\n },\n tooltip: {\n ...getChartTooltipOptions(this),\n enabled: !dimensions.isTooSmall,\n filter: (tooltipItem) => {\n // Hide tooltips for transparent placeholder segments\n const dataset = tooltipItem.dataset;\n const bgColor = Array.isArray(dataset.backgroundColor)\n ? dataset.backgroundColor[tooltipItem.dataIndex]\n : dataset.backgroundColor;\n return bgColor !== 'transparent';\n },\n callbacks: {\n title: () => '', // No title line\n label: (context) => {\n const label = context.label ?? '';\n const value = context.parsed;\n const denominator = this.total > 0 ? this.total : 1;\n const isPercentage = this.outerLabelUnit === '%';\n const numericValue = formatNumericValue(\n value,\n denominator,\n isPercentage,\n this.outerLabelDecimalPlaces\n );\n const showUnit = this.showUnit && this.outerLabelUnit;\n return showUnit\n ? `${label} ${numericValue}${this.outerLabelUnit}`\n : `${label} ${numericValue}`;\n },\n },\n },\n },\n animation: {\n animateRotate: false,\n animateScale: false,\n },\n };\n }\n\n private createOuterLabelPiePlugin(): Plugin {\n return createArcOuterLabelPlugin(this, {\n formattedLabels: this.formattedLabels,\n hideIndex: this.sunburst ? this.activeSegmentIndex : null,\n }) as Plugin;\n }\n\n private createChart() {\n // Guard: Verify canvas exists and is connected to DOM\n if (!this.canvasEl || !this.canvasEl.isConnected) return;\n\n const ctx = this.canvasEl.getContext('2d');\n if (!ctx) return;\n\n const {\n values,\n labels,\n colors,\n sunburstValues,\n sunburstColors,\n sunburstLabels,\n } = this.prepareChartData();\n\n // Always use pie chart type, add custom plugin for sunburst\n const datasets: ChartDataset<'pie', number[]>[] = [\n {\n data: values,\n backgroundColor: colors,\n borderWidth: 1,\n borderColor: getCssVariableValue(\n this,\n PIE_DIMENSIONS.GAP_AND_BORDER_COLOR\n ),\n },\n ];\n\n const height = this.canvasEl?.clientHeight ?? 0;\n const isTooSmall = height < CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n\n this.chart = new Chart(ctx, {\n type: 'pie',\n data: {\n labels,\n datasets,\n },\n options: this.getChartOptions(),\n plugins: [\n // Only show outer labels if enabled AND height is large enough\n ...(this.showOuterLabels && !isTooSmall\n ? [this.createOuterLabelPiePlugin()]\n : []),\n this.sunburst && sunburstValues.length > 0\n ? this.createSunburstPlugin(\n sunburstValues,\n sunburstColors,\n sunburstLabels\n )\n : {id: 'sunburst'},\n ].filter((p) => p !== undefined),\n });\n\n // Defer legend update to next tick to ensure Chart.js metadata is initialized\n requestAnimationFrame(() => this.updateLegend());\n }\n\n private createSunburstPlugin(\n _outerValues: number[],\n sunburstColors: string[],\n sunburstLabels: string[]\n ): Plugin {\n return {\n id: 'sunburst',\n afterDatasetsDraw: (chart) => {\n const meta = chart.getDatasetMeta(0);\n if (!meta?.data.length) return;\n\n // Only draw if a segment is active (clicked)\n if (this.activeSegmentIndex === null) return;\n\n const {ctx} = chart;\n const centerX = chart.chartArea.left + chart.chartArea.width / 2;\n const centerY = chart.chartArea.top + chart.chartArea.height / 2;\n\n ctx.save();\n\n // Calculate radii to fit within CHART_WIDTH\n // Inner pie is now at 75% (radius property in getChartOptions)\n const firstArc = meta.data[0] as ArcElement;\n const innerPieRadius = firstArc.outerRadius;\n\n // The original 100% radius (before shrinking to 75%)\n // innerPieRadius = 0.75 * originalRadius, so originalRadius = innerPieRadius / 0.75\n const originalFullRadius = innerPieRadius / 0.75;\n\n // Determine if chart is below label threshold\n const height = this.canvasEl?.clientHeight ?? 0;\n const isTooSmall = height < PIE_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n\n // Gap and thickness logic for small charts\n const gapWidth = isTooSmall ? 2 : 8;\n // For small charts, fill all available space with the sunburst arc\n const outerRingInnerRadius = innerPieRadius + gapWidth;\n const outerRingOuterRadius = isTooSmall\n ? originalFullRadius\n : originalFullRadius;\n // (If you want to reserve a gap to the edge, adjust here)\n\n // Setup font styling for labels\n const fontFamily = getCssVariableValue(\n this,\n OUTER_LABEL_CONFIG.fontFamily\n );\n const fontWeight = getCssVariableValue(\n this,\n OUTER_LABEL_CONFIG.fontWeightVar\n );\n const fontSize = getCssVariableValue(\n this,\n OUTER_LABEL_CONFIG.fontSizeVar\n );\n const fontColor = getCssVariableValue(\n this,\n OUTER_LABEL_CONFIG.fontColorVar\n );\n\n ctx.font = `${fontWeight} ${fontSize} ${fontFamily}`;\n ctx.fillStyle = fontColor;\n ctx.textBaseline = 'middle';\n\n // Draw outer ring segments only for the active parent\n let sunburstDataIndex = 0;\n this.data.forEach((segment, segmentIndex) => {\n const children = segment.children || [];\n\n if (children.length > 0) {\n // Only draw if this is the active segment\n if (segmentIndex === this.activeSegmentIndex) {\n // Calculate total for this parent's children\n const childrenTotal = children.reduce(\n (sum, child) => sum + child.value,\n 0\n );\n let startAngle = 0;\n\n // Find the parent arc to align with it\n const parentArc = meta.data[segmentIndex] as ArcElement;\n const parentStart = parentArc.startAngle;\n const parentEnd = parentArc.endAngle;\n const parentAngleRange = parentEnd - parentStart;\n\n children.forEach((child) => {\n const childValue = child.value;\n const childRatio = childValue / childrenTotal;\n const childAngleRange = parentAngleRange * childRatio;\n const childStartAngle = parentStart + startAngle;\n const childEndAngle = childStartAngle + childAngleRange;\n\n // Draw the outer/sunburst arc\n ctx.fillStyle =\n sunburstColors[sunburstDataIndex] || 'transparent';\n ctx.beginPath();\n ctx.arc(\n centerX,\n centerY,\n outerRingOuterRadius,\n childStartAngle,\n childEndAngle\n );\n ctx.arc(\n centerX,\n centerY,\n outerRingInnerRadius,\n childEndAngle,\n childStartAngle,\n true\n );\n ctx.closePath();\n ctx.fill();\n\n // Draw label for this sunburst segment (if showOuterLabels is enabled)\n if (this.showOuterLabels && sunburstLabels[sunburstDataIndex]) {\n const middleAngle = (childStartAngle + childEndAngle) / 2;\n const labelRadius =\n outerRingOuterRadius + OUTER_LABEL_CONFIG.labelGap;\n const x = centerX + Math.cos(middleAngle) * labelRadius;\n const y = centerY + Math.sin(middleAngle) * labelRadius;\n const alignLeft = Math.cos(middleAngle) >= 0;\n\n ctx.fillStyle = fontColor;\n ctx.textAlign = alignLeft ? 'left' : 'right';\n const textX = alignLeft\n ? x + OUTER_LABEL_CONFIG.labelGap\n : x - OUTER_LABEL_CONFIG.labelGap;\n\n // Format label using shared helper\n const total = this.total > 0 ? this.total : 1;\n const valueText = formatSingleLabel(childValue, total, {\n unit: this.outerLabelUnit,\n showUnit: this.showUnit,\n decimalPlaces: this.outerLabelDecimalPlaces,\n maxLength: this.outerLabelMaxLength,\n });\n\n ctx.fillText(valueText, textX, y);\n }\n\n startAngle += childAngleRange;\n sunburstDataIndex++;\n });\n } else {\n // Skip this parent's children\n sunburstDataIndex += children.length;\n }\n } else {\n sunburstDataIndex++; // Skip transparent placeholders\n }\n });\n\n ctx.restore();\n },\n };\n }\n\n private updateChart() {\n // Guard: Verify chart and canvas still exist and are connected\n if (!this.chart || !this.canvasEl || !this.canvasEl.isConnected) return;\n\n this.chart.update();\n\n // Update legend after chart update completes to ensure metadata is ready\n requestAnimationFrame(() => this.updateLegend());\n }\n\n /**\n * Update only chart colors without recreating the entire chart\n * Used by theme observer for efficient theme changes\n */\n private updateChartColors() {\n // Guard: Verify chart and canvas still exist and are connected\n if (!this.chart || !this.canvasEl || !this.canvasEl.isConnected) return;\n\n const {colors, sunburstColors} = this.prepareChartData();\n\n // Update dataset colors\n if (this.chart.data.datasets[0]) {\n this.chart.data.datasets[0].backgroundColor = colors;\n }\n\n // Update sunburst dataset colors if in sunburst mode\n if (this.sunburst && this.chart.data.datasets[1]) {\n this.chart.data.datasets[1].backgroundColor = sunburstColors;\n }\n\n // Update without animation for instant theme change\n this.chart.update('none');\n\n // Defer legend update to next frame to ensure metadata is ready\n requestAnimationFrame(() => this.updateLegend());\n }\n\n /**\n * Update the legend HTML content\n */\n private updateLegend() {\n // Guard: Check if legend should be shown and chart is ready\n if (!this.legend || !this.legendDiv || !this.chart) return;\n\n // Guard: Check if chart metadata is available\n const meta = this.chart.getDatasetMeta(0);\n if (!meta || !meta.controller) {\n // console.debug('[obc-pie-chart] updateLegend: skipped - chart metadata not yet initialized');\n return;\n }\n\n // Guard: Check if dataset has data\n if (!this.data || this.data.length === 0) {\n // console.debug('[obc-pie-chart] updateLegend: skipped - no data available');\n this.legendDiv.innerHTML = '';\n return;\n }\n\n // Denominator: use max if set, otherwise total, with minimum of 1\n const denominator = this.total > 0 ? this.total : 1;\n const isPercentage = this.outerLabelUnit === '%';\n\n try {\n const legendItems = this.data.map((item, i) => {\n const style = meta.controller.getStyle(i, false);\n const numericValue = formatNumericValue(\n item.value,\n denominator,\n isPercentage,\n this.outerLabelDecimalPlaces\n );\n const showUnit = this.showUnit && this.outerLabelUnit;\n const value = `${numericValue}`;\n const unit = showUnit ? `${this.outerLabelUnit}` : '';\n\n return {\n fillStyle: style.backgroundColor as string,\n label: item.label as string,\n value: value as string,\n unit: unit as string,\n };\n });\n\n const legendHTML = generateLegendHTML(legendItems);\n this.legendDiv.innerHTML = legendHTML;\n } catch (error) {\n console.debug(\n '[obc-pie-chart] updateLegend: error generating legend HTML',\n error\n );\n // Silent failure - don't throw, just skip legend update this time\n }\n }\n\n override render() {\n return html`\n <div class=\"wrapper\">\n <canvas></canvas>\n ${this.legend ? html`<div class=\"legend\"></div>` : ''}\n </div>\n `;\n }\n\n static override styles = [\n unsafeCSS(componentStyle),\n unsafeCSS(chartCommonStyle),\n unsafeCSS(chartLegendStyle),\n unsafeCSS(chartDebugStyle),\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-pie-chart': ObcPieChart;\n }\n}\n"],"names":["height"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"pie-chart.js","sources":["../../../src/bars-graphs/pie-chart/pie-chart.ts"],"sourcesContent":["import {LitElement, PropertyValues, html, unsafeCSS} from 'lit';\nimport {property, query, state} from 'lit/decorators.js';\nimport componentStyle from './pie-chart.css?inline';\nimport chartCommonStyle from '../../charthelpers/chart-common.css?inline';\nimport chartDebugStyle from '../../charthelpers/chart-debug.css?inline';\nimport chartLegendStyle from '../../charthelpers/chart-legend.css?inline';\nimport {customElement} from '../../decorator.js';\nimport {Priority} from '../../navigation-instruments/types.js';\nimport {\n Chart,\n PieController,\n DoughnutController,\n ArcElement,\n Tooltip,\n} from 'chart.js';\nimport type {Plugin, ChartOptions, ChartDataset} from 'chart.js';\nimport {\n CHART_SECTOR_DEFAULT_COLORS,\n CHART_SECTOR_ENHANCED_COLORS,\n CHART_DIMENSIONS,\n OUTER_LABEL_CONFIG,\n getCssVariableValue,\n getChartColorsOrDefault,\n observeThemeChanges,\n calculateSumTotal,\n createArcOuterLabelPlugin,\n calculateFixedHeightChartLayout,\n formatSingleLabel,\n formatNumericValue,\n getChartTooltipOptions,\n generateLegendHTML,\n} from '../../charthelpers/index.js';\n\n// Register Chart.js components\nChart.register(PieController, DoughnutController, ArcElement, Tooltip);\n\n// Pie-specific dimension constants (extends shared CHART_DIMENSIONS)\nconst PIE_DIMENSIONS = {\n ...CHART_DIMENSIONS,\n GAP_AND_BORDER_COLOR: '--container-section-color',\n} as const;\n\nconst PIE_RECREATE_PROP_NAMES = [\n 'priority',\n 'sunburst',\n 'showOuterLabels',\n 'showUnit',\n 'outerLabelUnit',\n 'outerLabelMaxLength',\n 'outerLabelDecimalPlaces',\n 'showDebugOverlay',\n 'fixedHeight',\n] as const;\n\nconst PIE_WATCHED_PROP_NAMES = [\n 'legend',\n 'data',\n 'colors',\n 'priority',\n 'sunburst',\n 'showOuterLabels',\n 'showUnit',\n 'outerLabelUnit',\n 'outerLabelMaxLength',\n 'outerLabelDecimalPlaces',\n 'showDebugOverlay',\n 'fixedHeight',\n] as const;\n\ntype PieChartChildDataItem = {\n label: string;\n value: number;\n};\n\nexport type PieChartDataItem = {\n label: string;\n value: number;\n children?: PieChartChildDataItem[];\n};\n\n/**\n * `<obc-pie-chart>` – A customizable pie chart component for visualizing proportional data as segments, with optional sunburst subsegments and outer labels.\n *\n * This component renders an interactive pie chart powered by Chart.js, displaying data segments as arcs with optional outer labels and a sunburst mode for hierarchical data. It supports customizable colors, percentage or unit display, and adapts its layout based on available space. Labels are hidden when the chart is too small (< 192px height), ensuring clarity at all sizes.\n *\n * ## Features\n * - **Fixed Height ⇒ Fixed Circumference:** The chart's circumference is determined by the `fixedHeight` property (default: 320px). This ensures the donut's circumference remains consistent and matches other radial instruments, regardless of the available browser or container width. The chart does not scale to fill the width; instead, it always uses the specified fixed height to define its size and circumference.\n * - **Layout:**\n * - Full 360° pie chart layout.\n * - **Outer Labels:**\n * - Optional labels positioned outside the chart showing segment names and values.\n * - Supports percentage or custom units (e.g., \"kW\", \"kg\", \"MB\").\n * - Configurable decimal places and maximum label length (with trimming).\n * - **Sunburst Mode:**\n * - Enable hierarchical data display with interactive subsegments (children) as an outer ring.\n * - Click a segment to expand/collapse its children in the sunburst ring.\n * - **Customization:**\n * - Custom segment colors (with automatic fallback to theme palette).\n * - Adjustable outer label formatting and units.\n * - **Color Priority:** Set `priority` to `Priority.enhanced` to use the blue/enhanced\n * color palette instead of the default gray/regular palette (default: `Priority.regular`).\n * - **Responsive Behavior:**\n * - Automatically hides labels when height < 192px.\n * - Maintains aspect ratio and adjusts padding for optimal label positioning.\n * - **Theme Integration:**\n * - Colors update automatically when the `data-obc-theme` attribute changes on the `<html>` element.\n * - Example:\n * ```\n * <html lang=\"en\" data-obc-theme=\"day\"></html>\n * ```\n *\n * ## Example\n *\n * **Basic Usage**\n * ```html\n * <obc-pie-chart></obc-pie-chart>\n * <script>\n * document.querySelector('obc-pie-chart').data = [\n * {label: 'A', value: 50},\n * {label: 'B', value: 30},\n * {label: 'C', value: 20}\n * ];\n * </script>\n * ```\n *\n * **With Sunburst Subsegments**\n * ```html\n * <obc-pie-chart></obc-pie-chart>\n * <script>\n * const chart = document.querySelector('obc-pie-chart');\n * chart.sunburst = true;\n * chart.data = [\n * {label: 'A', value: 50, children: [\n * {label: 'A1', value: 30},\n * {label: 'A2', value: 20}\n * ]},\n * {label: 'B', value: 30}\n * ];\n * </script>\n * ```\n *\n * **Custom Colors and Units**\n * ```html\n * <obc-pie-chart></obc-pie-chart>\n * <script>\n * const chart = document.querySelector('obc-pie-chart');\n * chart.showOuterLabels = true;\n * chart.outerLabelUnit = 'kW';\n * chart.outerLabelDecimalPlaces = 2;\n * chart.data = [\n * {label: 'Critical', value: 20},\n * {label: 'Warning', value: 35},\n * {label: 'Normal', value: 45}\n * ];\n * chart.colors = ['#e74c3c', '#f39c12', '#2ecc71'];\n * </script>\n * ```\n *\n * @beta\n */\n@customElement('obc-pie-chart')\nexport class ObcPieChart extends LitElement {\n /** Chart data segments with optional children subsegments for sunburst mode (set via JavaScript). */\n @property({type: Array, attribute: false})\n data: PieChartDataItem[] = [];\n\n /** Custom segment colors (set via JavaScript) with fallback to theme palette */\n @property({type: Array, attribute: false})\n colors: string[] = [];\n\n @property({type: String})\n priority: Priority = Priority.regular;\n\n /** Show outer labels, default: false */\n @property({type: Boolean})\n showOuterLabels = false;\n\n /** Whether to show unit in labels, default: false */\n @property({type: Boolean})\n showUnit = false;\n\n /** Enable sunburst mode with interactive children subsegments, default: false */\n @property({type: Boolean})\n sunburst = false;\n\n /** Unit string to append to outer labels, default: \"%\" */\n @property({type: String})\n outerLabelUnit = '%';\n\n /**\n * Maximum character length for labels before trim (0 = no limit), default: 0\n * @availableWhen showOuterLabels==true\n */\n @property({\n type: Number,\n })\n outerLabelMaxLength = 0;\n\n /** Number of decimal places in labels, default: 0 */\n @property({\n type: Number,\n })\n outerLabelDecimalPlaces = 0;\n\n /** Whether to display the legend below the chart, default: false */\n @property({type: Boolean, reflect: true})\n legend = false;\n\n /** Show debug overlay for development, default: false */\n @property({type: Boolean, reflect: true})\n showDebugOverlay = false;\n\n /** Fixed height of the chart in pixels (determines chart circumference), default: 320. The chart's circumference is always based on this fixed height to match other radial instruments. */\n @property({type: Number, reflect: true})\n fixedHeight = 320;\n\n /** @internal */\n @state() private total = 0;\n\n /** @internal - Pre-formatted labels for outer label rendering */\n @state() private formattedLabels: string[] = [];\n\n /** @internal */\n @state() private activeSegmentIndex: number | null = null;\n\n /** @internal */\n @query('canvas') private canvasEl?: HTMLCanvasElement;\n\n /** @internal */\n @query('.legend') private legendDiv?: HTMLDivElement;\n\n /** @internal */\n private chart?: Chart;\n\n /** @internal */\n private themeObserver?: MutationObserver;\n\n /** @internal - ResizeObserver for tracking height threshold crossings */\n private resizeObserver?: ResizeObserver;\n\n /** @internal - Track previous state to detect threshold crossing */\n private wasAboveThreshold = false;\n\n private hasAnyChanged(\n changed: PropertyValues,\n props: readonly (keyof ObcPieChart)[]\n ): boolean {\n return props.some((prop) => changed.has(prop));\n }\n\n /**\n * Get layout configuration for canvas calculation\n */\n private getLayoutConfig() {\n return {\n unit: this.outerLabelUnit,\n showUnit: this.showUnit,\n outerLabelMaxLength: this.outerLabelMaxLength,\n decimalPlaces: this.outerLabelDecimalPlaces,\n data: this.data,\n denominator: this.total > 0 ? this.total : 1,\n };\n }\n\n // Calculate derived state BEFORE render\n override willUpdate(changed: PropertyValues) {\n if (changed.has('data')) {\n this.total = calculateSumTotal(this.data);\n }\n }\n\n // Update external library AFTER render\n override updated(changed: PropertyValues) {\n super.updated(changed);\n\n if (this.hasAnyChanged(changed, PIE_WATCHED_PROP_NAMES)) {\n // Recreate chart when major layout properties change or when plugin configuration changes\n // These properties affect aspect ratio calculation, plugin registration, or outer label rendering\n const needsRecreation = this.hasAnyChanged(\n changed,\n PIE_RECREATE_PROP_NAMES\n );\n\n if (needsRecreation) {\n this.chart?.destroy();\n this.removeSunburstInteraction();\n this.createChart();\n if (this.sunburst) {\n this.setupSunburstInteraction();\n }\n } else {\n this.updateChart();\n }\n }\n }\n\n override firstUpdated() {\n this.createChart();\n this.themeObserver = observeThemeChanges(() => this.updateChartColors());\n this.setupResizeObserver();\n\n // Add click listeners for sunburst interaction\n if (this.sunburst) {\n this.setupSunburstInteraction();\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this.chart?.destroy();\n this.themeObserver?.disconnect();\n this.resizeObserver?.disconnect();\n this.removeSunburstInteraction();\n }\n\n /**\n * Setup resize observer to detect when fixedHeight property changes programmatically\n * (e.g., via Storybook controls or user code)\n */\n private setupResizeObserver() {\n if (!this.canvasEl) return;\n\n this.resizeObserver = new ResizeObserver(() => {\n if (!this.chart) return;\n\n const height = this.canvasEl?.clientHeight ?? 0;\n const isAboveThreshold =\n height >= CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n\n // Only recreate chart if we crossed the threshold\n if (isAboveThreshold !== this.wasAboveThreshold) {\n this.wasAboveThreshold = isAboveThreshold;\n this.chart.destroy();\n this.createChart();\n } else {\n // Height changed but didn't cross threshold - just update\n this.updateChart();\n }\n });\n\n this.resizeObserver.observe(this.canvasEl);\n\n // Initialize threshold state\n const height = this.canvasEl.clientHeight;\n this.wasAboveThreshold = height >= CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n }\n\n /** @internal */\n private handleCanvasClick = (event: MouseEvent) => {\n if (!this.chart || !this.sunburst) return;\n\n const elements = this.chart.getElementsAtEventForMode(\n event as unknown as Event,\n 'nearest',\n {intersect: true},\n false\n );\n\n if (elements.length > 0) {\n const clickedIndex = elements[0].index;\n // Toggle: if already active, deactivate; otherwise activate\n const newIndex =\n this.activeSegmentIndex === clickedIndex ? null : clickedIndex;\n this.activeSegmentIndex = newIndex;\n\n // Recreate chart to update plugins with new hideIndex and radius\n this.chart.destroy();\n this.createChart();\n }\n };\n\n private setupSunburstInteraction() {\n if (!this.canvasEl) return;\n this.canvasEl.addEventListener('click', this.handleCanvasClick);\n this.canvasEl.style.cursor = 'pointer';\n }\n\n private removeSunburstInteraction() {\n if (!this.canvasEl) return;\n this.canvasEl.removeEventListener('click', this.handleCanvasClick);\n this.canvasEl.style.cursor = '';\n }\n\n private prepareChartData() {\n const values = this.data.map((d) => d.value);\n const labels = this.data.map((d) => d.label);\n const chartColors = getChartColorsOrDefault(\n this,\n this.colors,\n this.priority === Priority.enhanced\n ? CHART_SECTOR_ENHANCED_COLORS\n : CHART_SECTOR_DEFAULT_COLORS\n );\n const segmentColors = values.map(\n (_, index) => chartColors[index % chartColors.length]\n );\n\n if (!this.sunburst) {\n return {\n values,\n labels,\n colors: segmentColors,\n sunburstValues: [],\n sunburstColors: [],\n sunburstLabels: [],\n };\n }\n\n // Sunburst mode: create outer ring dataset and shrink the 'inner' pie chart radius\n const sunburstValues: number[] = [];\n const sunburstColors: string[] = [];\n const sunburstLabels: string[] = [];\n\n this.data.forEach((segment, parentIndex) => {\n const children = segment.children || [];\n\n if (children.length > 0) {\n // Add children to outer/sunburst ring\n children.forEach((child, childIndex) => {\n sunburstValues.push(child.value);\n sunburstLabels.push(child.label);\n // Use next colors in sequence after parent color\n const colorIndex =\n (parentIndex + childIndex + 1) % chartColors.length;\n sunburstColors.push(chartColors[colorIndex]);\n });\n } else {\n // No children: add transparent placeholder with same value as parent\n sunburstValues.push(segment.value);\n sunburstLabels.push('');\n sunburstColors.push('transparent');\n }\n });\n\n return {\n values,\n labels,\n colors: segmentColors,\n sunburstValues,\n sunburstColors,\n sunburstLabels,\n };\n }\n\n /**\n * Get Chart.js options using centralized fixed height layout calculation\n */\n private getChartOptions(): ChartOptions<'pie'> {\n // If sunburst mode and a segment is active, reduce the pie chart radius\n // to make room for the outer ring while keeping total size at CHART_WIDTH\n const radiusPercentage =\n this.sunburst && this.activeSegmentIndex !== null ? 75 : 100;\n\n // Use centralized layout calculation helper\n const dimensions = calculateFixedHeightChartLayout({\n fixedHeight: this.fixedHeight,\n isHalfMode: false, // Pie charts are always full circles\n showOuterLabels: this.showOuterLabels,\n canvasEl: this.canvasEl,\n layoutConfig: this.getLayoutConfig(),\n host: this,\n });\n\n // Store formatted labels for use in plugins\n this.formattedLabels = dimensions.formattedLabels;\n\n // Set CSS variables for wrapper and canvas sizing\n this.style.setProperty('--chart-width', `${dimensions.calculatedWidth}px`);\n this.style.setProperty('--chart-height', `${dimensions.actualHeight}px`);\n\n // Calculate dynamic padding for Chart.js layout\n const dynamicPadding = dimensions.isTooSmall\n ? {top: 0, right: 0, bottom: 0, left: 0}\n : {\n top: dimensions.topPadding,\n right: dimensions.rightPadding,\n bottom: dimensions.bottomPadding,\n left: dimensions.leftPadding,\n };\n\n return {\n responsive: true,\n maintainAspectRatio: true,\n aspectRatio: dimensions.aspectRatio,\n radius: `${radiusPercentage}%`,\n layout: {\n padding: dynamicPadding ?? PIE_DIMENSIONS.CANVAS_PADDING,\n },\n plugins: {\n legend: {\n display: false,\n labels: {\n generateLabels: () => [], // Prevent Chart.js from generating labels internally\n },\n onClick: () => {}, // Disable legend click handler\n },\n tooltip: {\n ...getChartTooltipOptions(this),\n enabled: !dimensions.isTooSmall,\n filter: (tooltipItem) => {\n // Hide tooltips for transparent placeholder segments\n const dataset = tooltipItem.dataset;\n const bgColor = Array.isArray(dataset.backgroundColor)\n ? dataset.backgroundColor[tooltipItem.dataIndex]\n : dataset.backgroundColor;\n return bgColor !== 'transparent';\n },\n callbacks: {\n title: () => '', // No title line\n label: (context) => {\n const label = context.label ?? '';\n const value = context.parsed;\n const denominator = this.total > 0 ? this.total : 1;\n const isPercentage = this.outerLabelUnit === '%';\n const numericValue = formatNumericValue(\n value,\n denominator,\n isPercentage,\n this.outerLabelDecimalPlaces\n );\n const showUnit = this.showUnit && this.outerLabelUnit;\n return showUnit\n ? `${label} ${numericValue}${this.outerLabelUnit}`\n : `${label} ${numericValue}`;\n },\n },\n },\n },\n animation: {\n animateRotate: false,\n animateScale: false,\n },\n };\n }\n\n private createOuterLabelPiePlugin(): Plugin {\n return createArcOuterLabelPlugin(this, {\n formattedLabels: this.formattedLabels,\n hideIndex: this.sunburst ? this.activeSegmentIndex : null,\n }) as Plugin;\n }\n\n private createChart() {\n // Guard: Verify canvas exists and is connected to DOM\n if (!this.canvasEl || !this.canvasEl.isConnected) return;\n\n const ctx = this.canvasEl.getContext('2d');\n if (!ctx) return;\n\n const {\n values,\n labels,\n colors,\n sunburstValues,\n sunburstColors,\n sunburstLabels,\n } = this.prepareChartData();\n\n // Always use pie chart type, add custom plugin for sunburst\n const datasets: ChartDataset<'pie', number[]>[] = [\n {\n data: values,\n backgroundColor: colors,\n borderWidth: 1,\n borderColor: getCssVariableValue(\n this,\n PIE_DIMENSIONS.GAP_AND_BORDER_COLOR\n ),\n },\n ];\n\n const height = this.canvasEl?.clientHeight ?? 0;\n const isTooSmall = height < CHART_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n\n this.chart = new Chart(ctx, {\n type: 'pie',\n data: {\n labels,\n datasets,\n },\n options: this.getChartOptions(),\n plugins: [\n // Only show outer labels if enabled AND height is large enough\n ...(this.showOuterLabels && !isTooSmall\n ? [this.createOuterLabelPiePlugin()]\n : []),\n this.sunburst && sunburstValues.length > 0\n ? this.createSunburstPlugin(\n sunburstValues,\n sunburstColors,\n sunburstLabels\n )\n : {id: 'sunburst'},\n ].filter((p) => p !== undefined),\n });\n\n // Defer legend update to next tick to ensure Chart.js metadata is initialized\n requestAnimationFrame(() => this.updateLegend());\n }\n\n private createSunburstPlugin(\n _outerValues: number[],\n sunburstColors: string[],\n sunburstLabels: string[]\n ): Plugin {\n return {\n id: 'sunburst',\n afterDatasetsDraw: (chart) => {\n const meta = chart.getDatasetMeta(0);\n if (!meta?.data.length) return;\n\n // Only draw if a segment is active (clicked)\n if (this.activeSegmentIndex === null) return;\n\n const {ctx} = chart;\n const centerX = chart.chartArea.left + chart.chartArea.width / 2;\n const centerY = chart.chartArea.top + chart.chartArea.height / 2;\n\n ctx.save();\n\n // Calculate radii to fit within CHART_WIDTH\n // Inner pie is now at 75% (radius property in getChartOptions)\n const firstArc = meta.data[0] as ArcElement;\n const innerPieRadius = firstArc.outerRadius;\n\n // The original 100% radius (before shrinking to 75%)\n // innerPieRadius = 0.75 * originalRadius, so originalRadius = innerPieRadius / 0.75\n const originalFullRadius = innerPieRadius / 0.75;\n\n // Determine if chart is below label threshold\n const height = this.canvasEl?.clientHeight ?? 0;\n const isTooSmall = height < PIE_DIMENSIONS.MIN_HEIGHT_WITH_LABELS;\n\n // Gap and thickness logic for small charts\n const gapWidth = isTooSmall ? 2 : 8;\n // For small charts, fill all available space with the sunburst arc\n const outerRingInnerRadius = innerPieRadius + gapWidth;\n const outerRingOuterRadius = isTooSmall\n ? originalFullRadius\n : originalFullRadius;\n // (If you want to reserve a gap to the edge, adjust here)\n\n // Setup font styling for labels\n const fontFamily = getCssVariableValue(\n this,\n OUTER_LABEL_CONFIG.fontFamily\n );\n const fontWeight = getCssVariableValue(\n this,\n OUTER_LABEL_CONFIG.fontWeightVar\n );\n const fontSize = getCssVariableValue(\n this,\n OUTER_LABEL_CONFIG.fontSizeVar\n );\n const fontColor = getCssVariableValue(\n this,\n OUTER_LABEL_CONFIG.fontColorVar\n );\n\n ctx.font = `${fontWeight} ${fontSize} ${fontFamily}`;\n ctx.fillStyle = fontColor;\n ctx.textBaseline = 'middle';\n\n // Draw outer ring segments only for the active parent\n let sunburstDataIndex = 0;\n this.data.forEach((segment, segmentIndex) => {\n const children = segment.children || [];\n\n if (children.length > 0) {\n // Only draw if this is the active segment\n if (segmentIndex === this.activeSegmentIndex) {\n // Calculate total for this parent's children\n const childrenTotal = children.reduce(\n (sum, child) => sum + child.value,\n 0\n );\n let startAngle = 0;\n\n // Find the parent arc to align with it\n const parentArc = meta.data[segmentIndex] as ArcElement;\n const parentStart = parentArc.startAngle;\n const parentEnd = parentArc.endAngle;\n const parentAngleRange = parentEnd - parentStart;\n\n children.forEach((child) => {\n const childValue = child.value;\n const childRatio = childValue / childrenTotal;\n const childAngleRange = parentAngleRange * childRatio;\n const childStartAngle = parentStart + startAngle;\n const childEndAngle = childStartAngle + childAngleRange;\n\n // Draw the outer/sunburst arc\n ctx.fillStyle =\n sunburstColors[sunburstDataIndex] || 'transparent';\n ctx.beginPath();\n ctx.arc(\n centerX,\n centerY,\n outerRingOuterRadius,\n childStartAngle,\n childEndAngle\n );\n ctx.arc(\n centerX,\n centerY,\n outerRingInnerRadius,\n childEndAngle,\n childStartAngle,\n true\n );\n ctx.closePath();\n ctx.fill();\n\n // Draw label for this sunburst segment (if showOuterLabels is enabled)\n if (this.showOuterLabels && sunburstLabels[sunburstDataIndex]) {\n const middleAngle = (childStartAngle + childEndAngle) / 2;\n const labelRadius =\n outerRingOuterRadius + OUTER_LABEL_CONFIG.labelGap;\n const x = centerX + Math.cos(middleAngle) * labelRadius;\n const y = centerY + Math.sin(middleAngle) * labelRadius;\n const alignLeft = Math.cos(middleAngle) >= 0;\n\n ctx.fillStyle = fontColor;\n ctx.textAlign = alignLeft ? 'left' : 'right';\n const textX = alignLeft\n ? x + OUTER_LABEL_CONFIG.labelGap\n : x - OUTER_LABEL_CONFIG.labelGap;\n\n // Format label using shared helper\n const total = this.total > 0 ? this.total : 1;\n const valueText = formatSingleLabel(childValue, total, {\n unit: this.outerLabelUnit,\n showUnit: this.showUnit,\n decimalPlaces: this.outerLabelDecimalPlaces,\n maxLength: this.outerLabelMaxLength,\n });\n\n ctx.fillText(valueText, textX, y);\n }\n\n startAngle += childAngleRange;\n sunburstDataIndex++;\n });\n } else {\n // Skip this parent's children\n sunburstDataIndex += children.length;\n }\n } else {\n sunburstDataIndex++; // Skip transparent placeholders\n }\n });\n\n ctx.restore();\n },\n };\n }\n\n private updateChart() {\n // Guard: Verify chart and canvas still exist and are connected\n if (!this.chart || !this.canvasEl || !this.canvasEl.isConnected) return;\n\n this.chart.update();\n\n // Update legend after chart update completes to ensure metadata is ready\n requestAnimationFrame(() => this.updateLegend());\n }\n\n /**\n * Update only chart colors without recreating the entire chart\n * Used by theme observer for efficient theme changes\n */\n private updateChartColors() {\n // Guard: Verify chart and canvas still exist and are connected\n if (!this.chart || !this.canvasEl || !this.canvasEl.isConnected) return;\n\n const {colors, sunburstColors} = this.prepareChartData();\n\n // Update dataset colors\n if (this.chart.data.datasets[0]) {\n this.chart.data.datasets[0].backgroundColor = colors;\n }\n\n // Update sunburst dataset colors if in sunburst mode\n if (this.sunburst && this.chart.data.datasets[1]) {\n this.chart.data.datasets[1].backgroundColor = sunburstColors;\n }\n\n // Update without animation for instant theme change\n this.chart.update('none');\n\n // Defer legend update to next frame to ensure metadata is ready\n requestAnimationFrame(() => this.updateLegend());\n }\n\n /**\n * Update the legend HTML content\n */\n private updateLegend() {\n // Guard: Check if legend should be shown and chart is ready\n if (!this.legend || !this.legendDiv || !this.chart) return;\n\n // Guard: Check if chart metadata is available\n const meta = this.chart.getDatasetMeta(0);\n if (!meta || !meta.controller) {\n // console.debug('[obc-pie-chart] updateLegend: skipped - chart metadata not yet initialized');\n return;\n }\n\n // Guard: Check if dataset has data\n if (!this.data || this.data.length === 0) {\n // console.debug('[obc-pie-chart] updateLegend: skipped - no data available');\n this.legendDiv.innerHTML = '';\n return;\n }\n\n // Denominator: use max if set, otherwise total, with minimum of 1\n const denominator = this.total > 0 ? this.total : 1;\n const isPercentage = this.outerLabelUnit === '%';\n\n try {\n const legendItems = this.data.map((item, i) => {\n const style = meta.controller.getStyle(i, false);\n const numericValue = formatNumericValue(\n item.value,\n denominator,\n isPercentage,\n this.outerLabelDecimalPlaces\n );\n const showUnit = this.showUnit && this.outerLabelUnit;\n const value = `${numericValue}`;\n const unit = showUnit ? `${this.outerLabelUnit}` : '';\n\n return {\n fillStyle: style.backgroundColor as string,\n label: item.label as string,\n value: value as string,\n unit: unit as string,\n };\n });\n\n const legendHTML = generateLegendHTML(legendItems);\n this.legendDiv.innerHTML = legendHTML;\n } catch (error) {\n console.debug(\n '[obc-pie-chart] updateLegend: error generating legend HTML',\n error\n );\n // Silent failure - don't throw, just skip legend update this time\n }\n }\n\n override render() {\n return html`\n <div class=\"wrapper\">\n <canvas></canvas>\n ${this.legend ? html`<div class=\"legend\"></div>` : ''}\n </div>\n `;\n }\n\n static override styles = [\n unsafeCSS(componentStyle),\n unsafeCSS(chartCommonStyle),\n unsafeCSS(chartLegendStyle),\n unsafeCSS(chartDebugStyle),\n ];\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'obc-pie-chart': ObcPieChart;\n }\n}\n"],"names":["height"],"mappings":"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"}
|
|
@@ -82,40 +82,43 @@ export type PolarChartDataItem = {
|
|
|
82
82
|
* </script>
|
|
83
83
|
* ```
|
|
84
84
|
*
|
|
85
|
-
* @property {Array<{label: string, value: number}>} data - Chart data segments (set via JavaScript)
|
|
86
|
-
* @property {string[]} colors - Custom segment colors (set via JavaScript) with fallback to theme palette
|
|
87
|
-
* @property {boolean} monochrome - Use single color for all sectors (uses first color from array, default: false)
|
|
88
|
-
* @property {boolean} discreteColorStops - Draw sectors as radial color bands from center outward using the colors array as threshold steps (default: false)
|
|
89
|
-
* @property {boolean} trimToDiscreteStops - When true, visually trim sectors to the nearest discrete color band boundary. When false, show exact values with partial band fills (default: true)
|
|
90
|
-
* @property {boolean} showSectorLabels - When true, display sector labels from data (e.g. "Sector A"). When false, display angle values (0°, 30°, etc.). Default: false
|
|
91
|
-
* @property {boolean} showUnit - Whether to show unit in angle or outer labels, default: false
|
|
92
|
-
* @property {boolean} showOuterLabels - Show outer labels, default: false
|
|
93
|
-
* @property {string} outerLabelUnit - Unit string to append to outer labels, default: ""
|
|
94
|
-
* @property {number} outerLabelMaxLength - Maximum character length for labels before trim (0 = no limit), default: 0
|
|
95
|
-
* @property {number} outerLabelDecimalPlaces - Number of decimal places in labels, default: 0
|
|
96
|
-
* @property {boolean} showDebugOverlay - Show debug overlay for development, default: false
|
|
97
|
-
* @property {number} fixedHeight - Fixed height of the chart in pixels (mandatory, determines chart circumference), default: 320. The chart's circumference is always based on this fixed height to match other radial instruments.
|
|
98
|
-
* @property {boolean} legend - Whether to display the legend below the chart, default: false
|
|
99
85
|
* @beta
|
|
100
86
|
*/
|
|
101
87
|
export declare class ObcPolarChart extends LitElement {
|
|
88
|
+
/** Chart data segments (set via JavaScript) */
|
|
102
89
|
data: PolarChartDataItem[];
|
|
90
|
+
/** Custom segment colors (set via JavaScript) with fallback to theme palette */
|
|
103
91
|
colors: string[];
|
|
104
92
|
/** @internal */
|
|
105
93
|
private centerFirstSector;
|
|
106
94
|
priority: Priority;
|
|
107
|
-
/**
|
|
95
|
+
/**
|
|
96
|
+
* Use single color for all sectors (uses first color from array, default: false)
|
|
97
|
+
* @availableWhen discreteColorStops==false
|
|
98
|
+
*/
|
|
108
99
|
monochrome: boolean;
|
|
100
|
+
/** Draw sectors as radial color bands from center outward using the colors array as threshold steps (default: false) */
|
|
109
101
|
discreteColorStops: boolean;
|
|
102
|
+
/** When true, display sector labels from data (e.g. "Sector A"). When false, display angle values (0°, 30°, etc.). Default: false */
|
|
110
103
|
showSectorLabels: boolean;
|
|
104
|
+
/** Whether to show unit in angle or outer labels, default: false */
|
|
111
105
|
showUnit: boolean;
|
|
106
|
+
/** Show outer labels, default: false */
|
|
112
107
|
showOuterLabels: boolean;
|
|
108
|
+
/** Unit string to append to outer labels, default: "°" */
|
|
113
109
|
outerLabelUnit: string;
|
|
114
|
-
/**
|
|
110
|
+
/**
|
|
111
|
+
* Maximum character length for labels before trim (0 = no limit), default: 0
|
|
112
|
+
* @availableWhen showOuterLabels==true
|
|
113
|
+
*/
|
|
115
114
|
outerLabelMaxLength: number;
|
|
115
|
+
/** Number of decimal places in labels, default: 0 */
|
|
116
116
|
outerLabelDecimalPlaces: number;
|
|
117
|
+
/** Fixed height of the chart in pixels (determines chart circumference), default: 320. The chart's circumference is always based on this fixed height to match other radial instruments. */
|
|
117
118
|
fixedHeight: number;
|
|
119
|
+
/** Whether to display the legend below the chart, default: false */
|
|
118
120
|
legend: boolean;
|
|
121
|
+
/** Show debug overlay for development, default: false */
|
|
119
122
|
showDebugOverlay: boolean;
|
|
120
123
|
/** @internal - Pre-formatted labels for outer label rendering */
|
|
121
124
|
private formattedLabels;
|