@flux-ui/statistics 3.0.0-next.67 → 3.0.0-next.69

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.
Files changed (165) hide show
  1. package/README.md +1 -1
  2. package/dist/component/FluxStatisticsAreaChart.vue.d.ts +11 -4
  3. package/dist/component/FluxStatisticsBarChart.vue.d.ts +11 -4
  4. package/dist/component/FluxStatisticsBase.vue.d.ts +1 -0
  5. package/dist/component/FluxStatisticsBoxPlotChart.vue.d.ts +15 -0
  6. package/dist/component/FluxStatisticsBubbleChart.vue.d.ts +14 -0
  7. package/dist/component/FluxStatisticsCandlestickChart.vue.d.ts +15 -0
  8. package/dist/component/FluxStatisticsChart.vue.d.ts +7 -5
  9. package/dist/component/FluxStatisticsChartPane.vue.d.ts +1 -0
  10. package/dist/component/FluxStatisticsComparison.vue.d.ts +16 -0
  11. package/dist/component/FluxStatisticsDonutChart.vue.d.ts +8 -4
  12. package/dist/component/FluxStatisticsEmpty.vue.d.ts +19 -0
  13. package/dist/component/FluxStatisticsHeatmapChart.vue.d.ts +15 -0
  14. package/dist/component/FluxStatisticsLegendItem.vue.d.ts +1 -0
  15. package/dist/component/FluxStatisticsLegendScope.vue.d.ts +13 -0
  16. package/dist/component/FluxStatisticsLineChart.vue.d.ts +11 -4
  17. package/dist/component/FluxStatisticsMixedChart.vue.d.ts +17 -0
  18. package/dist/component/FluxStatisticsPercentageBar.vue.d.ts +8 -0
  19. package/dist/component/FluxStatisticsPieChart.vue.d.ts +8 -4
  20. package/dist/component/FluxStatisticsPolarAreaChart.vue.d.ts +14 -0
  21. package/dist/component/FluxStatisticsRadarChart.vue.d.ts +12 -0
  22. package/dist/component/FluxStatisticsRadialBar.vue.d.ts +11 -0
  23. package/dist/component/FluxStatisticsScatterChart.vue.d.ts +14 -0
  24. package/dist/component/FluxStatisticsSparkline.vue.d.ts +13 -0
  25. package/dist/component/FluxStatisticsTreemapChart.vue.d.ts +11 -0
  26. package/dist/component/index.d.ts +15 -0
  27. package/dist/composable/index.d.ts +12 -0
  28. package/dist/composable/useChartBaseSetup.d.ts +8 -0
  29. package/dist/composable/useChartHoverSync.d.ts +9 -0
  30. package/dist/composable/useChartLegend.d.ts +14 -0
  31. package/dist/composable/useChartSeriesSetup.d.ts +23 -0
  32. package/dist/composable/useChartSlicesSetup.d.ts +14 -0
  33. package/dist/composable/useECharts.d.ts +9 -0
  34. package/dist/echarts.d.ts +1 -0
  35. package/dist/index.css +262 -34
  36. package/dist/index.d.ts +5 -2
  37. package/dist/index.js +9176 -6895
  38. package/dist/index.js.map +1 -1
  39. package/dist/util/colors.d.ts +4 -0
  40. package/dist/util/icons.d.ts +2 -0
  41. package/dist/util/index.d.ts +6 -0
  42. package/dist/util/options/buildBaseOptions.d.ts +2 -0
  43. package/dist/util/options/buildCartesianBaseOptions.d.ts +13 -0
  44. package/dist/util/options/buildCircularBaseOptions.d.ts +2 -0
  45. package/dist/util/options/cartesian/buildAreaChartOptions.d.ts +17 -0
  46. package/dist/util/options/cartesian/buildBarChartOptions.d.ts +17 -0
  47. package/dist/util/options/cartesian/buildBoxPlotChartOptions.d.ts +16 -0
  48. package/dist/util/options/cartesian/buildBubbleChartOptions.d.ts +15 -0
  49. package/dist/util/options/cartesian/buildCandlestickChartOptions.d.ts +17 -0
  50. package/dist/util/options/cartesian/buildHeatmapChartOptions.d.ts +15 -0
  51. package/dist/util/options/cartesian/buildLineChartOptions.d.ts +17 -0
  52. package/dist/util/options/cartesian/buildMixedChartOptions.d.ts +17 -0
  53. package/dist/util/options/cartesian/buildScatterChartOptions.d.ts +15 -0
  54. package/dist/util/options/cartesian/index.d.ts +18 -0
  55. package/dist/util/options/circular/buildDonutChartOptions.d.ts +15 -0
  56. package/dist/util/options/circular/buildGaugeChartOptions.d.ts +14 -0
  57. package/dist/util/options/circular/buildPieChartOptions.d.ts +15 -0
  58. package/dist/util/options/circular/buildPolarAreaChartOptions.d.ts +15 -0
  59. package/dist/util/options/circular/buildRadarChartOptions.d.ts +13 -0
  60. package/dist/util/options/circular/buildTreemapChartOptions.d.ts +12 -0
  61. package/dist/util/options/circular/index.d.ts +12 -0
  62. package/dist/util/options/index.d.ts +6 -0
  63. package/dist/util/series/chartColors.d.ts +3 -0
  64. package/dist/util/series/converters.d.ts +17 -0
  65. package/dist/util/series/defaults.d.ts +15 -0
  66. package/dist/util/series/index.d.ts +4 -0
  67. package/dist/util/series/labels.d.ts +5 -0
  68. package/dist/util/sparkline.d.ts +7 -0
  69. package/dist/util/tooltips/buildBoxPlotTooltip.d.ts +22 -0
  70. package/dist/util/tooltips/buildCartesianTooltip.d.ts +10 -0
  71. package/dist/util/tooltips/buildGaugeTooltip.d.ts +14 -0
  72. package/dist/util/tooltips/buildHeatmapTooltip.d.ts +17 -0
  73. package/dist/util/tooltips/buildRadarTooltip.d.ts +11 -0
  74. package/dist/util/tooltips/buildSharedItemTooltip.d.ts +10 -0
  75. package/dist/util/tooltips/buildTreemapTooltip.d.ts +12 -0
  76. package/dist/util/tooltips/index.d.ts +15 -0
  77. package/dist/util/tooltips/render.d.ts +4 -0
  78. package/dist/util/tooltips/types.d.ts +24 -0
  79. package/package.json +14 -15
  80. package/src/component/FluxStatisticsAreaChart.vue +36 -43
  81. package/src/component/FluxStatisticsBarChart.vue +36 -35
  82. package/src/component/FluxStatisticsBase.vue +14 -1
  83. package/src/component/FluxStatisticsBoxPlotChart.vue +49 -0
  84. package/src/component/FluxStatisticsBubbleChart.vue +46 -0
  85. package/src/component/FluxStatisticsCandlestickChart.vue +50 -0
  86. package/src/component/FluxStatisticsChart.vue +19 -169
  87. package/src/component/FluxStatisticsChartPane.vue +22 -11
  88. package/src/component/FluxStatisticsComparison.vue +113 -0
  89. package/src/component/FluxStatisticsDonutChart.vue +31 -19
  90. package/src/component/FluxStatisticsEmpty.vue +44 -0
  91. package/src/component/FluxStatisticsHeatmapChart.vue +47 -0
  92. package/src/component/FluxStatisticsLegend.vue +33 -1
  93. package/src/component/FluxStatisticsLegendItem.vue +3 -1
  94. package/src/component/FluxStatisticsLegendScope.vue +16 -0
  95. package/src/component/FluxStatisticsLineChart.vue +36 -43
  96. package/src/component/FluxStatisticsMixedChart.vue +52 -0
  97. package/src/component/FluxStatisticsPercentageBar.vue +90 -0
  98. package/src/component/FluxStatisticsPieChart.vue +31 -19
  99. package/src/component/FluxStatisticsPolarAreaChart.vue +44 -0
  100. package/src/component/FluxStatisticsRadarChart.vue +40 -0
  101. package/src/component/FluxStatisticsRadialBar.vue +39 -0
  102. package/src/component/FluxStatisticsScatterChart.vue +46 -0
  103. package/src/component/FluxStatisticsSparkline.vue +67 -0
  104. package/src/component/FluxStatisticsTreemapChart.vue +35 -0
  105. package/src/component/index.ts +15 -0
  106. package/src/composable/index.ts +12 -0
  107. package/src/composable/useChartBaseSetup.ts +16 -0
  108. package/src/composable/useChartHoverSync.ts +92 -0
  109. package/src/composable/useChartLegend.ts +23 -0
  110. package/src/composable/useChartSeriesSetup.ts +75 -0
  111. package/src/composable/useChartSlicesSetup.ts +58 -0
  112. package/src/composable/useECharts.ts +55 -0
  113. package/src/css/Base.module.scss +28 -1
  114. package/src/css/Chart.module.scss +59 -30
  115. package/src/css/ChartPane.module.scss +20 -12
  116. package/src/css/Comparison.module.scss +52 -0
  117. package/src/css/Empty.module.scss +39 -0
  118. package/src/css/Grid.module.scss +1 -0
  119. package/src/css/Legend.module.scss +22 -4
  120. package/src/css/Meter.module.scss +1 -0
  121. package/src/css/Metric.module.scss +6 -0
  122. package/src/css/PercentageBar.module.scss +36 -0
  123. package/src/css/Sparkline.module.scss +13 -0
  124. package/src/echarts.ts +47 -0
  125. package/src/index.ts +7 -3
  126. package/src/util/colors.ts +86 -0
  127. package/src/util/icons.ts +20 -0
  128. package/src/util/index.ts +6 -0
  129. package/src/util/options/buildBaseOptions.ts +31 -0
  130. package/src/util/options/buildCartesianBaseOptions.ts +67 -0
  131. package/src/util/options/buildCircularBaseOptions.ts +10 -0
  132. package/src/util/options/cartesian/buildAreaChartOptions.ts +44 -0
  133. package/src/util/options/cartesian/buildBarChartOptions.ts +44 -0
  134. package/src/util/options/cartesian/buildBoxPlotChartOptions.ts +63 -0
  135. package/src/util/options/cartesian/buildBubbleChartOptions.ts +48 -0
  136. package/src/util/options/cartesian/buildCandlestickChartOptions.ts +77 -0
  137. package/src/util/options/cartesian/buildHeatmapChartOptions.ts +72 -0
  138. package/src/util/options/cartesian/buildLineChartOptions.ts +44 -0
  139. package/src/util/options/cartesian/buildMixedChartOptions.ts +44 -0
  140. package/src/util/options/cartesian/buildScatterChartOptions.ts +48 -0
  141. package/src/util/options/cartesian/index.ts +18 -0
  142. package/src/util/options/circular/buildDonutChartOptions.ts +31 -0
  143. package/src/util/options/circular/buildGaugeChartOptions.ts +45 -0
  144. package/src/util/options/circular/buildPieChartOptions.ts +31 -0
  145. package/src/util/options/circular/buildPolarAreaChartOptions.ts +31 -0
  146. package/src/util/options/circular/buildRadarChartOptions.ts +52 -0
  147. package/src/util/options/circular/buildTreemapChartOptions.ts +28 -0
  148. package/src/util/options/circular/index.ts +12 -0
  149. package/src/util/options/index.ts +6 -0
  150. package/src/util/series/chartColors.ts +20 -0
  151. package/src/util/series/converters.ts +318 -0
  152. package/src/util/series/defaults.ts +210 -0
  153. package/src/util/series/index.ts +4 -0
  154. package/src/util/series/labels.ts +30 -0
  155. package/src/util/sparkline.ts +67 -0
  156. package/src/util/tooltips/buildBoxPlotTooltip.ts +66 -0
  157. package/src/util/tooltips/buildCartesianTooltip.ts +44 -0
  158. package/src/util/tooltips/buildGaugeTooltip.ts +49 -0
  159. package/src/util/tooltips/buildHeatmapTooltip.ts +57 -0
  160. package/src/util/tooltips/buildRadarTooltip.ts +53 -0
  161. package/src/util/tooltips/buildSharedItemTooltip.ts +38 -0
  162. package/src/util/tooltips/buildTreemapTooltip.ts +49 -0
  163. package/src/util/tooltips/index.ts +15 -0
  164. package/src/util/tooltips/render.ts +66 -0
  165. package/src/util/tooltips/types.ts +29 -0
@@ -0,0 +1,44 @@
1
+ <template>
2
+ <Chart
3
+ ref="chartRef"
4
+ :options="mergedOptions"/>
5
+ </template>
6
+
7
+ <script
8
+ lang="ts"
9
+ setup>
10
+ import type { FluxStatisticsChartPieSlice } from '@flux-ui/types';
11
+ import { computed } from 'vue';
12
+ import { useChartSlicesSetup, type EChartsOption } from '~flux/statistics/composable';
13
+ import { buildPolarAreaChartOptions, type ChartTooltipValueFormatter } from '~flux/statistics/util';
14
+ import Chart from './FluxStatisticsChart.vue';
15
+ import $style from '~flux/statistics/css/Chart.module.scss';
16
+
17
+ const {
18
+ advancedOptions,
19
+ slices,
20
+ title,
21
+ tooltip = false,
22
+ tooltipValueFormatter
23
+ } = defineProps<{
24
+ readonly advancedOptions?: EChartsOption;
25
+ readonly slices: readonly FluxStatisticsChartPieSlice[];
26
+ readonly title?: string;
27
+ readonly tooltip?: boolean;
28
+ readonly tooltipValueFormatter?: ChartTooltipValueFormatter;
29
+ }>();
30
+
31
+ const { t, palette, tooltipItems } = useChartSlicesSetup(() => slices);
32
+
33
+ const mergedOptions = computed(() => buildPolarAreaChartOptions({
34
+ slices,
35
+ palette: palette.value,
36
+ tooltipItems: tooltipItems.value,
37
+ title,
38
+ t,
39
+ styles: $style,
40
+ tooltip,
41
+ tooltipValueFormatter,
42
+ advancedOptions
43
+ }));
44
+ </script>
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <Chart
3
+ ref="chartRef"
4
+ :options="mergedOptions"/>
5
+ </template>
6
+
7
+ <script
8
+ lang="ts"
9
+ setup>
10
+ import type { FluxStatisticsChartRadarIndicator, FluxStatisticsChartRadarSeries } from '@flux-ui/types';
11
+ import { computed } from 'vue';
12
+ import { useChartSeriesSetup, type EChartsOption } from '~flux/statistics/composable';
13
+ import { buildRadarChartOptions } from '~flux/statistics/util';
14
+ import Chart from './FluxStatisticsChart.vue';
15
+ import $style from '~flux/statistics/css/Chart.module.scss';
16
+
17
+ const {
18
+ advancedOptions,
19
+ indicators,
20
+ series,
21
+ tooltip = false
22
+ } = defineProps<{
23
+ readonly advancedOptions?: EChartsOption;
24
+ readonly indicators: readonly FluxStatisticsChartRadarIndicator[];
25
+ readonly series: readonly FluxStatisticsChartRadarSeries[];
26
+ readonly tooltip?: boolean;
27
+ }>();
28
+
29
+ const { t, palette } = useChartSeriesSetup(() => series, { mode: 'data' });
30
+
31
+ const mergedOptions = computed(() => buildRadarChartOptions({
32
+ series,
33
+ indicators,
34
+ palette: palette.value,
35
+ t,
36
+ styles: $style,
37
+ tooltip,
38
+ advancedOptions
39
+ }));
40
+ </script>
@@ -0,0 +1,39 @@
1
+ <template>
2
+ <Chart
3
+ ref="chartRef"
4
+ :options="mergedOptions"/>
5
+ </template>
6
+
7
+ <script
8
+ lang="ts"
9
+ setup>
10
+ import type { FluxStatisticsChartGaugeSeries } from '@flux-ui/types';
11
+ import { computed } from 'vue';
12
+ import { useChartSeriesSetup, type EChartsOption } from '~flux/statistics/composable';
13
+ import { buildGaugeChartOptions, gaugeLegendItemBuilder } from '~flux/statistics/util';
14
+ import Chart from './FluxStatisticsChart.vue';
15
+ import $style from '~flux/statistics/css/Chart.module.scss';
16
+
17
+ const {
18
+ advancedOptions,
19
+ series,
20
+ tooltip = false
21
+ } = defineProps<{
22
+ readonly advancedOptions?: EChartsOption;
23
+ readonly series: readonly FluxStatisticsChartGaugeSeries[];
24
+ readonly tooltip?: boolean;
25
+ }>();
26
+
27
+ const { t, palette } = useChartSeriesSetup(() => series, {
28
+ getLegendItem: gaugeLegendItemBuilder
29
+ });
30
+
31
+ const mergedOptions = computed(() => buildGaugeChartOptions({
32
+ series,
33
+ palette: palette.value,
34
+ t,
35
+ styles: $style,
36
+ tooltip,
37
+ advancedOptions
38
+ }));
39
+ </script>
@@ -0,0 +1,46 @@
1
+ <template>
2
+ <Chart
3
+ ref="chartRef"
4
+ :options="mergedOptions"/>
5
+ </template>
6
+
7
+ <script
8
+ lang="ts"
9
+ setup>
10
+ import type { FluxStatisticsChartScatterSeries } from '@flux-ui/types';
11
+ import { computed } from 'vue';
12
+ import { useChartSeriesSetup, type EChartsOption } from '~flux/statistics/composable';
13
+ import { buildScatterChartOptions } from '~flux/statistics/util';
14
+ import Chart from './FluxStatisticsChart.vue';
15
+ import $style from '~flux/statistics/css/Chart.module.scss';
16
+
17
+ const {
18
+ advancedOptions,
19
+ series,
20
+ splitLines = false,
21
+ tooltip = false,
22
+ xAxisLabels = false,
23
+ yAxisLabels = false
24
+ } = defineProps<{
25
+ readonly advancedOptions?: EChartsOption;
26
+ readonly series: readonly FluxStatisticsChartScatterSeries[];
27
+ readonly splitLines?: boolean;
28
+ readonly tooltip?: boolean;
29
+ readonly xAxisLabels?: boolean;
30
+ readonly yAxisLabels?: boolean;
31
+ }>();
32
+
33
+ const { t, palette } = useChartSeriesSetup(() => series);
34
+
35
+ const mergedOptions = computed(() => buildScatterChartOptions({
36
+ series,
37
+ palette: palette.value,
38
+ t,
39
+ styles: $style,
40
+ tooltip,
41
+ xAxisLabels,
42
+ yAxisLabels,
43
+ splitLines,
44
+ advancedOptions
45
+ }));
46
+ </script>
@@ -0,0 +1,67 @@
1
+ <template>
2
+ <div
3
+ data-sparkline
4
+ :class="$style.statisticsSparkline"
5
+ :style="{
6
+ '--color': resolvedColor
7
+ }">
8
+ <div
9
+ ref="chart"
10
+ :class="$style.statisticsSparklineChart"/>
11
+ </div>
12
+ </template>
13
+
14
+ <script
15
+ lang="ts"
16
+ setup>
17
+ import type { FluxColor } from '@flux-ui/types';
18
+ import { merge } from 'lodash-es';
19
+ import { computed, useTemplateRef } from 'vue';
20
+ import { type EChartsOption, useECharts } from '~flux/statistics/composable';
21
+ import { buildSparklineOptions, deepResolveCssVars, type SparklineSeriesItem, useCssVarVersion } from '~flux/statistics/util';
22
+ import $style from '~flux/statistics/css/Sparkline.module.scss';
23
+
24
+ const FLUX_COLORS: FluxColor[] = ['gray', 'primary', 'danger', 'info', 'success', 'warning'];
25
+
26
+ const {
27
+ color,
28
+ options = {},
29
+ series,
30
+ variant = 'line'
31
+ } = defineProps<{
32
+ readonly color?: FluxColor | `#${string}`;
33
+ readonly options?: EChartsOption;
34
+ readonly series: readonly SparklineSeriesItem[];
35
+ readonly variant?: 'line' | 'bar' | 'area';
36
+ }>();
37
+
38
+ const chart = useTemplateRef('chart');
39
+
40
+ const resolvedColor = computed(() => {
41
+ if (!color) {
42
+ return undefined;
43
+ }
44
+
45
+ if (FLUX_COLORS.includes(color as FluxColor)) {
46
+ return `var(--${color}-600)`;
47
+ }
48
+
49
+ return color;
50
+ });
51
+
52
+ const themeVersion = useCssVarVersion();
53
+
54
+ const mergedOptions = computed<EChartsOption>(() => {
55
+ themeVersion.value;
56
+
57
+ const merged = merge(
58
+ {},
59
+ buildSparklineOptions(variant, resolvedColor.value ?? 'var(--chart-1)', series),
60
+ options
61
+ );
62
+
63
+ return deepResolveCssVars(merged);
64
+ });
65
+
66
+ useECharts(chart, mergedOptions);
67
+ </script>
@@ -0,0 +1,35 @@
1
+ <template>
2
+ <Chart
3
+ :options="mergedOptions"/>
4
+ </template>
5
+
6
+ <script
7
+ lang="ts"
8
+ setup>
9
+ import type { FluxStatisticsChartTreemapNode } from '@flux-ui/types';
10
+ import { computed } from 'vue';
11
+ import { useChartBaseSetup, type EChartsOption } from '~flux/statistics/composable';
12
+ import { buildTreemapChartOptions } from '~flux/statistics/util';
13
+ import Chart from './FluxStatisticsChart.vue';
14
+ import $style from '~flux/statistics/css/Chart.module.scss';
15
+
16
+ const {
17
+ advancedOptions,
18
+ nodes,
19
+ tooltip = false
20
+ } = defineProps<{
21
+ readonly advancedOptions?: EChartsOption;
22
+ readonly nodes: readonly FluxStatisticsChartTreemapNode[];
23
+ readonly tooltip?: boolean;
24
+ }>();
25
+
26
+ const { t } = useChartBaseSetup();
27
+
28
+ const mergedOptions = computed(() => buildTreemapChartOptions({
29
+ nodes,
30
+ t,
31
+ styles: $style,
32
+ tooltip,
33
+ advancedOptions
34
+ }));
35
+ </script>
@@ -1,17 +1,32 @@
1
1
  export { default as FluxStatisticsAreaChart } from './FluxStatisticsAreaChart.vue';
2
2
  export { default as FluxStatisticsBarChart } from './FluxStatisticsBarChart.vue';
3
3
  export { default as FluxStatisticsBase } from './FluxStatisticsBase.vue';
4
+ export { default as FluxStatisticsBoxPlotChart } from './FluxStatisticsBoxPlotChart.vue';
5
+ export { default as FluxStatisticsBubbleChart } from './FluxStatisticsBubbleChart.vue';
6
+ export { default as FluxStatisticsCandlestickChart } from './FluxStatisticsCandlestickChart.vue';
4
7
  export { default as FluxStatisticsChange } from './FluxStatisticsChange.vue';
5
8
  export { default as FluxStatisticsChart } from './FluxStatisticsChart.vue';
6
9
  export { default as FluxStatisticsChartPane } from './FluxStatisticsChartPane.vue';
10
+ export { default as FluxStatisticsComparison } from './FluxStatisticsComparison.vue';
7
11
  export { default as FluxStatisticsDetailsTable } from './FluxStatisticsDetailsTable.vue';
8
12
  export { default as FluxStatisticsDetailsTableRow } from './FluxStatisticsDetailsTableRow.vue';
9
13
  export { default as FluxStatisticsDonutChart } from './FluxStatisticsDonutChart.vue';
14
+ export { default as FluxStatisticsEmpty } from './FluxStatisticsEmpty.vue';
10
15
  export { default as FluxStatisticsGrid } from './FluxStatisticsGrid.vue';
16
+ export { default as FluxStatisticsHeatmapChart } from './FluxStatisticsHeatmapChart.vue';
11
17
  export { default as FluxStatisticsLineChart } from './FluxStatisticsLineChart.vue';
12
18
  export { default as FluxStatisticsKpi } from './FluxStatisticsKpi.vue';
13
19
  export { default as FluxStatisticsLegend } from './FluxStatisticsLegend.vue';
14
20
  export { default as FluxStatisticsLegendItem } from './FluxStatisticsLegendItem.vue';
21
+ export { default as FluxStatisticsLegendScope } from './FluxStatisticsLegendScope.vue';
15
22
  export { default as FluxStatisticsMeter } from './FluxStatisticsMeter.vue';
16
23
  export { default as FluxStatisticsMetric } from './FluxStatisticsMetric.vue';
24
+ export { default as FluxStatisticsMixedChart } from './FluxStatisticsMixedChart.vue';
25
+ export { default as FluxStatisticsPercentageBar } from './FluxStatisticsPercentageBar.vue';
17
26
  export { default as FluxStatisticsPieChart } from './FluxStatisticsPieChart.vue';
27
+ export { default as FluxStatisticsPolarAreaChart } from './FluxStatisticsPolarAreaChart.vue';
28
+ export { default as FluxStatisticsRadarChart } from './FluxStatisticsRadarChart.vue';
29
+ export { default as FluxStatisticsRadialBar } from './FluxStatisticsRadialBar.vue';
30
+ export { default as FluxStatisticsScatterChart } from './FluxStatisticsScatterChart.vue';
31
+ export { default as FluxStatisticsSparkline } from './FluxStatisticsSparkline.vue';
32
+ export { default as FluxStatisticsTreemapChart } from './FluxStatisticsTreemapChart.vue';
@@ -0,0 +1,12 @@
1
+ export type { UseChartBaseSetupReturn } from './useChartBaseSetup';
2
+ export { useChartBaseSetup } from './useChartBaseSetup';
3
+ export type { ChartLegendContext, ChartLegendItem } from './useChartLegend';
4
+ export { createChartLegendContext, FluxStatisticsChartLegendInjectionKey } from './useChartLegend';
5
+ export type { ChartHoverSyncMode, UseChartHoverSyncOptions } from './useChartHoverSync';
6
+ export { useChartHoverSync } from './useChartHoverSync';
7
+ export type { ChartLegendItemBuilder, ChartSeriesShape, UseChartSeriesSetupOptions, UseChartSeriesSetupReturn } from './useChartSeriesSetup';
8
+ export { useChartSeriesSetup } from './useChartSeriesSetup';
9
+ export type { UseChartSlicesSetupReturn } from './useChartSlicesSetup';
10
+ export { useChartSlicesSetup } from './useChartSlicesSetup';
11
+ export type { EChartsInstance, EChartsOption, UseEChartsReturn } from './useECharts';
12
+ export { useECharts } from './useECharts';
@@ -0,0 +1,16 @@
1
+ import { computed, useTemplateRef, type ComputedRef } from 'vue';
2
+ import { useI18n } from 'vue-i18n';
3
+ import type { EChartsInstance } from './useECharts';
4
+
5
+ export interface UseChartBaseSetupReturn {
6
+ readonly t: ReturnType<typeof useI18n>['t'];
7
+ readonly chartInstance: ComputedRef<EChartsInstance | null>;
8
+ }
9
+
10
+ export function useChartBaseSetup(): UseChartBaseSetupReturn {
11
+ const { t } = useI18n({ useScope: 'parent' });
12
+ const chartRef = useTemplateRef<{ chartInstance: EChartsInstance | null } | null>('chartRef');
13
+ const chartInstance = computed<EChartsInstance | null>(() => chartRef.value?.chartInstance ?? null);
14
+
15
+ return { t, chartInstance };
16
+ }
@@ -0,0 +1,92 @@
1
+ import { onBeforeUnmount, watch, type Ref } from 'vue';
2
+ import type { ChartLegendContext } from './useChartLegend';
3
+ import type { EChartsInstance } from './useECharts';
4
+
5
+ export type ChartHoverSyncMode = 'series' | 'data';
6
+
7
+ export interface UseChartHoverSyncOptions {
8
+ readonly mode: ChartHoverSyncMode;
9
+ readonly seriesIndex?: number;
10
+ }
11
+
12
+ export function useChartHoverSync(
13
+ chartInstance: Ref<EChartsInstance | null>,
14
+ legendContext: ChartLegendContext | null,
15
+ options: UseChartHoverSyncOptions
16
+ ): void {
17
+ if (!legendContext) {
18
+ return;
19
+ }
20
+
21
+ const { mode, seriesIndex: forcedSeriesIndex = 0 } = options;
22
+
23
+ let attached: EChartsInstance | null = null;
24
+ let syncing = false;
25
+
26
+ const onMouseOver = (params: { seriesIndex?: number; dataIndex?: number }) => {
27
+ if (syncing) {
28
+ return;
29
+ }
30
+
31
+ const index = mode === 'series'
32
+ ? params.seriesIndex ?? null
33
+ : params.dataIndex ?? null;
34
+
35
+ legendContext.hoveredIndex.value = index;
36
+ };
37
+
38
+ const onMouseOut = () => {
39
+ if (syncing) {
40
+ return;
41
+ }
42
+
43
+ legendContext.hoveredIndex.value = null;
44
+ };
45
+
46
+ const dispatchHighlight = (instance: EChartsInstance, index: number | null) => {
47
+ syncing = true;
48
+
49
+ try {
50
+ instance.dispatchAction({ type: 'downplay' });
51
+
52
+ if (index !== null) {
53
+ if (mode === 'series') {
54
+ instance.dispatchAction({ type: 'highlight', seriesIndex: index });
55
+ } else {
56
+ instance.dispatchAction({ type: 'highlight', seriesIndex: forcedSeriesIndex, dataIndex: index });
57
+ }
58
+ }
59
+ } finally {
60
+ syncing = false;
61
+ }
62
+ };
63
+
64
+ watch(chartInstance, instance => {
65
+ if (attached) {
66
+ attached.off('mouseover', onMouseOver as never);
67
+ attached.off('mouseout', onMouseOut as never);
68
+ attached = null;
69
+ }
70
+
71
+ if (instance) {
72
+ instance.on('mouseover', onMouseOver as never);
73
+ instance.on('mouseout', onMouseOut as never);
74
+ attached = instance;
75
+ dispatchHighlight(instance, legendContext.hoveredIndex.value);
76
+ }
77
+ }, { immediate: true });
78
+
79
+ watch(() => legendContext.hoveredIndex.value, index => {
80
+ if (chartInstance.value) {
81
+ dispatchHighlight(chartInstance.value, index);
82
+ }
83
+ });
84
+
85
+ onBeforeUnmount(() => {
86
+ if (attached) {
87
+ attached.off('mouseover', onMouseOver as never);
88
+ attached.off('mouseout', onMouseOut as never);
89
+ attached = null;
90
+ }
91
+ });
92
+ }
@@ -0,0 +1,23 @@
1
+ import type { FluxIconName } from '@flux-ui/types';
2
+ import { ref, type InjectionKey, type Ref } from 'vue';
3
+
4
+ export interface ChartLegendItem {
5
+ readonly color?: string;
6
+ readonly icon?: FluxIconName;
7
+ readonly label: string;
8
+ readonly value?: string | number;
9
+ }
10
+
11
+ export interface ChartLegendContext {
12
+ readonly items: Ref<readonly ChartLegendItem[]>;
13
+ readonly hoveredIndex: Ref<number | null>;
14
+ }
15
+
16
+ export const FluxStatisticsChartLegendInjectionKey: InjectionKey<ChartLegendContext> = Symbol('flux-statistics-chart-legend');
17
+
18
+ export function createChartLegendContext(): ChartLegendContext {
19
+ return {
20
+ items: ref<readonly ChartLegendItem[]>([]),
21
+ hoveredIndex: ref<number | null>(null)
22
+ };
23
+ }
@@ -0,0 +1,75 @@
1
+ import type { FluxIconName, FluxStatisticsChartColor } from '@flux-ui/types';
2
+ import { computed, inject, useTemplateRef, watchEffect, type ComputedRef } from 'vue';
3
+ import { useI18n } from 'vue-i18n';
4
+ import { CHART_DEFAULT_COLORS, resolveChartColor } from '~flux/statistics/util';
5
+ import { type ChartHoverSyncMode, useChartHoverSync } from './useChartHoverSync';
6
+ import { type ChartLegendContext, type ChartLegendItem, FluxStatisticsChartLegendInjectionKey } from './useChartLegend';
7
+ import type { EChartsInstance } from './useECharts';
8
+
9
+ export interface ChartSeriesShape {
10
+ readonly name?: string;
11
+ readonly icon?: FluxIconName;
12
+ readonly color?: FluxStatisticsChartColor;
13
+ }
14
+
15
+ export type ChartLegendItemBuilder<S> = (
16
+ series: S,
17
+ color: string,
18
+ index: number,
19
+ t: ReturnType<typeof useI18n>['t']
20
+ ) => ChartLegendItem | readonly ChartLegendItem[];
21
+
22
+ export interface UseChartSeriesSetupOptions<S extends ChartSeriesShape> {
23
+ readonly mode?: ChartHoverSyncMode;
24
+ readonly getLegendItem?: ChartLegendItemBuilder<S>;
25
+ }
26
+
27
+ export interface UseChartSeriesSetupReturn {
28
+ readonly t: ReturnType<typeof useI18n>['t'];
29
+ readonly palette: ComputedRef<readonly string[]>;
30
+ readonly legendContext: ChartLegendContext | null;
31
+ readonly chartInstance: ComputedRef<EChartsInstance | null>;
32
+ }
33
+
34
+ const defaultLegendItem = <S extends ChartSeriesShape>(
35
+ s: S,
36
+ color: string,
37
+ _index: number,
38
+ t: ReturnType<typeof useI18n>['t']
39
+ ): ChartLegendItem => ({
40
+ color,
41
+ icon: s.icon,
42
+ label: s.name ? t(String(s.name)) : ''
43
+ });
44
+
45
+ export function useChartSeriesSetup<S extends ChartSeriesShape>(
46
+ seriesGetter: () => readonly S[],
47
+ options: UseChartSeriesSetupOptions<S> = {}
48
+ ): UseChartSeriesSetupReturn {
49
+ const { mode = 'series', getLegendItem = defaultLegendItem } = options;
50
+ const { t } = useI18n({ useScope: 'parent' });
51
+ const legendContext = inject(FluxStatisticsChartLegendInjectionKey, null);
52
+ const chartRef = useTemplateRef<{ chartInstance: EChartsInstance | null } | null>('chartRef');
53
+ const chartInstance = computed<EChartsInstance | null>(() => chartRef.value?.chartInstance ?? null);
54
+
55
+ useChartHoverSync(chartInstance, legendContext, { mode });
56
+
57
+ const palette = computed<readonly string[]>(() =>
58
+ seriesGetter().map((s, i) => resolveChartColor(s.color) ?? CHART_DEFAULT_COLORS[i % CHART_DEFAULT_COLORS.length])
59
+ );
60
+
61
+ const legendItems = computed<readonly ChartLegendItem[]>(() =>
62
+ seriesGetter().flatMap((s, i) => {
63
+ const item = getLegendItem(s, palette.value[i], i, t);
64
+ return Array.isArray(item) ? item : [item as ChartLegendItem];
65
+ })
66
+ );
67
+
68
+ watchEffect(() => {
69
+ if (legendContext) {
70
+ legendContext.items.value = legendItems.value;
71
+ }
72
+ });
73
+
74
+ return { t, palette, legendContext, chartInstance };
75
+ }
@@ -0,0 +1,58 @@
1
+ import type { FluxStatisticsChartPieSlice } from '@flux-ui/types';
2
+ import { computed, inject, useTemplateRef, watchEffect, type ComputedRef } from 'vue';
3
+ import { useI18n } from 'vue-i18n';
4
+ import { CHART_DEFAULT_COLORS, resolveChartColor, type SharedTooltipItem } from '~flux/statistics/util';
5
+ import { useChartHoverSync } from './useChartHoverSync';
6
+ import { type ChartLegendContext, type ChartLegendItem, FluxStatisticsChartLegendInjectionKey } from './useChartLegend';
7
+ import type { EChartsInstance } from './useECharts';
8
+
9
+ export interface UseChartSlicesSetupReturn {
10
+ readonly t: ReturnType<typeof useI18n>['t'];
11
+ readonly palette: ComputedRef<readonly string[]>;
12
+ readonly tooltipItems: ComputedRef<readonly SharedTooltipItem[]>;
13
+ readonly legendContext: ChartLegendContext | null;
14
+ readonly chartInstance: ComputedRef<EChartsInstance | null>;
15
+ }
16
+
17
+ export function useChartSlicesSetup(
18
+ slicesGetter: () => readonly FluxStatisticsChartPieSlice[]
19
+ ): UseChartSlicesSetupReturn {
20
+ const { t } = useI18n({ useScope: 'parent' });
21
+ const legendContext = inject(FluxStatisticsChartLegendInjectionKey, null);
22
+ const chartRef = useTemplateRef<{ chartInstance: EChartsInstance | null } | null>('chartRef');
23
+ const chartInstance = computed<EChartsInstance | null>(() => chartRef.value?.chartInstance ?? null);
24
+
25
+ useChartHoverSync(chartInstance, legendContext, { mode: 'data' });
26
+
27
+ const palette = computed<readonly string[]>(() =>
28
+ slicesGetter().map((slice, i) => resolveChartColor(slice.color) ?? CHART_DEFAULT_COLORS[i % CHART_DEFAULT_COLORS.length])
29
+ );
30
+
31
+ const tooltipItems = computed<readonly SharedTooltipItem[]>(() =>
32
+ slicesGetter().map((slice, i) => ({
33
+ name: slice.label,
34
+ value: slice.formatted ?? slice.value,
35
+ color: palette.value[i],
36
+ icon: slice.icon,
37
+ seriesIndex: 0,
38
+ dataIndex: i
39
+ }))
40
+ );
41
+
42
+ const legendItems = computed<readonly ChartLegendItem[]>(() =>
43
+ slicesGetter().map((slice, i) => ({
44
+ color: palette.value[i],
45
+ icon: slice.icon,
46
+ label: slice.label ? t(String(slice.label)) : '',
47
+ value: slice.formatted ?? slice.value
48
+ }))
49
+ );
50
+
51
+ watchEffect(() => {
52
+ if (legendContext) {
53
+ legendContext.items.value = legendItems.value;
54
+ }
55
+ });
56
+
57
+ return { t, palette, tooltipItems, legendContext, chartInstance };
58
+ }
@@ -0,0 +1,55 @@
1
+ import { useResizeObserver } from '@basmilius/common';
2
+ import { init, type EChartsCoreOption } from 'echarts/core';
3
+ import { markRaw, onBeforeUnmount, onMounted, ref, toValue, type MaybeRefOrGetter, type Ref } from 'vue';
4
+ import '~flux/statistics/echarts';
5
+
6
+ export type EChartsOption = EChartsCoreOption;
7
+ export type EChartsInstance = ReturnType<typeof init>;
8
+
9
+ export interface UseEChartsReturn {
10
+ readonly chartInstance: Ref<EChartsInstance | null>;
11
+ resize(): void;
12
+ }
13
+
14
+ export function useECharts(
15
+ target: Ref<HTMLElement | null>,
16
+ options: MaybeRefOrGetter<EChartsOption>
17
+ ): UseEChartsReturn {
18
+ const chartInstance = ref<EChartsInstance | null>(null);
19
+ let pendingResize: number | null = null;
20
+
21
+ onMounted(() => {
22
+ if (!target.value) {
23
+ return;
24
+ }
25
+
26
+ chartInstance.value = markRaw(init(target.value));
27
+ chartInstance.value.setOption(toValue(options));
28
+ });
29
+
30
+ onBeforeUnmount(() => {
31
+ if (pendingResize !== null) {
32
+ cancelAnimationFrame(pendingResize);
33
+ pendingResize = null;
34
+ }
35
+
36
+ chartInstance.value?.dispose();
37
+ chartInstance.value = null;
38
+ });
39
+
40
+ useResizeObserver(target as any, () => {
41
+ if (pendingResize !== null) {
42
+ return;
43
+ }
44
+
45
+ pendingResize = requestAnimationFrame(() => {
46
+ pendingResize = null;
47
+ chartInstance.value?.resize();
48
+ });
49
+ });
50
+
51
+ return {
52
+ chartInstance: chartInstance as Ref<EChartsInstance | null>,
53
+ resize: () => chartInstance.value?.resize()
54
+ };
55
+ }