@flux-ui/statistics 3.0.0-next.28
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 +16 -0
- package/dist/component/FluxStatisticsAreaChart.vue.d.ts +9 -0
- package/dist/component/FluxStatisticsBarChart.vue.d.ts +9 -0
- package/dist/component/FluxStatisticsBase.vue.d.ts +28 -0
- package/dist/component/FluxStatisticsChange.vue.d.ts +9 -0
- package/dist/component/FluxStatisticsChart.vue.d.ts +22 -0
- package/dist/component/FluxStatisticsChartPane.vue.d.ts +32 -0
- package/dist/component/FluxStatisticsDetailsTable.vue.d.ts +23 -0
- package/dist/component/FluxStatisticsDetailsTableRow.vue.d.ts +7 -0
- package/dist/component/FluxStatisticsDonutChart.vue.d.ts +9 -0
- package/dist/component/FluxStatisticsGrid.vue.d.ts +26 -0
- package/dist/component/FluxStatisticsKpi.vue.d.ts +11 -0
- package/dist/component/FluxStatisticsLegend.vue.d.ts +18 -0
- package/dist/component/FluxStatisticsLegendItem.vue.d.ts +10 -0
- package/dist/component/FluxStatisticsLineChart.vue.d.ts +9 -0
- package/dist/component/FluxStatisticsMeter.vue.d.ts +14 -0
- package/dist/component/FluxStatisticsMetric.vue.d.ts +29 -0
- package/dist/component/FluxStatisticsPieChart.vue.d.ts +9 -0
- package/dist/component/index.d.ts +17 -0
- package/dist/index.css +492 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +10184 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +13 -0
- package/package.json +77 -0
- package/src/component/FluxStatisticsAreaChart.vue +59 -0
- package/src/component/FluxStatisticsBarChart.vue +51 -0
- package/src/component/FluxStatisticsBase.vue +43 -0
- package/src/component/FluxStatisticsChange.vue +37 -0
- package/src/component/FluxStatisticsChart.vue +193 -0
- package/src/component/FluxStatisticsChartPane.vue +47 -0
- package/src/component/FluxStatisticsDetailsTable.vue +25 -0
- package/src/component/FluxStatisticsDetailsTableRow.vue +22 -0
- package/src/component/FluxStatisticsDonutChart.vue +32 -0
- package/src/component/FluxStatisticsGrid.vue +31 -0
- package/src/component/FluxStatisticsKpi.vue +43 -0
- package/src/component/FluxStatisticsLegend.vue +11 -0
- package/src/component/FluxStatisticsLegendItem.vue +59 -0
- package/src/component/FluxStatisticsLineChart.vue +59 -0
- package/src/component/FluxStatisticsMeter.vue +83 -0
- package/src/component/FluxStatisticsMetric.vue +59 -0
- package/src/component/FluxStatisticsPieChart.vue +32 -0
- package/src/component/index.ts +17 -0
- package/src/css/Base.module.scss +46 -0
- package/src/css/Change.module.scss +42 -0
- package/src/css/Chart.module.scss +93 -0
- package/src/css/ChartPane.module.scss +38 -0
- package/src/css/Core.module.scss +3 -0
- package/src/css/DetailsTable.module.scss +43 -0
- package/src/css/Grid.module.scss +26 -0
- package/src/css/Kpi.module.scss +21 -0
- package/src/css/Legend.module.scss +53 -0
- package/src/css/Meter.module.scss +98 -0
- package/src/css/Metric.module.scss +66 -0
- package/src/index.ts +48 -0
- package/src/types.d.ts +13 -0
- package/tsconfig.json +7 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="$style.statisticsLegendItem"
|
|
4
|
+
:style="{
|
|
5
|
+
'--color': colorValue
|
|
6
|
+
}">
|
|
7
|
+
<FluxIcon
|
|
8
|
+
v-if="icon"
|
|
9
|
+
:class="$style.statisticsLegendItemIcon"
|
|
10
|
+
:name="icon"
|
|
11
|
+
:size="16"/>
|
|
12
|
+
|
|
13
|
+
<div
|
|
14
|
+
v-else
|
|
15
|
+
:class="$style.statisticsLegendItemColor"/>
|
|
16
|
+
|
|
17
|
+
<span
|
|
18
|
+
v-if="label"
|
|
19
|
+
:class="$style.statisticsLegendItemLabel">
|
|
20
|
+
{{ label }}
|
|
21
|
+
</span>
|
|
22
|
+
|
|
23
|
+
<span
|
|
24
|
+
v-if="value"
|
|
25
|
+
:class="$style.statisticsLegendItemValue">
|
|
26
|
+
{{ value }}
|
|
27
|
+
</span>
|
|
28
|
+
</div>
|
|
29
|
+
</template>
|
|
30
|
+
|
|
31
|
+
<script
|
|
32
|
+
lang="ts"
|
|
33
|
+
setup>
|
|
34
|
+
import { FluxIcon } from '@flux-ui/components';
|
|
35
|
+
import type { FluxColor, FluxIconName } from '@flux-ui/types';
|
|
36
|
+
import { computed } from 'vue';
|
|
37
|
+
import $style from '$fluxStatistics/css/Legend.module.scss';
|
|
38
|
+
|
|
39
|
+
const {
|
|
40
|
+
color
|
|
41
|
+
} = defineProps<{
|
|
42
|
+
readonly color?: FluxColor | `#${string}`;
|
|
43
|
+
readonly icon?: FluxIconName;
|
|
44
|
+
readonly label: string;
|
|
45
|
+
readonly value?: string | number;
|
|
46
|
+
}>();
|
|
47
|
+
|
|
48
|
+
const colorValue = computed(() => {
|
|
49
|
+
if (!color) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (['gray', 'primary', 'danger', 'info', 'success', 'warning'].includes(color)) {
|
|
54
|
+
return `var(--${color}-600)`;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return color;
|
|
58
|
+
});
|
|
59
|
+
</script>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Chart
|
|
3
|
+
:aspectRatio="aspectRatio"
|
|
4
|
+
:options="merge({
|
|
5
|
+
chart: {
|
|
6
|
+
type: 'line',
|
|
7
|
+
sparkline: {
|
|
8
|
+
enabled: true
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
fill: {
|
|
12
|
+
gradient: {
|
|
13
|
+
enabled: true,
|
|
14
|
+
opacityFrom: 0.5,
|
|
15
|
+
opacityTo: 0
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
grid: {
|
|
19
|
+
show: true,
|
|
20
|
+
clipMarkers: false
|
|
21
|
+
},
|
|
22
|
+
legend: {
|
|
23
|
+
show: false
|
|
24
|
+
},
|
|
25
|
+
stroke: {
|
|
26
|
+
curve: 'smooth',
|
|
27
|
+
width: 2
|
|
28
|
+
}
|
|
29
|
+
}, options)"
|
|
30
|
+
:series="translatedSeries"/>
|
|
31
|
+
</template>
|
|
32
|
+
|
|
33
|
+
<script
|
|
34
|
+
lang="ts"
|
|
35
|
+
setup>
|
|
36
|
+
import type { ApexOptions } from 'apexcharts';
|
|
37
|
+
import { merge } from 'lodash-es';
|
|
38
|
+
import { computed } from 'vue';
|
|
39
|
+
import { useI18n } from 'vue-i18n';
|
|
40
|
+
import Chart from './FluxStatisticsChart.vue';
|
|
41
|
+
|
|
42
|
+
const {
|
|
43
|
+
options = {},
|
|
44
|
+
series
|
|
45
|
+
} = defineProps<{
|
|
46
|
+
readonly aspectRatio?: number;
|
|
47
|
+
readonly options?: ApexOptions;
|
|
48
|
+
readonly series: ApexOptions['series'];
|
|
49
|
+
}>();
|
|
50
|
+
|
|
51
|
+
const {t} = useI18n({useScope: 'parent'});
|
|
52
|
+
|
|
53
|
+
const translatedSeries = computed(() => {
|
|
54
|
+
return (series as any).map((seriesItem: any) => ({
|
|
55
|
+
...seriesItem,
|
|
56
|
+
name: t(seriesItem.name as string)
|
|
57
|
+
}));
|
|
58
|
+
});
|
|
59
|
+
</script>
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div
|
|
3
|
+
:class="isSmall ? $style.statisticsMeterSmall : $style.statisticsMeter"
|
|
4
|
+
:style="{
|
|
5
|
+
'--color': colorValue,
|
|
6
|
+
'--percentage': `${value * 100}%`
|
|
7
|
+
}">
|
|
8
|
+
<div :class="$style.statisticsMeterHeader">
|
|
9
|
+
<FluxIcon
|
|
10
|
+
v-if="icon"
|
|
11
|
+
:class="$style.statisticsMeterHeaderIcon"
|
|
12
|
+
:name="icon"
|
|
13
|
+
:size="16"/>
|
|
14
|
+
|
|
15
|
+
<span
|
|
16
|
+
v-if="title"
|
|
17
|
+
:class="$style.statisticsMeterHeaderTitle">
|
|
18
|
+
{{ title }}
|
|
19
|
+
</span>
|
|
20
|
+
|
|
21
|
+
<span
|
|
22
|
+
v-if="subTitle"
|
|
23
|
+
:class="$style.statisticsMeterHeaderSubTitle">
|
|
24
|
+
{{ subTitle }}
|
|
25
|
+
</span>
|
|
26
|
+
|
|
27
|
+
<span :class="$style.statisticsMeterHeaderValue">
|
|
28
|
+
{{ formatPercentage(value) }}
|
|
29
|
+
</span>
|
|
30
|
+
|
|
31
|
+
<span
|
|
32
|
+
v-if="tip"
|
|
33
|
+
:class="$style.statisticsMeterHeaderTip">
|
|
34
|
+
{{ tip }}
|
|
35
|
+
</span>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
<div :class="$style.statisticsMeterBar">
|
|
39
|
+
<div :class="$style.statisticsMeterBarValue"/>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<div
|
|
43
|
+
v-if="footer"
|
|
44
|
+
:class="$style.statisticsMeterFooter">
|
|
45
|
+
{{ footer }}
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<script
|
|
51
|
+
lang="ts"
|
|
52
|
+
setup>
|
|
53
|
+
import { formatPercentage } from '@basmilius/utils';
|
|
54
|
+
import { FluxIcon } from '@flux-ui/components';
|
|
55
|
+
import type { FluxColor, FluxIconName } from '@flux-ui/types';
|
|
56
|
+
import { computed } from 'vue';
|
|
57
|
+
import $style from '$fluxStatistics/css/Meter.module.scss';
|
|
58
|
+
|
|
59
|
+
const {
|
|
60
|
+
color
|
|
61
|
+
} = defineProps<{
|
|
62
|
+
readonly color?: FluxColor | `#${string}`;
|
|
63
|
+
readonly icon?: FluxIconName;
|
|
64
|
+
readonly isSmall?: boolean;
|
|
65
|
+
readonly footer?: string;
|
|
66
|
+
readonly subTitle?: string;
|
|
67
|
+
readonly tip?: string;
|
|
68
|
+
readonly title?: string;
|
|
69
|
+
readonly value: number;
|
|
70
|
+
}>();
|
|
71
|
+
|
|
72
|
+
const colorValue = computed(() => {
|
|
73
|
+
if (!color) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (['gray', 'primary', 'danger', 'info', 'success', 'warning'].includes(color)) {
|
|
78
|
+
return `var(--${color}-600)`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return color;
|
|
82
|
+
});
|
|
83
|
+
</script>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Base
|
|
3
|
+
:icon="icon"
|
|
4
|
+
:title="title">
|
|
5
|
+
<div :class="$style.statisticsMetricLabel">
|
|
6
|
+
{{ label }}
|
|
7
|
+
</div>
|
|
8
|
+
|
|
9
|
+
<div
|
|
10
|
+
v-if="value"
|
|
11
|
+
:class="$style.statisticsMetricValue">
|
|
12
|
+
{{ value }}
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div
|
|
16
|
+
v-if="slots.default"
|
|
17
|
+
:class="$style.statisticsMetricContent">
|
|
18
|
+
<slot/>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div
|
|
22
|
+
v-if="change || footer"
|
|
23
|
+
:class="$style.statisticsMetricBottom">
|
|
24
|
+
<Change
|
|
25
|
+
v-if="change"
|
|
26
|
+
:color="change.color"
|
|
27
|
+
:icon="change.icon"
|
|
28
|
+
:value="change.value"/>
|
|
29
|
+
|
|
30
|
+
<span
|
|
31
|
+
v-if="footer"
|
|
32
|
+
:class="$style.statisticsMetricFooter">
|
|
33
|
+
{{ footer }}
|
|
34
|
+
</span>
|
|
35
|
+
</div>
|
|
36
|
+
</Base>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<script
|
|
40
|
+
lang="ts"
|
|
41
|
+
setup>
|
|
42
|
+
import type { FluxIconName, FluxStatisticsChange } from '@flux-ui/types';
|
|
43
|
+
import Base from './FluxStatisticsBase.vue';
|
|
44
|
+
import Change from './FluxStatisticsChange.vue';
|
|
45
|
+
import $style from '$fluxStatistics/css/Metric.module.scss';
|
|
46
|
+
|
|
47
|
+
defineProps<{
|
|
48
|
+
readonly footer?: string;
|
|
49
|
+
readonly change?: FluxStatisticsChange;
|
|
50
|
+
readonly icon?: FluxIconName;
|
|
51
|
+
readonly label?: string;
|
|
52
|
+
readonly title: string;
|
|
53
|
+
readonly value?: string | number;
|
|
54
|
+
}>();
|
|
55
|
+
|
|
56
|
+
const slots = defineSlots<{
|
|
57
|
+
default?(): any;
|
|
58
|
+
}>();
|
|
59
|
+
</script>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Chart
|
|
3
|
+
:aspectRatio="aspectRatio"
|
|
4
|
+
:options="merge({
|
|
5
|
+
chart: {
|
|
6
|
+
type: 'pie'
|
|
7
|
+
},
|
|
8
|
+
legend: {
|
|
9
|
+
show: false
|
|
10
|
+
},
|
|
11
|
+
tooltip: {
|
|
12
|
+
enabled: false
|
|
13
|
+
}
|
|
14
|
+
}, options)"
|
|
15
|
+
:series="series"/>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<script
|
|
19
|
+
lang="ts"
|
|
20
|
+
setup>
|
|
21
|
+
import type { ApexOptions } from 'apexcharts';
|
|
22
|
+
import { merge } from 'lodash-es';
|
|
23
|
+
import Chart from './FluxStatisticsChart.vue';
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
options = {}
|
|
27
|
+
} = defineProps<{
|
|
28
|
+
readonly aspectRatio?: number;
|
|
29
|
+
readonly options?: ApexOptions;
|
|
30
|
+
readonly series: ApexOptions['series'];
|
|
31
|
+
}>();
|
|
32
|
+
</script>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export { default as FluxStatisticsAreaChart } from './FluxStatisticsAreaChart.vue';
|
|
2
|
+
export { default as FluxStatisticsBarChart } from './FluxStatisticsBarChart.vue';
|
|
3
|
+
export { default as FluxStatisticsBase } from './FluxStatisticsBase.vue';
|
|
4
|
+
export { default as FluxStatisticsChange } from './FluxStatisticsChange.vue';
|
|
5
|
+
export { default as FluxStatisticsChart } from './FluxStatisticsChart.vue';
|
|
6
|
+
export { default as FluxStatisticsChartPane } from './FluxStatisticsChartPane.vue';
|
|
7
|
+
export { default as FluxStatisticsDetailsTable } from './FluxStatisticsDetailsTable.vue';
|
|
8
|
+
export { default as FluxStatisticsDetailsTableRow } from './FluxStatisticsDetailsTableRow.vue';
|
|
9
|
+
export { default as FluxStatisticsDonutChart } from './FluxStatisticsDonutChart.vue';
|
|
10
|
+
export { default as FluxStatisticsGrid } from './FluxStatisticsGrid.vue';
|
|
11
|
+
export { default as FluxStatisticsLineChart } from './FluxStatisticsLineChart.vue';
|
|
12
|
+
export { default as FluxStatisticsKpi } from './FluxStatisticsKpi.vue';
|
|
13
|
+
export { default as FluxStatisticsLegend } from './FluxStatisticsLegend.vue';
|
|
14
|
+
export { default as FluxStatisticsLegendItem } from './FluxStatisticsLegendItem.vue';
|
|
15
|
+
export { default as FluxStatisticsMeter } from './FluxStatisticsMeter.vue';
|
|
16
|
+
export { default as FluxStatisticsMetric } from './FluxStatisticsMetric.vue';
|
|
17
|
+
export { default as FluxStatisticsPieChart } from './FluxStatisticsPieChart.vue';
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
.statisticsBase {
|
|
2
|
+
display: flex;
|
|
3
|
+
height: 100%;
|
|
4
|
+
flex-flow: column;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.statisticsBaseSmall {
|
|
8
|
+
composes: statisticsBase;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.statisticsBaseContent {
|
|
12
|
+
position: relative;
|
|
13
|
+
display: flex;
|
|
14
|
+
padding: 21px;
|
|
15
|
+
flex-flow: column;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.statisticsBaseHeader {
|
|
19
|
+
display: flex;
|
|
20
|
+
padding: 21px 21px 0;
|
|
21
|
+
align-items: flex-start;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.statisticsBaseHeaderTitle {
|
|
25
|
+
color: var(--foreground-prominent);
|
|
26
|
+
font-size: 15px;
|
|
27
|
+
font-weight: 600;
|
|
28
|
+
line-height: 24px;
|
|
29
|
+
word-break: break-word;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.statisticsBaseHeaderIcon {
|
|
33
|
+
margin-left: auto;
|
|
34
|
+
color: var(--primary-600);
|
|
35
|
+
font-size: 20px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.statisticsBaseSmall .statisticsBaseHeaderTitle {
|
|
39
|
+
color: var(--foreground);
|
|
40
|
+
font-size: 14px;
|
|
41
|
+
line-height: 18px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.statisticsBaseSmall .statisticsBaseHeaderIcon {
|
|
45
|
+
font-size: 18px;
|
|
46
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
.statisticsChange {
|
|
2
|
+
display: inline-flex;
|
|
3
|
+
align-items: baseline;
|
|
4
|
+
flex-flow: row nowrap;
|
|
5
|
+
gap: 6px;
|
|
6
|
+
|
|
7
|
+
&.isGray {
|
|
8
|
+
--color: var(--foreground-prominent);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
&.isPrimary {
|
|
12
|
+
--color: var(--primary-600);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
&.isDanger {
|
|
16
|
+
--color: var(--danger-600);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
&.isInfo {
|
|
20
|
+
--color: var(--info-600);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
&.isSuccess {
|
|
24
|
+
--color: var(--success-600);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&.isWarning {
|
|
28
|
+
--color: var(--warning-600);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.statisticsChangeIcon {
|
|
33
|
+
color: var(--color);
|
|
34
|
+
font-size: 12px;
|
|
35
|
+
translate: 0 1px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.statisticsChangeValue {
|
|
39
|
+
color: var(--color);
|
|
40
|
+
font-size: 12px;
|
|
41
|
+
font-weight: 500;
|
|
42
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--chart-primary: var(--primary-700);
|
|
3
|
+
--chart-positive: var(--success-500);
|
|
4
|
+
--chart-negative: var(--danger-500);
|
|
5
|
+
--chart-1: var(--chart-primary);
|
|
6
|
+
--chart-2: var(--primary-500);
|
|
7
|
+
--chart-3: var(--primary-300);
|
|
8
|
+
--chart-4: var(--primary-100);
|
|
9
|
+
--chart-secondary-1: var(--gray-300);
|
|
10
|
+
--chart-secondary-2: var(--gray-200);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
:local(.pane):has(.statisticsChart) {
|
|
14
|
+
display: flex;
|
|
15
|
+
min-width: 0;
|
|
16
|
+
flex-flow: column;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.statisticsChart {
|
|
20
|
+
position: absolute;
|
|
21
|
+
display: block;
|
|
22
|
+
inset: 0;
|
|
23
|
+
//inset: -3px -2px -4px -2px;
|
|
24
|
+
height: unset;
|
|
25
|
+
width: unset;
|
|
26
|
+
|
|
27
|
+
:global(svg) {
|
|
28
|
+
overflow: hidden;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
--stroke: rgb(from var(--surface-stroke) r g b / .5);
|
|
32
|
+
|
|
33
|
+
:global(.apexcharts-canvas) {
|
|
34
|
+
:global(.apexcharts-grid-borders) {
|
|
35
|
+
display: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:global(.apexcharts-yaxis-texts-g) {
|
|
39
|
+
display: none;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:global(.apexcharts-tooltip) {
|
|
43
|
+
background: rgb(from var(--gray-25) r g b / .85);
|
|
44
|
+
background-clip: padding-box;
|
|
45
|
+
backdrop-filter: blur(6px) saturate(180%);
|
|
46
|
+
border: 1px solid var(--surface-stroke-out-hover);
|
|
47
|
+
border-radius: var(--radius-double);
|
|
48
|
+
box-shadow: var(--shadow-lg);
|
|
49
|
+
color: var(--foreground);
|
|
50
|
+
contain: paint;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.statisticsChartElement {
|
|
56
|
+
position: absolute;
|
|
57
|
+
display: block;
|
|
58
|
+
inset: 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.statisticsChartTooltipTitle {
|
|
62
|
+
padding: 18px 18px 0;
|
|
63
|
+
color: var(--foreground-prominent);
|
|
64
|
+
font-size: 15px;
|
|
65
|
+
font-weight: 700;
|
|
66
|
+
line-height: 1;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.statisticsChartTooltipBody {
|
|
70
|
+
display: grid;
|
|
71
|
+
padding: 12px 18px 15px;
|
|
72
|
+
align-items: center;
|
|
73
|
+
gap: 6px 15px;
|
|
74
|
+
grid-template-columns: repeat(3, auto);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.statisticsChartTooltipSeriesColor {
|
|
78
|
+
height: 12px;
|
|
79
|
+
width: 12px;
|
|
80
|
+
background: var(--danger-600);
|
|
81
|
+
border-radius: 6px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.statisticsChartTooltipSeriesName {
|
|
85
|
+
font-size: 14px;
|
|
86
|
+
font-weight: 700;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.statisticsChartTooltipSeriesValue {
|
|
90
|
+
font-size: 14px;
|
|
91
|
+
font-weight: 500;
|
|
92
|
+
text-align: right;
|
|
93
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
@use '$flux/css/mixin';
|
|
2
|
+
|
|
3
|
+
.statisticsChartPane {
|
|
4
|
+
--aspect-ratio: unset;
|
|
5
|
+
|
|
6
|
+
max-width: 100%;
|
|
7
|
+
aspect-ratio: var(--aspect-ratio);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.statisticsChartPaneBody {
|
|
11
|
+
display: grid;
|
|
12
|
+
flex-grow: 1;
|
|
13
|
+
grid-template-columns: 1fr;
|
|
14
|
+
grid-template-rows: 1fr;
|
|
15
|
+
|
|
16
|
+
&:has(.statisticsLegend) {
|
|
17
|
+
grid-template-columns: 1fr 1fr;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.statisticsChartPaneContainer {
|
|
22
|
+
position: relative;
|
|
23
|
+
display: block;
|
|
24
|
+
|
|
25
|
+
&:first-child :global(svg) {
|
|
26
|
+
border-top-left-radius: var(--radius);
|
|
27
|
+
border-top-right-radius: var(--radius);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
&:last-child :global(svg) {
|
|
31
|
+
border-bottom-left-radius: var(--radius);
|
|
32
|
+
border-bottom-right-radius: var(--radius);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
:local(.paneHeader) + .statisticsChartPaneContainer {
|
|
37
|
+
margin-top: 21px;
|
|
38
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
@use '$flux/css/mixin';
|
|
2
|
+
|
|
3
|
+
.detailsTable {
|
|
4
|
+
composes: statisticsStackable from './Core.module.scss';
|
|
5
|
+
|
|
6
|
+
display: flex;
|
|
7
|
+
flex-flow: column;
|
|
8
|
+
gap: 6px;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.detailsTableRow {
|
|
12
|
+
display: flex;
|
|
13
|
+
margin: -3px -6px;
|
|
14
|
+
padding: 3px 6px;
|
|
15
|
+
color: var(--foreground-secondary);
|
|
16
|
+
font-size: 14px;
|
|
17
|
+
line-height: 24px;
|
|
18
|
+
border-radius: var(--radius-half);
|
|
19
|
+
|
|
20
|
+
@include mixin.hover {
|
|
21
|
+
background: var(--gray-50);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.detailsTableRowLabel {
|
|
26
|
+
flex-grow: 1;
|
|
27
|
+
font-weight: 500;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.detailsTableRowValue {
|
|
31
|
+
text-align: right;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.detailsTableRows {
|
|
35
|
+
display: flex;
|
|
36
|
+
flex-flow: column;
|
|
37
|
+
gap: 3px;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.detailsTableTitle {
|
|
41
|
+
font-size: 15px;
|
|
42
|
+
font-weight: 600;
|
|
43
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
@use '$flux/css/mixin';
|
|
2
|
+
|
|
3
|
+
.statisticsGrid {
|
|
4
|
+
--columns: 1;
|
|
5
|
+
--gap: 21px;
|
|
6
|
+
|
|
7
|
+
position: relative;
|
|
8
|
+
container: grid / inline-size;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
.statisticsGridContent {
|
|
12
|
+
display: grid;
|
|
13
|
+
gap: var(--gap);
|
|
14
|
+
grid-template-columns: repeat(var(--columns), 1fr);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
$-breakpoints: xl, lg, md, sm, xs;
|
|
18
|
+
//$-breakpoints: xs, sm, md, lg, xl;
|
|
19
|
+
|
|
20
|
+
@each $-breakpoint in $-breakpoints {
|
|
21
|
+
@include mixin.container-breakpoint-down(grid, $-breakpoint) {
|
|
22
|
+
.statisticsGridContent {
|
|
23
|
+
--columns: var(--#{$-breakpoint});
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
.statisticsKpiBottom {
|
|
2
|
+
margin-top: 3px;
|
|
3
|
+
line-height: 18px;
|
|
4
|
+
|
|
5
|
+
:local(.statisticsChange) {
|
|
6
|
+
margin-right: .3em;
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.statisticsKpiFooter {
|
|
11
|
+
color: var(--foreground-secondary);
|
|
12
|
+
font-size: 14px;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.statisticsKpiValue {
|
|
16
|
+
padding-top: 21px;
|
|
17
|
+
color: var(--foreground-prominent);
|
|
18
|
+
font-size: 21px;
|
|
19
|
+
font-weight: 800;
|
|
20
|
+
line-height: 36px;
|
|
21
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
@use '$flux/css/mixin';
|
|
2
|
+
|
|
3
|
+
.statisticsLegend {
|
|
4
|
+
display: flex;
|
|
5
|
+
min-width: 0;
|
|
6
|
+
padding: 15px 21px 15px;
|
|
7
|
+
align-self: center;
|
|
8
|
+
flex-flow: column;
|
|
9
|
+
flex-grow: 1;
|
|
10
|
+
gap: 3px;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.statisticsLegendItem {
|
|
14
|
+
--color: var(--primary-600);
|
|
15
|
+
|
|
16
|
+
display: flex;
|
|
17
|
+
padding: 6px 0;
|
|
18
|
+
align-items: flex-start;
|
|
19
|
+
flex-flow: row nowrap;
|
|
20
|
+
gap: 9px;
|
|
21
|
+
font-size: 14px;
|
|
22
|
+
line-height: 20px;
|
|
23
|
+
white-space: nowrap;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.statisticsLegendItemColor {
|
|
27
|
+
height: 12px;
|
|
28
|
+
width: 12px;
|
|
29
|
+
margin: 4px;
|
|
30
|
+
flex-shrink: 0;
|
|
31
|
+
background: var(--color);
|
|
32
|
+
border-radius: calc(var(--radius-half) / 2);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.statisticsLegendItemIcon {
|
|
36
|
+
margin: 2px;
|
|
37
|
+
color: var(--color);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.statisticsLegendItemLabel {
|
|
41
|
+
flex-grow: 1;
|
|
42
|
+
color: var(--foreground);
|
|
43
|
+
font-weight: 600;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.statisticsLegendItemValue {
|
|
47
|
+
margin-left: 15px;
|
|
48
|
+
text-align: right;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.statisticsLegendItem + .statisticsLegendItem {
|
|
52
|
+
border-top: 1px dashed var(--surface-stroke);
|
|
53
|
+
}
|