@ifto/mantine-kit 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -226,6 +226,10 @@ The chart types in `component/organism/EChart/chart` (`LINE_CHART`, `BAR_CHART`,
226
226
  build a complete option, with one panel per unit, from generic series:
227
227
  `option={LINE_CHART.buildOption(data, { title: 'Revenue', locale: 'en-US' })}`.
228
228
 
229
+ Each of these types has an `icon`, to show in a chart type selector (e.g. `IconChartBar` for `BAR_CHART`). To use another
230
+ one, create the type with it: `new BarChart(IconChartHistogram)`. The `icon` is optional in the `ChartType` contract, so
231
+ a custom chart type does not need one.
232
+
229
233
  ### Export to Excel or CSV
230
234
 
231
235
  ```tsx
@@ -1,3 +1,4 @@
1
+ import { type Icon } from '@tabler/icons-react';
1
2
  import { ChartSeries } from './ChartSeries';
2
3
  import { ChartTypeId } from './ChartTypeId';
3
4
  import { CartesianChart, CartesianSeries, DataPoint } from './CartesianChart';
@@ -11,6 +12,8 @@ export declare const NEGATIVE_VALUE_COLOR = "#d9480f";
11
12
  */
12
13
  export declare class BarChart extends CartesianChart {
13
14
  readonly id: ChartTypeId;
15
+ /** @param icon icon that replaces the default one */
16
+ constructor(icon?: Icon);
14
17
  protected seriesStyle(): CartesianSeries;
15
18
  protected seriesData(serie: ChartSeries): DataPoint[];
16
19
  }
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { CartesianChart } from "./CartesianChart.js";
3
+ import { IconChartBar } from "@tabler/icons-react";
3
4
  // src/component/organism/EChart/chart/BarChart.ts
4
5
  /** Color of the columns with a negative value (e.g. a deficit), to set them apart from the positive ones. */
5
6
  var NEGATIVE_VALUE_COLOR = "#d9480f";
@@ -11,6 +12,10 @@ var NEGATIVE_VALUE_COLOR = "#d9480f";
11
12
  */
12
13
  var BarChart = class extends CartesianChart {
13
14
  id = "bar";
15
+ /** @param icon icon that replaces the default one */
16
+ constructor(icon = IconChartBar) {
17
+ super(icon);
18
+ }
14
19
  seriesStyle() {
15
20
  return { type: "bar" };
16
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"BarChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/BarChart.ts"],"sourcesContent":["import { ChartSeries } from './ChartSeries';\nimport { ChartTypeId } from './ChartTypeId';\nimport { CartesianChart, CartesianSeries, DataPoint } from './CartesianChart';\n\n/** Color of the columns with a negative value (e.g. a deficit), to set them apart from the positive ones. */\nexport const NEGATIVE_VALUE_COLOR = '#d9480f';\n\n/**\n * Grouped column chart: compares the series category by category.\n * Suited to flows (e.g. yearly values) and to balances that may be negative (deficit/surplus): the negative columns\n * get the {@link NEGATIVE_VALUE_COLOR}, without changing the color of the series in the legend.\n * @author Manoel Campos\n */\nexport class BarChart extends CartesianChart {\n readonly id: ChartTypeId = 'bar';\n\n protected seriesStyle(): CartesianSeries {\n return { type: 'bar' };\n }\n\n protected seriesData(serie: ChartSeries): DataPoint[] {\n return highlightNegativeValues(serie.values);\n }\n}\n\n/**\n * Gives the {@link NEGATIVE_VALUE_COLOR} only to the negative values. The others keep the color of the series.\n * @param values values of a series\n * @return the values in the `series[i].data` format, with their own style in the negative ones\n */\nexport function highlightNegativeValues(values: (number | null)[]): DataPoint[] {\n return values.map(value =>\n value !== null && value < 0 ? { value, itemStyle: { color: NEGATIVE_VALUE_COLOR } } : value\n );\n}\n"],"mappings":";;;;AAKA,IAAa,uBAAuB;;;;;;;AAQpC,IAAa,WAAb,cAA8B,eAAe;CACzC,KAA2B;CAE3B,cAAyC;EACrC,OAAO,EAAE,MAAM,MAAM;CACzB;CAEA,WAAqB,OAAiC;EAClD,OAAO,wBAAwB,MAAM,MAAM;CAC/C;AACJ;;;;;;AAOA,SAAgB,wBAAwB,QAAwC;CAC5E,OAAO,OAAO,KAAI,UACd,UAAU,QAAQ,QAAQ,IAAI;EAAE;EAAO,WAAW,EAAE,OAAO,qBAAqB;CAAE,IAAI,KAC1F;AACJ"}
1
+ {"version":3,"file":"BarChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/BarChart.ts"],"sourcesContent":["import { IconChartBar, type Icon } from '@tabler/icons-react';\n\nimport { ChartSeries } from './ChartSeries';\nimport { ChartTypeId } from './ChartTypeId';\nimport { CartesianChart, CartesianSeries, DataPoint } from './CartesianChart';\n\n/** Color of the columns with a negative value (e.g. a deficit), to set them apart from the positive ones. */\nexport const NEGATIVE_VALUE_COLOR = '#d9480f';\n\n/**\n * Grouped column chart: compares the series category by category.\n * Suited to flows (e.g. yearly values) and to balances that may be negative (deficit/surplus): the negative columns\n * get the {@link NEGATIVE_VALUE_COLOR}, without changing the color of the series in the legend.\n * @author Manoel Campos\n */\nexport class BarChart extends CartesianChart {\n readonly id: ChartTypeId = 'bar';\n\n /** @param icon icon that replaces the default one */\n constructor(icon: Icon = IconChartBar) {\n super(icon);\n }\n\n protected seriesStyle(): CartesianSeries {\n return { type: 'bar' };\n }\n\n protected seriesData(serie: ChartSeries): DataPoint[] {\n return highlightNegativeValues(serie.values);\n }\n}\n\n/**\n * Gives the {@link NEGATIVE_VALUE_COLOR} only to the negative values. The others keep the color of the series.\n * @param values values of a series\n * @return the values in the `series[i].data` format, with their own style in the negative ones\n */\nexport function highlightNegativeValues(values: (number | null)[]): DataPoint[] {\n return values.map(value =>\n value !== null && value < 0 ? { value, itemStyle: { color: NEGATIVE_VALUE_COLOR } } : value\n );\n}\n"],"mappings":";;;;;AAOA,IAAa,uBAAuB;;;;;;;AAQpC,IAAa,WAAb,cAA8B,eAAe;CACzC,KAA2B;;CAG3B,YAAY,OAAa,cAAc;EACnC,MAAM,IAAI;CACd;CAEA,cAAyC;EACrC,OAAO,EAAE,MAAM,MAAM;CACzB;CAEA,WAAqB,OAAiC;EAClD,OAAO,wBAAwB,MAAM,MAAM;CAC/C;AACJ;;;;;;AAOA,SAAgB,wBAAwB,QAAwC;CAC5E,OAAO,OAAO,KAAI,UACd,UAAU,QAAQ,QAAQ,IAAI;EAAE;EAAO,WAAW,EAAE,OAAO,qBAAqB;CAAE,IAAI,KAC1F;AACJ"}
@@ -1,3 +1,4 @@
1
+ import type { Icon } from '@tabler/icons-react';
1
2
  import type { BarSeriesOption, EChartsOption, LineSeriesOption } from 'echarts';
2
3
  import { ChartData, ChartSeries } from './ChartSeries';
3
4
  import { ChartContext, ChartType } from './ChartType';
@@ -17,8 +18,11 @@ export type DataPoint = number | null | {
17
18
  * @author Manoel Campos
18
19
  */
19
20
  export declare abstract class CartesianChart implements ChartType {
21
+ readonly icon?: Icon | undefined;
20
22
  abstract readonly id: ChartTypeId;
21
23
  readonly singleCategory = false;
24
+ /** @param icon icon of the type (see {@link ChartType#icon}) */
25
+ constructor(icon?: Icon | undefined);
22
26
  /** Types with axes work for any set of series, except the ones that restrict it (see the subclasses). */
23
27
  isAvailable(series: ChartSeries[]): boolean;
24
28
  buildOption(data: ChartData, context: ChartContext): EChartsOption;
@@ -9,7 +9,12 @@ import { buildChartHeader, legendExtraHeight, tooltipFormatter } from "./ChartHe
9
9
  * @author Manoel Campos
10
10
  */
11
11
  var CartesianChart = class {
12
+ icon;
12
13
  singleCategory = false;
14
+ /** @param icon icon of the type (see {@link ChartType#icon}) */
15
+ constructor(icon) {
16
+ this.icon = icon;
17
+ }
13
18
  /** Types with axes work for any set of series, except the ones that restrict it (see the subclasses). */
14
19
  isAvailable(series) {
15
20
  return series.length > 0;
@@ -1 +1 @@
1
- {"version":3,"file":"CartesianChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/CartesianChart.ts"],"sourcesContent":["import type { BarSeriesOption, EChartsOption, LineSeriesOption } from 'echarts';\n\nimport { ChartData, ChartSeries } from './ChartSeries';\nimport { ChartContext, ChartType } from './ChartType';\nimport { ChartTypeId } from './ChartTypeId';\nimport { chartLocale, chartMessages } from './ChartTexts';\nimport { buildPanelAxes, groupByUnit, panelsHeight } from './UnitPanels';\nimport { buildChartHeader, legendExtraHeight, tooltipFormatter } from './ChartHeader';\n\n/** Column or line series, the two formats used in the charts with axes (cartesian). */\nexport type CartesianSeries = BarSeriesOption | LineSeriesOption;\n\n/** Value of a category in a series, in the format accepted by `series[i].data` (with or without its own style). */\nexport type DataPoint = number | null | { value: number; itemStyle: { color: string } };\n\n/**\n * Base of the chart types with an X axis of categories (line, columns, stacked columns).\n * It builds the panels per unit, the header and the tooltip, leaving to each type just the style of each series.\n * @author Manoel Campos\n */\nexport abstract class CartesianChart implements ChartType {\n abstract readonly id: ChartTypeId;\n readonly singleCategory = false;\n\n /** Types with axes work for any set of series, except the ones that restrict it (see the subclasses). */\n isAvailable(series: ChartSeries[]): boolean {\n return series.length > 0;\n }\n\n buildOption(data: ChartData, context: ChartContext): EChartsOption {\n const panels = groupByUnit(data.series);\n const series = panels.flatMap((panel, index) =>\n panel.series.map(serie => this.buildSeries(serie, data.series, index))\n );\n const names = data.series.map(serie => serie.name);\n const extraTop = legendExtraHeight(names, context.width);\n\n return {\n ...buildChartHeader(context.title, names, chartMessages(context)),\n tooltip: { trigger: 'axis' },\n ...buildPanelAxes(panels, data.categories, extraTop, chartLocale(context)),\n series\n };\n }\n\n height(data: ChartData, context: ChartContext): number {\n const extraTop = legendExtraHeight(\n data.series.map(serie => serie.name),\n context.width\n );\n return panelsHeight(groupByUnit(data.series).length, data.categories.length, extraTop);\n }\n\n /**\n * Defines how a series is drawn (type, stacking etc.).\n * @param serie series to draw\n * @param all all series of the chart, for types that depend on the whole set (e.g. stacking)\n * @return the style of the series in the ECharts format, without name, data and axes (filled by the base)\n */\n protected abstract seriesStyle(serie: ChartSeries, all: ChartSeries[]): CartesianSeries;\n\n /**\n * Values of the series in the `series[i].data` format. By default, the values themselves; subclasses may give\n * their own style to some values (e.g. negative values).\n * @param serie series of the chart\n * @return one value per category\n */\n protected seriesData(serie: ChartSeries): DataPoint[] {\n return serie.values;\n }\n\n /**\n * Creates the complete ECharts series: style of the type, name, values, axes of the panel and tooltip format.\n * @param serie series of the chart\n * @param all all series of the chart\n * @param panelIndex index of the panel (and of the axes) of the unit of the series\n * @return the series in the ECharts format\n */\n private buildSeries(serie: ChartSeries, all: ChartSeries[], panelIndex: number): CartesianSeries {\n return {\n ...this.seriesStyle(serie, all),\n id: serie.id,\n name: serie.name,\n data: this.seriesData(serie),\n xAxisIndex: panelIndex,\n yAxisIndex: panelIndex,\n tooltip: { valueFormatter: tooltipFormatter(serie.unit) }\n } as CartesianSeries;\n }\n}\n"],"mappings":";;;;;;;;;;AAoBA,IAAsB,iBAAtB,MAA0D;CAEtD,iBAA0B;;CAG1B,YAAY,QAAgC;EACxC,OAAO,OAAO,SAAS;CAC3B;CAEA,YAAY,MAAiB,SAAsC;EAC/D,MAAM,SAAS,YAAY,KAAK,MAAM;EACtC,MAAM,SAAS,OAAO,SAAS,OAAO,UAClC,MAAM,OAAO,KAAI,UAAS,KAAK,YAAY,OAAO,KAAK,QAAQ,KAAK,CAAC,CACzE;EACA,MAAM,QAAQ,KAAK,OAAO,KAAI,UAAS,MAAM,IAAI;EACjD,MAAM,WAAW,kBAAkB,OAAO,QAAQ,KAAK;EAEvD,OAAO;GACH,GAAG,iBAAiB,QAAQ,OAAO,OAAO,cAAc,OAAO,CAAC;GAChE,SAAS,EAAE,SAAS,OAAO;GAC3B,GAAG,eAAe,QAAQ,KAAK,YAAY,UAAU,YAAY,OAAO,CAAC;GACzE;EACJ;CACJ;CAEA,OAAO,MAAiB,SAA+B;EACnD,MAAM,WAAW,kBACb,KAAK,OAAO,KAAI,UAAS,MAAM,IAAI,GACnC,QAAQ,KACZ;EACA,OAAO,aAAa,YAAY,KAAK,MAAM,CAAC,CAAC,QAAQ,KAAK,WAAW,QAAQ,QAAQ;CACzF;;;;;;;CAgBA,WAAqB,OAAiC;EAClD,OAAO,MAAM;CACjB;;;;;;;;CASA,YAAoB,OAAoB,KAAoB,YAAqC;EAC7F,OAAO;GACH,GAAG,KAAK,YAAY,OAAO,GAAG;GAC9B,IAAI,MAAM;GACV,MAAM,MAAM;GACZ,MAAM,KAAK,WAAW,KAAK;GAC3B,YAAY;GACZ,YAAY;GACZ,SAAS,EAAE,gBAAgB,iBAAiB,MAAM,IAAI,EAAE;EAC5D;CACJ;AACJ"}
1
+ {"version":3,"file":"CartesianChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/CartesianChart.ts"],"sourcesContent":["import type { Icon } from '@tabler/icons-react';\nimport type { BarSeriesOption, EChartsOption, LineSeriesOption } from 'echarts';\n\nimport { ChartData, ChartSeries } from './ChartSeries';\nimport { ChartContext, ChartType } from './ChartType';\nimport { ChartTypeId } from './ChartTypeId';\nimport { chartLocale, chartMessages } from './ChartTexts';\nimport { buildPanelAxes, groupByUnit, panelsHeight } from './UnitPanels';\nimport { buildChartHeader, legendExtraHeight, tooltipFormatter } from './ChartHeader';\n\n/** Column or line series, the two formats used in the charts with axes (cartesian). */\nexport type CartesianSeries = BarSeriesOption | LineSeriesOption;\n\n/** Value of a category in a series, in the format accepted by `series[i].data` (with or without its own style). */\nexport type DataPoint = number | null | { value: number; itemStyle: { color: string } };\n\n/**\n * Base of the chart types with an X axis of categories (line, columns, stacked columns).\n * It builds the panels per unit, the header and the tooltip, leaving to each type just the style of each series.\n * @author Manoel Campos\n */\nexport abstract class CartesianChart implements ChartType {\n abstract readonly id: ChartTypeId;\n readonly singleCategory = false;\n\n /** @param icon icon of the type (see {@link ChartType#icon}) */\n constructor(readonly icon?: Icon) {}\n\n /** Types with axes work for any set of series, except the ones that restrict it (see the subclasses). */\n isAvailable(series: ChartSeries[]): boolean {\n return series.length > 0;\n }\n\n buildOption(data: ChartData, context: ChartContext): EChartsOption {\n const panels = groupByUnit(data.series);\n const series = panels.flatMap((panel, index) =>\n panel.series.map(serie => this.buildSeries(serie, data.series, index))\n );\n const names = data.series.map(serie => serie.name);\n const extraTop = legendExtraHeight(names, context.width);\n\n return {\n ...buildChartHeader(context.title, names, chartMessages(context)),\n tooltip: { trigger: 'axis' },\n ...buildPanelAxes(panels, data.categories, extraTop, chartLocale(context)),\n series\n };\n }\n\n height(data: ChartData, context: ChartContext): number {\n const extraTop = legendExtraHeight(\n data.series.map(serie => serie.name),\n context.width\n );\n return panelsHeight(groupByUnit(data.series).length, data.categories.length, extraTop);\n }\n\n /**\n * Defines how a series is drawn (type, stacking etc.).\n * @param serie series to draw\n * @param all all series of the chart, for types that depend on the whole set (e.g. stacking)\n * @return the style of the series in the ECharts format, without name, data and axes (filled by the base)\n */\n protected abstract seriesStyle(serie: ChartSeries, all: ChartSeries[]): CartesianSeries;\n\n /**\n * Values of the series in the `series[i].data` format. By default, the values themselves; subclasses may give\n * their own style to some values (e.g. negative values).\n * @param serie series of the chart\n * @return one value per category\n */\n protected seriesData(serie: ChartSeries): DataPoint[] {\n return serie.values;\n }\n\n /**\n * Creates the complete ECharts series: style of the type, name, values, axes of the panel and tooltip format.\n * @param serie series of the chart\n * @param all all series of the chart\n * @param panelIndex index of the panel (and of the axes) of the unit of the series\n * @return the series in the ECharts format\n */\n private buildSeries(serie: ChartSeries, all: ChartSeries[], panelIndex: number): CartesianSeries {\n return {\n ...this.seriesStyle(serie, all),\n id: serie.id,\n name: serie.name,\n data: this.seriesData(serie),\n xAxisIndex: panelIndex,\n yAxisIndex: panelIndex,\n tooltip: { valueFormatter: tooltipFormatter(serie.unit) }\n } as CartesianSeries;\n }\n}\n"],"mappings":";;;;;;;;;;AAqBA,IAAsB,iBAAtB,MAA0D;CAKjC;CAHrB,iBAA0B;;CAG1B,YAAY,MAAsB;EAAb,KAAA,OAAA;CAAc;;CAGnC,YAAY,QAAgC;EACxC,OAAO,OAAO,SAAS;CAC3B;CAEA,YAAY,MAAiB,SAAsC;EAC/D,MAAM,SAAS,YAAY,KAAK,MAAM;EACtC,MAAM,SAAS,OAAO,SAAS,OAAO,UAClC,MAAM,OAAO,KAAI,UAAS,KAAK,YAAY,OAAO,KAAK,QAAQ,KAAK,CAAC,CACzE;EACA,MAAM,QAAQ,KAAK,OAAO,KAAI,UAAS,MAAM,IAAI;EACjD,MAAM,WAAW,kBAAkB,OAAO,QAAQ,KAAK;EAEvD,OAAO;GACH,GAAG,iBAAiB,QAAQ,OAAO,OAAO,cAAc,OAAO,CAAC;GAChE,SAAS,EAAE,SAAS,OAAO;GAC3B,GAAG,eAAe,QAAQ,KAAK,YAAY,UAAU,YAAY,OAAO,CAAC;GACzE;EACJ;CACJ;CAEA,OAAO,MAAiB,SAA+B;EACnD,MAAM,WAAW,kBACb,KAAK,OAAO,KAAI,UAAS,MAAM,IAAI,GACnC,QAAQ,KACZ;EACA,OAAO,aAAa,YAAY,KAAK,MAAM,CAAC,CAAC,QAAQ,KAAK,WAAW,QAAQ,QAAQ;CACzF;;;;;;;CAgBA,WAAqB,OAAiC;EAClD,OAAO,MAAM;CACjB;;;;;;;;CASA,YAAoB,OAAoB,KAAoB,YAAqC;EAC7F,OAAO;GACH,GAAG,KAAK,YAAY,OAAO,GAAG;GAC9B,IAAI,MAAM;GACV,MAAM,MAAM;GACZ,MAAM,KAAK,WAAW,KAAK;GAC3B,YAAY;GACZ,YAAY;GACZ,SAAS,EAAE,gBAAgB,iBAAiB,MAAM,IAAI,EAAE;EAC5D;CACJ;AACJ"}
@@ -1,3 +1,4 @@
1
+ import type { Icon } from '@tabler/icons-react';
1
2
  import type { EChartsOption } from 'echarts';
2
3
  import { KitLocale } from '../../../../i18n/KitLocale';
3
4
  import { ChartMessages } from '../../../../i18n/KitMessages';
@@ -25,6 +26,8 @@ export type ChartContext = {
25
26
  };
26
27
  export interface ChartType {
27
28
  readonly id: ChartTypeId;
29
+ /** Icon that represents the type, such as in a chart type selector; absent if the type has none. */
30
+ readonly icon?: Icon;
28
31
  /** Whether the type shows a single category (so the screen should show a category selector, such as the year). */
29
32
  readonly singleCategory: boolean;
30
33
  /**
@@ -1,3 +1,4 @@
1
+ import { type Icon } from '@tabler/icons-react';
1
2
  import type { EChartsOption } from 'echarts';
2
3
  import { ChartData, ChartSeries } from './ChartSeries';
3
4
  import { ChartContext, ChartType } from './ChartType';
@@ -16,8 +17,11 @@ export declare const DONUT_HEIGHT = 520;
16
17
  * @author Manoel Campos
17
18
  */
18
19
  export declare class DonutChart implements ChartType {
20
+ readonly icon: Icon;
19
21
  readonly id: ChartTypeId;
20
22
  readonly singleCategory = true;
23
+ /** @param icon icon that replaces the default one */
24
+ constructor(icon?: Icon);
21
25
  isAvailable(series: ChartSeries[]): boolean;
22
26
  buildOption(data: ChartData, context: ChartContext): EChartsOption;
23
27
  height(data: ChartData, context: ChartContext): number;
@@ -2,6 +2,7 @@
2
2
  import { groupByStack } from "./ChartSeries.js";
3
3
  import { chartMessages } from "./ChartTexts.js";
4
4
  import { buildChartHeader, legendExtraHeight, tooltipFormatter } from "./ChartHeader.js";
5
+ import { IconChartDonut } from "@tabler/icons-react";
5
6
  // src/component/organism/EChart/chart/DonutChart.ts
6
7
  /**
7
8
  * Height of the donut chart with the legend in one row (px). It does not depend on the number of categories; it only
@@ -21,8 +22,13 @@ var DONUT_CENTER = ["50%", "58%"];
21
22
  * @author Manoel Campos
22
23
  */
23
24
  var DonutChart = class {
25
+ icon;
24
26
  id = "donut";
25
27
  singleCategory = true;
28
+ /** @param icon icon that replaces the default one */
29
+ constructor(icon = IconChartDonut) {
30
+ this.icon = icon;
31
+ }
26
32
  isAvailable(series) {
27
33
  const stacks = [...groupByStack(series).entries()];
28
34
  if (stacks.length !== 1) return false;
@@ -1 +1 @@
1
- {"version":3,"file":"DonutChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/DonutChart.ts"],"sourcesContent":["import type { EChartsOption } from 'echarts';\n\nimport { ChartData, ChartSeries, groupByStack } from './ChartSeries';\nimport { ChartContext, ChartType } from './ChartType';\nimport { ChartTypeId } from './ChartTypeId';\nimport { chartMessages } from './ChartTexts';\nimport { buildChartHeader, legendExtraHeight, tooltipFormatter } from './ChartHeader';\n\n/**\n * Height of the donut chart with the legend in one row (px). It does not depend on the number of categories; it only\n * grows when the legend wraps in more rows.\n */\nexport const DONUT_HEIGHT = 520;\n\n/** Inner and outer radius of the donut, relative to the area of the donut ({@link DONUT_HEIGHT} high). */\nconst DONUT_RADIUS = ['40%', '68%'];\n\n/** Center of the donut: moved down so it is not under the title. */\nconst DONUT_CENTER = ['50%', '58%'];\n\n/**\n * Donut chart: shows how the total of a stack ({@link ChartSeries#stack}) splits among its series in a single\n * category (e.g. \"how the revenue splits by category in 2040\").\n * It is available only when there is exactly one stack, none of its series has a negative value (negative slices make\n * no sense) and all series of the chart are in the stack or are its total ({@link ChartSeries#totalOf}).\n * So choosing the donut never stops showing, without warning, a series the user selected.\n * @author Manoel Campos\n */\nexport class DonutChart implements ChartType {\n readonly id: ChartTypeId = 'donut';\n readonly singleCategory = true;\n\n isAvailable(series: ChartSeries[]): boolean {\n const stacks = [...groupByStack(series).entries()];\n if (stacks.length !== 1) return false;\n\n const [stack, slicesSeries] = stacks[0];\n const belongsToStack = (serie: ChartSeries) => serie.stack === stack || serie.totalOf === stack;\n return series.every(belongsToStack) && slicesSeries.every(hasNoNegativeValues);\n }\n\n buildOption(data: ChartData, context: ChartContext): EChartsOption {\n const messages = chartMessages(context);\n const category = shownCategory(data.categories, context.category);\n const slices = buildSlices(data, context);\n const unit = stackSeries(data)[0]?.unit;\n const total = slices.reduce((sum, slice) => sum + slice.value, 0);\n const header = buildChartHeader(\n `${context.title} - ${category}`,\n slices.map(slice => slice.name),\n messages\n );\n\n return {\n ...header,\n title: { ...header.title, subtext: unit && messages.total(unit.format(total)) },\n // The legend goes to the bottom, so it is not under the subtitle with the total.\n legend: { ...header.legend, top: undefined, bottom: 0 },\n tooltip: { trigger: 'item', valueFormatter: unit && tooltipFormatter(unit) },\n series: [\n {\n type: 'pie',\n // The area of the donut is fixed at the top; the extra legend rows stay below it.\n top: 0,\n height: DONUT_HEIGHT,\n radius: DONUT_RADIUS,\n center: DONUT_CENTER,\n data: slices,\n label: { formatter: '{b}: {d}%' }\n }\n ]\n } as EChartsOption;\n }\n\n height(data: ChartData, context: ChartContext): number {\n return (\n DONUT_HEIGHT +\n legendExtraHeight(\n buildSlices(data, context).map(slice => slice.name),\n context.width\n )\n );\n }\n}\n\n/** Slice of the donut: the value of a series of the stack in the category shown. */\ntype Slice = { name: string; value: number };\n\n/**\n * Returns the series of the only stack of the chart, which become the slices of the donut.\n * @param data series and categories of the chart\n * @return the series of the stack (empty if there is no stack)\n */\nfunction stackSeries(data: ChartData): ChartSeries[] {\n return [...groupByStack(data.series).values()][0] ?? [];\n}\n\n/**\n * Builds the slices of the donut in the category shown, without the series that have no value in it.\n * @param data series and categories of the chart\n * @param context category chosen on the screen\n * @return a slice per series of the stack with a value in the category\n */\nfunction buildSlices(data: ChartData, context: ChartContext): Slice[] {\n const categoryIndex = data.categories.indexOf(shownCategory(data.categories, context.category));\n return stackSeries(data)\n .map(serie => ({ name: serie.name, value: serie.values[categoryIndex] }))\n .filter((slice): slice is Slice => slice.value !== null);\n}\n\n/**\n * Checks whether a series has no negative values, which make no sense as slices.\n * @param serie series of a stack\n * @return true if the series has no negative value (categories without a value are ignored)\n */\nfunction hasNoNegativeValues(serie: ChartSeries): boolean {\n return serie.values.every(value => value === null || value >= 0);\n}\n\n/**\n * Returns the category a single-category chart should show: the chosen one, if it is in the chart; otherwise, the last.\n * @template C type of the categories (e.g. the years, as numbers)\n * @param categories categories of the chart\n * @param chosen category chosen on the screen; absent if none was chosen\n * @return the category to show\n */\nexport function shownCategory<C extends string | number>(categories: C[], chosen?: C): C {\n return chosen !== undefined && categories.includes(chosen) ? chosen : categories[categories.length - 1];\n}\n"],"mappings":";;;;;;;;;AAYA,IAAa,eAAe;;AAG5B,IAAM,eAAe,CAAC,OAAO,KAAK;;AAGlC,IAAM,eAAe,CAAC,OAAO,KAAK;;;;;;;;;AAUlC,IAAa,aAAb,MAA6C;CACzC,KAA2B;CAC3B,iBAA0B;CAE1B,YAAY,QAAgC;EACxC,MAAM,SAAS,CAAC,GAAG,aAAa,MAAM,CAAC,CAAC,QAAQ,CAAC;EACjD,IAAI,OAAO,WAAW,GAAG,OAAO;EAEhC,MAAM,CAAC,OAAO,gBAAgB,OAAO;EACrC,MAAM,kBAAkB,UAAuB,MAAM,UAAU,SAAS,MAAM,YAAY;EAC1F,OAAO,OAAO,MAAM,cAAc,KAAK,aAAa,MAAM,mBAAmB;CACjF;CAEA,YAAY,MAAiB,SAAsC;EAC/D,MAAM,WAAW,cAAc,OAAO;EACtC,MAAM,WAAW,cAAc,KAAK,YAAY,QAAQ,QAAQ;EAChE,MAAM,SAAS,YAAY,MAAM,OAAO;EACxC,MAAM,OAAO,YAAY,IAAI,CAAC,CAAC,EAAE,EAAE;EACnC,MAAM,QAAQ,OAAO,QAAQ,KAAK,UAAU,MAAM,MAAM,OAAO,CAAC;EAChE,MAAM,SAAS,iBACX,GAAG,QAAQ,MAAM,KAAK,YACtB,OAAO,KAAI,UAAS,MAAM,IAAI,GAC9B,QACJ;EAEA,OAAO;GACH,GAAG;GACH,OAAO;IAAE,GAAG,OAAO;IAAO,SAAS,QAAQ,SAAS,MAAM,KAAK,OAAO,KAAK,CAAC;GAAE;GAE9E,QAAQ;IAAE,GAAG,OAAO;IAAQ,KAAK,KAAA;IAAW,QAAQ;GAAE;GACtD,SAAS;IAAE,SAAS;IAAQ,gBAAgB,QAAQ,iBAAiB,IAAI;GAAE;GAC3E,QAAQ,CACJ;IACI,MAAM;IAEN,KAAK;IACL,QAAA;IACA,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,OAAO,EAAE,WAAW,YAAY;GACpC,CACJ;EACJ;CACJ;CAEA,OAAO,MAAiB,SAA+B;EACnD,OAAA,MAEI,kBACI,YAAY,MAAM,OAAO,CAAC,CAAC,KAAI,UAAS,MAAM,IAAI,GAClD,QAAQ,KACZ;CAER;AACJ;;;;;;AAUA,SAAS,YAAY,MAAgC;CACjD,OAAO,CAAC,GAAG,aAAa,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AAC1D;;;;;;;AAQA,SAAS,YAAY,MAAiB,SAAgC;CAClE,MAAM,gBAAgB,KAAK,WAAW,QAAQ,cAAc,KAAK,YAAY,QAAQ,QAAQ,CAAC;CAC9F,OAAO,YAAY,IAAI,CAAC,CACnB,KAAI,WAAU;EAAE,MAAM,MAAM;EAAM,OAAO,MAAM,OAAO;CAAe,EAAE,CAAC,CACxE,QAAQ,UAA0B,MAAM,UAAU,IAAI;AAC/D;;;;;;AAOA,SAAS,oBAAoB,OAA6B;CACtD,OAAO,MAAM,OAAO,OAAM,UAAS,UAAU,QAAQ,SAAS,CAAC;AACnE;;;;;;;;AASA,SAAgB,cAAyC,YAAiB,QAAe;CACrF,OAAO,WAAW,KAAA,KAAa,WAAW,SAAS,MAAM,IAAI,SAAS,WAAW,WAAW,SAAS;AACzG"}
1
+ {"version":3,"file":"DonutChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/DonutChart.ts"],"sourcesContent":["import { IconChartDonut, type Icon } from '@tabler/icons-react';\nimport type { EChartsOption } from 'echarts';\n\nimport { ChartData, ChartSeries, groupByStack } from './ChartSeries';\nimport { ChartContext, ChartType } from './ChartType';\nimport { ChartTypeId } from './ChartTypeId';\nimport { chartMessages } from './ChartTexts';\nimport { buildChartHeader, legendExtraHeight, tooltipFormatter } from './ChartHeader';\n\n/**\n * Height of the donut chart with the legend in one row (px). It does not depend on the number of categories; it only\n * grows when the legend wraps in more rows.\n */\nexport const DONUT_HEIGHT = 520;\n\n/** Inner and outer radius of the donut, relative to the area of the donut ({@link DONUT_HEIGHT} high). */\nconst DONUT_RADIUS = ['40%', '68%'];\n\n/** Center of the donut: moved down so it is not under the title. */\nconst DONUT_CENTER = ['50%', '58%'];\n\n/**\n * Donut chart: shows how the total of a stack ({@link ChartSeries#stack}) splits among its series in a single\n * category (e.g. \"how the revenue splits by category in 2040\").\n * It is available only when there is exactly one stack, none of its series has a negative value (negative slices make\n * no sense) and all series of the chart are in the stack or are its total ({@link ChartSeries#totalOf}).\n * So choosing the donut never stops showing, without warning, a series the user selected.\n * @author Manoel Campos\n */\nexport class DonutChart implements ChartType {\n readonly id: ChartTypeId = 'donut';\n readonly singleCategory = true;\n\n /** @param icon icon that replaces the default one */\n constructor(readonly icon: Icon = IconChartDonut) {}\n\n isAvailable(series: ChartSeries[]): boolean {\n const stacks = [...groupByStack(series).entries()];\n if (stacks.length !== 1) return false;\n\n const [stack, slicesSeries] = stacks[0];\n const belongsToStack = (serie: ChartSeries) => serie.stack === stack || serie.totalOf === stack;\n return series.every(belongsToStack) && slicesSeries.every(hasNoNegativeValues);\n }\n\n buildOption(data: ChartData, context: ChartContext): EChartsOption {\n const messages = chartMessages(context);\n const category = shownCategory(data.categories, context.category);\n const slices = buildSlices(data, context);\n const unit = stackSeries(data)[0]?.unit;\n const total = slices.reduce((sum, slice) => sum + slice.value, 0);\n const header = buildChartHeader(\n `${context.title} - ${category}`,\n slices.map(slice => slice.name),\n messages\n );\n\n return {\n ...header,\n title: { ...header.title, subtext: unit && messages.total(unit.format(total)) },\n // The legend goes to the bottom, so it is not under the subtitle with the total.\n legend: { ...header.legend, top: undefined, bottom: 0 },\n tooltip: { trigger: 'item', valueFormatter: unit && tooltipFormatter(unit) },\n series: [\n {\n type: 'pie',\n // The area of the donut is fixed at the top; the extra legend rows stay below it.\n top: 0,\n height: DONUT_HEIGHT,\n radius: DONUT_RADIUS,\n center: DONUT_CENTER,\n data: slices,\n label: { formatter: '{b}: {d}%' }\n }\n ]\n } as EChartsOption;\n }\n\n height(data: ChartData, context: ChartContext): number {\n return (\n DONUT_HEIGHT +\n legendExtraHeight(\n buildSlices(data, context).map(slice => slice.name),\n context.width\n )\n );\n }\n}\n\n/** Slice of the donut: the value of a series of the stack in the category shown. */\ntype Slice = { name: string; value: number };\n\n/**\n * Returns the series of the only stack of the chart, which become the slices of the donut.\n * @param data series and categories of the chart\n * @return the series of the stack (empty if there is no stack)\n */\nfunction stackSeries(data: ChartData): ChartSeries[] {\n return [...groupByStack(data.series).values()][0] ?? [];\n}\n\n/**\n * Builds the slices of the donut in the category shown, without the series that have no value in it.\n * @param data series and categories of the chart\n * @param context category chosen on the screen\n * @return a slice per series of the stack with a value in the category\n */\nfunction buildSlices(data: ChartData, context: ChartContext): Slice[] {\n const categoryIndex = data.categories.indexOf(shownCategory(data.categories, context.category));\n return stackSeries(data)\n .map(serie => ({ name: serie.name, value: serie.values[categoryIndex] }))\n .filter((slice): slice is Slice => slice.value !== null);\n}\n\n/**\n * Checks whether a series has no negative values, which make no sense as slices.\n * @param serie series of a stack\n * @return true if the series has no negative value (categories without a value are ignored)\n */\nfunction hasNoNegativeValues(serie: ChartSeries): boolean {\n return serie.values.every(value => value === null || value >= 0);\n}\n\n/**\n * Returns the category a single-category chart should show: the chosen one, if it is in the chart; otherwise, the last.\n * @template C type of the categories (e.g. the years, as numbers)\n * @param categories categories of the chart\n * @param chosen category chosen on the screen; absent if none was chosen\n * @return the category to show\n */\nexport function shownCategory<C extends string | number>(categories: C[], chosen?: C): C {\n return chosen !== undefined && categories.includes(chosen) ? chosen : categories[categories.length - 1];\n}\n"],"mappings":";;;;;;;;;;AAaA,IAAa,eAAe;;AAG5B,IAAM,eAAe,CAAC,OAAO,KAAK;;AAGlC,IAAM,eAAe,CAAC,OAAO,KAAK;;;;;;;;;AAUlC,IAAa,aAAb,MAA6C;CAKpB;CAJrB,KAA2B;CAC3B,iBAA0B;;CAG1B,YAAY,OAAsB,gBAAgB;EAA7B,KAAA,OAAA;CAA8B;CAEnD,YAAY,QAAgC;EACxC,MAAM,SAAS,CAAC,GAAG,aAAa,MAAM,CAAC,CAAC,QAAQ,CAAC;EACjD,IAAI,OAAO,WAAW,GAAG,OAAO;EAEhC,MAAM,CAAC,OAAO,gBAAgB,OAAO;EACrC,MAAM,kBAAkB,UAAuB,MAAM,UAAU,SAAS,MAAM,YAAY;EAC1F,OAAO,OAAO,MAAM,cAAc,KAAK,aAAa,MAAM,mBAAmB;CACjF;CAEA,YAAY,MAAiB,SAAsC;EAC/D,MAAM,WAAW,cAAc,OAAO;EACtC,MAAM,WAAW,cAAc,KAAK,YAAY,QAAQ,QAAQ;EAChE,MAAM,SAAS,YAAY,MAAM,OAAO;EACxC,MAAM,OAAO,YAAY,IAAI,CAAC,CAAC,EAAE,EAAE;EACnC,MAAM,QAAQ,OAAO,QAAQ,KAAK,UAAU,MAAM,MAAM,OAAO,CAAC;EAChE,MAAM,SAAS,iBACX,GAAG,QAAQ,MAAM,KAAK,YACtB,OAAO,KAAI,UAAS,MAAM,IAAI,GAC9B,QACJ;EAEA,OAAO;GACH,GAAG;GACH,OAAO;IAAE,GAAG,OAAO;IAAO,SAAS,QAAQ,SAAS,MAAM,KAAK,OAAO,KAAK,CAAC;GAAE;GAE9E,QAAQ;IAAE,GAAG,OAAO;IAAQ,KAAK,KAAA;IAAW,QAAQ;GAAE;GACtD,SAAS;IAAE,SAAS;IAAQ,gBAAgB,QAAQ,iBAAiB,IAAI;GAAE;GAC3E,QAAQ,CACJ;IACI,MAAM;IAEN,KAAK;IACL,QAAA;IACA,QAAQ;IACR,QAAQ;IACR,MAAM;IACN,OAAO,EAAE,WAAW,YAAY;GACpC,CACJ;EACJ;CACJ;CAEA,OAAO,MAAiB,SAA+B;EACnD,OAAA,MAEI,kBACI,YAAY,MAAM,OAAO,CAAC,CAAC,KAAI,UAAS,MAAM,IAAI,GAClD,QAAQ,KACZ;CAER;AACJ;;;;;;AAUA,SAAS,YAAY,MAAgC;CACjD,OAAO,CAAC,GAAG,aAAa,KAAK,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC;AAC1D;;;;;;;AAQA,SAAS,YAAY,MAAiB,SAAgC;CAClE,MAAM,gBAAgB,KAAK,WAAW,QAAQ,cAAc,KAAK,YAAY,QAAQ,QAAQ,CAAC;CAC9F,OAAO,YAAY,IAAI,CAAC,CACnB,KAAI,WAAU;EAAE,MAAM,MAAM;EAAM,OAAO,MAAM,OAAO;CAAe,EAAE,CAAC,CACxE,QAAQ,UAA0B,MAAM,UAAU,IAAI;AAC/D;;;;;;AAOA,SAAS,oBAAoB,OAA6B;CACtD,OAAO,MAAM,OAAO,OAAM,UAAS,UAAU,QAAQ,SAAS,CAAC;AACnE;;;;;;;;AASA,SAAgB,cAAyC,YAAiB,QAAe;CACrF,OAAO,WAAW,KAAA,KAAa,WAAW,SAAS,MAAM,IAAI,SAAS,WAAW,WAAW,SAAS;AACzG"}
@@ -1,3 +1,4 @@
1
+ import { type Icon } from '@tabler/icons-react';
1
2
  import { ChartTypeId } from './ChartTypeId';
2
3
  import { CartesianChart, CartesianSeries } from './CartesianChart';
3
4
  /**
@@ -7,5 +8,7 @@ import { CartesianChart, CartesianSeries } from './CartesianChart';
7
8
  */
8
9
  export declare class LineChart extends CartesianChart {
9
10
  readonly id: ChartTypeId;
11
+ /** @param icon icon that replaces the default one */
12
+ constructor(icon?: Icon);
10
13
  protected seriesStyle(): CartesianSeries;
11
14
  }
@@ -1,5 +1,6 @@
1
1
  "use client";
2
2
  import { CartesianChart } from "./CartesianChart.js";
3
+ import { IconChartLine } from "@tabler/icons-react";
3
4
  // src/component/organism/EChart/chart/LineChart.ts
4
5
  /**
5
6
  * Line chart: shows the trend of each series along the categories.
@@ -8,6 +9,10 @@ import { CartesianChart } from "./CartesianChart.js";
8
9
  */
9
10
  var LineChart = class extends CartesianChart {
10
11
  id = "line";
12
+ /** @param icon icon that replaces the default one */
13
+ constructor(icon = IconChartLine) {
14
+ super(icon);
15
+ }
11
16
  seriesStyle() {
12
17
  return {
13
18
  type: "line",
@@ -1 +1 @@
1
- {"version":3,"file":"LineChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/LineChart.ts"],"sourcesContent":["import { ChartTypeId } from './ChartTypeId';\nimport { CartesianChart, CartesianSeries } from './CartesianChart';\n\n/**\n * Line chart: shows the trend of each series along the categories.\n * Suited to rates and levels (e.g. percentages, coefficients, population).\n * @author Manoel Campos\n */\nexport class LineChart extends CartesianChart {\n readonly id: ChartTypeId = 'line';\n\n protected seriesStyle(): CartesianSeries {\n // connectNulls false: a category without a value is a gap in the line, instead of joining the neighbors.\n return { type: 'line', connectNulls: false };\n }\n}\n"],"mappings":";;;;;;;;AAQA,IAAa,YAAb,cAA+B,eAAe;CAC1C,KAA2B;CAE3B,cAAyC;EAErC,OAAO;GAAE,MAAM;GAAQ,cAAc;EAAM;CAC/C;AACJ"}
1
+ {"version":3,"file":"LineChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/LineChart.ts"],"sourcesContent":["import { IconChartLine, type Icon } from '@tabler/icons-react';\n\nimport { ChartTypeId } from './ChartTypeId';\nimport { CartesianChart, CartesianSeries } from './CartesianChart';\n\n/**\n * Line chart: shows the trend of each series along the categories.\n * Suited to rates and levels (e.g. percentages, coefficients, population).\n * @author Manoel Campos\n */\nexport class LineChart extends CartesianChart {\n readonly id: ChartTypeId = 'line';\n\n /** @param icon icon that replaces the default one */\n constructor(icon: Icon = IconChartLine) {\n super(icon);\n }\n\n protected seriesStyle(): CartesianSeries {\n // connectNulls false: a category without a value is a gap in the line, instead of joining the neighbors.\n return { type: 'line', connectNulls: false };\n }\n}\n"],"mappings":";;;;;;;;;AAUA,IAAa,YAAb,cAA+B,eAAe;CAC1C,KAA2B;;CAG3B,YAAY,OAAa,eAAe;EACpC,MAAM,IAAI;CACd;CAEA,cAAyC;EAErC,OAAO;GAAE,MAAM;GAAQ,cAAc;EAAM;CAC/C;AACJ"}
@@ -1,3 +1,4 @@
1
+ import { type Icon } from '@tabler/icons-react';
1
2
  import { ChartSeries } from './ChartSeries';
2
3
  import { ChartTypeId } from './ChartTypeId';
3
4
  import { CartesianChart, CartesianSeries } from './CartesianChart';
@@ -10,6 +11,8 @@ import { CartesianChart, CartesianSeries } from './CartesianChart';
10
11
  */
11
12
  export declare class StackedBarChart extends CartesianChart {
12
13
  readonly id: ChartTypeId;
14
+ /** @param icon icon that replaces the default one */
15
+ constructor(icon?: Icon);
13
16
  isAvailable(series: ChartSeries[]): boolean;
14
17
  protected seriesStyle(serie: ChartSeries, all: ChartSeries[]): CartesianSeries;
15
18
  }
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { groupByStack } from "./ChartSeries.js";
3
3
  import { CartesianChart } from "./CartesianChart.js";
4
+ import { IconChartColumn } from "@tabler/icons-react";
4
5
  // src/component/organism/EChart/chart/StackedBarChart.ts
5
6
  /**
6
7
  * Stacked column chart with lines: the series of the same stack ({@link ChartSeries#stack}) are stacked, showing how
@@ -11,6 +12,10 @@ import { CartesianChart } from "./CartesianChart.js";
11
12
  */
12
13
  var StackedBarChart = class extends CartesianChart {
13
14
  id = "stacked-bar";
15
+ /** @param icon icon that replaces the default one */
16
+ constructor(icon = IconChartColumn) {
17
+ super(icon);
18
+ }
14
19
  isAvailable(series) {
15
20
  return groupByStack(series).size > 0;
16
21
  }
@@ -1 +1 @@
1
- {"version":3,"file":"StackedBarChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/StackedBarChart.ts"],"sourcesContent":["import { ChartSeries, groupByStack } from './ChartSeries';\nimport { ChartTypeId } from './ChartTypeId';\nimport { CartesianChart, CartesianSeries } from './CartesianChart';\n\n/**\n * Stacked column chart with lines: the series of the same stack ({@link ChartSeries#stack}) are stacked, showing how\n * much each one contributes to each category, and the other series (such as a total) become lines over the columns.\n * It is available only when there is a stack with enough series (see `groupByStack`). Whoever builds the series\n * decides which ones can be stacked, so series whose sum makes no sense are never stacked.\n * @author Manoel Campos\n */\nexport class StackedBarChart extends CartesianChart {\n readonly id: ChartTypeId = 'stacked-bar';\n\n isAvailable(series: ChartSeries[]): boolean {\n return groupByStack(series).size > 0;\n }\n\n protected seriesStyle(serie: ChartSeries, all: ChartSeries[]): CartesianSeries {\n // A series with a stack, but alone in it, has nothing to be stacked with: it becomes a line.\n if (!serie.stack || !groupByStack(all).has(serie.stack)) return { type: 'line', connectNulls: false };\n\n // Each stack is stacked separately, so series of different wholes are not added up.\n return { type: 'bar', stack: serie.stack };\n }\n}\n"],"mappings":";;;;;;;;;;;AAWA,IAAa,kBAAb,cAAqC,eAAe;CAChD,KAA2B;CAE3B,YAAY,QAAgC;EACxC,OAAO,aAAa,MAAM,CAAC,CAAC,OAAO;CACvC;CAEA,YAAsB,OAAoB,KAAqC;EAE3E,IAAI,CAAC,MAAM,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC,IAAI,MAAM,KAAK,GAAG,OAAO;GAAE,MAAM;GAAQ,cAAc;EAAM;EAGpG,OAAO;GAAE,MAAM;GAAO,OAAO,MAAM;EAAM;CAC7C;AACJ"}
1
+ {"version":3,"file":"StackedBarChart.js","names":[],"sources":["../../../../../src/component/organism/EChart/chart/StackedBarChart.ts"],"sourcesContent":["import { IconChartColumn, type Icon } from '@tabler/icons-react';\n\nimport { ChartSeries, groupByStack } from './ChartSeries';\nimport { ChartTypeId } from './ChartTypeId';\nimport { CartesianChart, CartesianSeries } from './CartesianChart';\n\n/**\n * Stacked column chart with lines: the series of the same stack ({@link ChartSeries#stack}) are stacked, showing how\n * much each one contributes to each category, and the other series (such as a total) become lines over the columns.\n * It is available only when there is a stack with enough series (see `groupByStack`). Whoever builds the series\n * decides which ones can be stacked, so series whose sum makes no sense are never stacked.\n * @author Manoel Campos\n */\nexport class StackedBarChart extends CartesianChart {\n readonly id: ChartTypeId = 'stacked-bar';\n\n /** @param icon icon that replaces the default one */\n constructor(icon: Icon = IconChartColumn) {\n super(icon);\n }\n\n isAvailable(series: ChartSeries[]): boolean {\n return groupByStack(series).size > 0;\n }\n\n protected seriesStyle(serie: ChartSeries, all: ChartSeries[]): CartesianSeries {\n // A series with a stack, but alone in it, has nothing to be stacked with: it becomes a line.\n if (!serie.stack || !groupByStack(all).has(serie.stack)) return { type: 'line', connectNulls: false };\n\n // Each stack is stacked separately, so series of different wholes are not added up.\n return { type: 'bar', stack: serie.stack };\n }\n}\n"],"mappings":";;;;;;;;;;;;AAaA,IAAa,kBAAb,cAAqC,eAAe;CAChD,KAA2B;;CAG3B,YAAY,OAAa,iBAAiB;EACtC,MAAM,IAAI;CACd;CAEA,YAAY,QAAgC;EACxC,OAAO,aAAa,MAAM,CAAC,CAAC,OAAO;CACvC;CAEA,YAAsB,OAAoB,KAAqC;EAE3E,IAAI,CAAC,MAAM,SAAS,CAAC,aAAa,GAAG,CAAC,CAAC,IAAI,MAAM,KAAK,GAAG,OAAO;GAAE,MAAM;GAAQ,cAAc;EAAM;EAGpG,OAAO;GAAE,MAAM;GAAO,OAAO,MAAM;EAAM;CAC7C;AACJ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ifto/mantine-kit",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "General purpose Mantine components for React apps: CRUD tables and forms, layout, ECharts charts, Excel/CSV export, print pages and a REST HTTP client, with i18n (en-US and pt-BR).",
5
5
  "license": "MIT",
6
6
  "author": "IFTO - Campus Palmas",