@centreon/ui 24.10.12 → 24.10.13

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 (153) hide show
  1. package/package.json +3 -2
  2. package/public/mockServiceWorker.js +1 -1
  3. package/src/Button/Icon/index.tsx +3 -1
  4. package/src/Dashboard/Dashboard.styles.ts +3 -4
  5. package/src/Dashboard/DashboardLayout.stories.tsx +1 -1
  6. package/src/Dashboard/Grid.tsx +11 -17
  7. package/src/Dashboard/Layout.tsx +27 -56
  8. package/src/Dialog/UnsavedChanges/index.tsx +15 -13
  9. package/src/Dialog/UnsavedChanges/translatedLabels.ts +15 -13
  10. package/src/Form/Form.tsx +0 -1
  11. package/src/Form/Inputs/Autocomplete.tsx +1 -1
  12. package/src/Form/Inputs/ConnectedAutocomplete.tsx +5 -2
  13. package/src/Form/Inputs/Grid.tsx +7 -1
  14. package/src/Form/Inputs/Radio.tsx +1 -1
  15. package/src/Form/Inputs/Switch.tsx +1 -1
  16. package/src/Form/Inputs/Text.tsx +1 -1
  17. package/src/Form/Inputs/index.tsx +25 -24
  18. package/src/Form/Inputs/models.ts +2 -0
  19. package/src/Graph/BarChart/BarChart.cypress.spec.tsx +3 -3
  20. package/src/Graph/BarChart/BarChart.tsx +24 -31
  21. package/src/Graph/BarChart/BarGroup.tsx +32 -59
  22. package/src/Graph/BarChart/BarStack.tsx +64 -13
  23. package/src/Graph/BarChart/MemoizedGroup.tsx +123 -0
  24. package/src/Graph/BarChart/ResponsiveBarChart.tsx +21 -7
  25. package/src/Graph/BarStack/BarStack.cypress.spec.tsx +87 -9
  26. package/src/Graph/BarStack/BarStack.stories.tsx +13 -4
  27. package/src/Graph/BarStack/BarStack.styles.ts +57 -33
  28. package/src/Graph/BarStack/Graph.tsx +173 -0
  29. package/src/Graph/BarStack/GraphAndLegend.tsx +117 -0
  30. package/src/Graph/BarStack/ResponsiveBarStack.tsx +61 -168
  31. package/src/Graph/BarStack/constants.ts +5 -0
  32. package/src/Graph/BarStack/models.ts +0 -1
  33. package/src/Graph/BarStack/useGraphAndLegend.ts +84 -0
  34. package/src/Graph/BarStack/useResponsiveBarStack.ts +73 -97
  35. package/src/Graph/Chart/Chart.cypress.spec.tsx +14 -26
  36. package/src/Graph/Chart/Chart.stories.tsx +1 -1
  37. package/src/Graph/Chart/Chart.tsx +53 -37
  38. package/src/Graph/Chart/InteractiveComponents/AnchorPoint/GuidingLines.tsx +3 -3
  39. package/src/Graph/Chart/InteractiveComponents/AnchorPoint/useTickGraph.ts +19 -6
  40. package/src/Graph/Chart/Legend/Legend.styles.ts +25 -11
  41. package/src/Graph/Chart/Legend/index.tsx +6 -24
  42. package/src/Graph/Chart/index.tsx +34 -43
  43. package/src/Graph/Chart/models.ts +0 -1
  44. package/src/Graph/Chart/useChartData.ts +19 -1
  45. package/src/Graph/HeatMap/ResponsiveHeatMap.tsx +20 -2
  46. package/src/Graph/HeatMap/model.ts +6 -2
  47. package/src/Graph/Legend/Legend.styles.ts +10 -0
  48. package/src/Graph/Legend/Legend.tsx +6 -1
  49. package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +9 -10
  50. package/src/Graph/SingleBar/ThresholdLine.tsx +6 -6
  51. package/src/Graph/Text/Text.styles.ts +2 -2
  52. package/src/Graph/Text/Text.tsx +23 -10
  53. package/src/Graph/Timeline/ResponsiveTimeline.tsx +152 -0
  54. package/src/Graph/Timeline/Timeline.cypress.spec.tsx +148 -0
  55. package/src/Graph/Timeline/Timeline.stories.tsx +91 -0
  56. package/src/Graph/Timeline/Timeline.tsx +28 -0
  57. package/src/Graph/Timeline/index.ts +1 -0
  58. package/src/Graph/Timeline/models.ts +20 -0
  59. package/src/Graph/Timeline/timeline.styles.ts +11 -0
  60. package/src/Graph/Timeline/translatedLabel.ts +6 -0
  61. package/src/Graph/Timeline/useTimeline.ts +90 -0
  62. package/src/Graph/Tree/Links.tsx +2 -2
  63. package/src/Graph/Tree/Tree.tsx +2 -2
  64. package/src/Graph/Tree/constants.ts +1 -1
  65. package/src/Graph/common/Axes/index.tsx +1 -1
  66. package/src/Graph/common/Axes/useAxisY.ts +8 -4
  67. package/src/Graph/common/BaseChart/BaseChart.tsx +3 -12
  68. package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +12 -4
  69. package/src/Graph/common/BaseChart/Header/index.tsx +3 -1
  70. package/src/Graph/common/BaseChart/useComputeBaseChartDimensions.ts +23 -11
  71. package/src/Graph/common/BaseChart/useComputeYAxisMaxCharacters.ts +92 -0
  72. package/src/Graph/common/models.ts +7 -8
  73. package/src/Graph/common/timeSeries/index.test.ts +1 -1
  74. package/src/Graph/common/timeSeries/index.ts +56 -29
  75. package/src/Graph/common/timeSeries/models.ts +2 -0
  76. package/src/Graph/common/utils.ts +51 -3
  77. package/src/Graph/index.ts +4 -1
  78. package/src/Graph/mockedData/lastDayWithNullValues.json +6 -6
  79. package/src/Graph/mockedData/pingServiceLinesBars.json +47 -47
  80. package/src/Icon/DowntimeIcon.tsx +8 -1
  81. package/src/Icon/FlappingIcon.tsx +22 -0
  82. package/src/Icon/index.ts +1 -0
  83. package/src/InputField/Select/Autocomplete/Connected/Multi/index.test.tsx +21 -1
  84. package/src/InputField/Select/Autocomplete/Connected/index.test.tsx +2 -2
  85. package/src/InputField/Select/Autocomplete/Connected/index.tsx +52 -15
  86. package/src/InputField/Select/Autocomplete/Multi/index.stories.tsx +19 -0
  87. package/src/InputField/Select/Autocomplete/Multi/index.tsx +8 -5
  88. package/src/InputField/Select/Autocomplete/index.tsx +79 -54
  89. package/src/InputField/Text/index.tsx +6 -4
  90. package/src/InputField/translatedLabels.ts +2 -0
  91. package/src/Listing/ActionBar/index.tsx +1 -1
  92. package/src/Listing/Listing.styles.ts +3 -3
  93. package/src/Listing/index.tsx +40 -37
  94. package/src/Listing/models.ts +0 -8
  95. package/src/Listing/useStyleTable.ts +58 -32
  96. package/src/MultiSelectEntries/index.tsx +2 -0
  97. package/src/PopoverMenu/index.tsx +2 -9
  98. package/src/SortableItems/index.tsx +0 -1
  99. package/src/ThemeProvider/index.tsx +1 -1
  100. package/src/ThemeProvider/palettes.ts +6 -0
  101. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +2 -3
  102. package/src/TimePeriods/DateTimePickerInput.tsx +3 -1
  103. package/src/api/buildListingEndpoint/getSearchQueryParameterValue.ts +7 -1
  104. package/src/api/buildListingEndpoint/models.ts +1 -0
  105. package/src/api/customFetch.ts +4 -1
  106. package/src/api/models.ts +9 -0
  107. package/src/api/useGraphQuery/index.ts +117 -20
  108. package/src/api/useGraphQuery/models.ts +1 -0
  109. package/src/api/useMutationQuery/index.ts +1 -1
  110. package/src/components/DataTable/DataTable.styles.ts +1 -1
  111. package/src/components/DataTable/EmptyState/DataTableEmptyState.styles.ts +2 -1
  112. package/src/components/DataTable/EmptyState/DataTableEmptyState.tsx +4 -1
  113. package/src/components/DataTable/Item/DataTableItem.styles.ts +28 -2
  114. package/src/components/DataTable/Item/DataTableItem.tsx +19 -4
  115. package/src/components/Form/FormActions.tsx +21 -12
  116. package/src/components/Layout/AreaIndicator.tsx +1 -1
  117. package/src/components/Layout/PageLayout/PageLayout.styles.ts +2 -7
  118. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +0 -1
  119. package/src/components/Zoom/Zoom.tsx +9 -2
  120. package/src/components/Zoom/ZoomContent.tsx +143 -136
  121. package/src/components/Zoom/models.ts +18 -15
  122. package/src/components/Zoom/useMinimap.ts +5 -8
  123. package/src/components/Zoom/useZoom.ts +3 -3
  124. package/src/index.ts +2 -0
  125. package/src/utils/index.ts +1 -0
  126. package/src/utils/useLocale/index.ts +9 -0
  127. package/src/utils/useLocale/useLocale.cypress.spec.tsx +38 -0
  128. package/src/utils/useLocaleDateTimeFormat/index.ts +4 -2
  129. package/src/utils/usePluralizedTranslation.ts +2 -3
  130. package/src/Graph/common/timeSeries/index.test.ts-E +0 -622
  131. package/src/components/CrudPage/Actions/Actions.styles.ts +0 -16
  132. package/src/components/CrudPage/Actions/Actions.tsx +0 -24
  133. package/src/components/CrudPage/Actions/AddButton.tsx +0 -23
  134. package/src/components/CrudPage/Actions/Filters.tsx +0 -25
  135. package/src/components/CrudPage/Actions/Search.tsx +0 -31
  136. package/src/components/CrudPage/Actions/useSearch.tsx +0 -24
  137. package/src/components/CrudPage/Columns/Actions.tsx +0 -88
  138. package/src/components/CrudPage/CrudPage.cypress.spec.tsx +0 -559
  139. package/src/components/CrudPage/CrudPage.stories.tsx +0 -278
  140. package/src/components/CrudPage/CrudPageRoot.tsx +0 -142
  141. package/src/components/CrudPage/DeleteModal.tsx +0 -77
  142. package/src/components/CrudPage/Form/AddModal.tsx +0 -35
  143. package/src/components/CrudPage/Form/Buttons.tsx +0 -98
  144. package/src/components/CrudPage/Form/UpdateModal.tsx +0 -60
  145. package/src/components/CrudPage/Listing.tsx +0 -63
  146. package/src/components/CrudPage/atoms.ts +0 -30
  147. package/src/components/CrudPage/hooks/useDeleteItem.ts +0 -53
  148. package/src/components/CrudPage/hooks/useGetItem.ts +0 -36
  149. package/src/components/CrudPage/hooks/useGetItems.ts +0 -67
  150. package/src/components/CrudPage/hooks/useListingQueryKey.ts +0 -31
  151. package/src/components/CrudPage/index.tsx +0 -7
  152. package/src/components/CrudPage/models.ts +0 -118
  153. package/src/components/CrudPage/utils.ts +0 -4
@@ -1,18 +1,14 @@
1
- import { useRef } from 'react';
2
-
3
- import { Group } from '@visx/group';
4
- import { BarStackHorizontal, BarStack as BarStackVertical } from '@visx/shape';
5
- import { Text } from '@visx/text';
6
- import numeral from 'numeral';
7
- import { equals, lt } from 'ramda';
8
- import { useTranslation } from 'react-i18next';
9
-
10
- import { Tooltip } from '../../components';
11
1
  import { Legend as LegendComponent } from '../Legend';
12
2
  import { LegendProps } from '../Legend/models';
13
- import { getValueByUnit } from '../common/utils';
3
+ import { useStyles } from './BarStack.styles';
14
4
 
15
- import { useBarStackStyles } from './BarStack.styles';
5
+ import { Typography } from '@mui/material';
6
+ import numeral from 'numeral';
7
+ import { equals } from 'ramda';
8
+ import { useMemo } from 'react';
9
+ import { useTranslation } from 'react-i18next';
10
+ import GraphAndLegend from './GraphAndLegend';
11
+ import { gap, smallTitleHeight, titleHeight } from './constants';
16
12
  import { BarStackProps } from './models';
17
13
  import useResponsiveBarStack from './useResponsiveBarStack';
18
14
 
@@ -23,9 +19,8 @@ const DefaultLengd = ({ scale, direction }: LegendProps): JSX.Element => (
23
19
  const ResponsiveBarStack = ({
24
20
  title,
25
21
  data,
26
- width,
27
22
  height,
28
- size = 72,
23
+ width,
29
24
  onSingleBarClick,
30
25
  displayLegend = true,
31
26
  TooltipContent,
@@ -33,184 +28,82 @@ const ResponsiveBarStack = ({
33
28
  unit = 'number',
34
29
  displayValues,
35
30
  variant = 'vertical',
36
- legendDirection = 'column',
31
+ legendDirection,
37
32
  tooltipProps = {}
38
33
  }: BarStackProps & { height: number; width: number }): JSX.Element => {
39
34
  const { t } = useTranslation();
40
- const { classes, cx } = useBarStackStyles();
41
-
42
- const titleRef = useRef(null);
43
- const legendRef = useRef(null);
35
+ const { classes, cx } = useStyles();
44
36
 
45
37
  const {
46
- barSize,
47
- colorScale,
48
- input,
49
- keys,
50
- legendScale,
51
38
  total,
52
- xScale,
53
- yScale,
54
- svgContainerSize,
55
- isVerticalBar
39
+ titleVariant,
40
+ legendScale,
41
+ isVerticalBar,
42
+ colorScale,
43
+ formattedLegendDirection
56
44
  } = useResponsiveBarStack({
57
45
  data,
58
46
  height,
59
- legendRef,
60
- size,
61
- titleRef,
47
+ width,
62
48
  unit,
63
49
  variant,
64
- width
50
+ legendDirection
65
51
  });
66
52
 
67
- const BarStackComponent = isVerticalBar
68
- ? BarStackVertical
69
- : BarStackHorizontal;
53
+ const graphAndLegendHeight = useMemo(() => {
54
+ if (equals(titleVariant, 'xs')) {
55
+ return height - 2 * smallTitleHeight - gap;
56
+ }
70
57
 
71
- const isSmallHeight = isVerticalBar ? lt(height, 190) : lt(height, 100);
72
- const isSmallWidth = isVerticalBar ? lt(width, 80) : lt(width, 350);
73
- const mustDisplayLegend = isSmallWidth ? false : displayLegend;
58
+ if (equals(titleVariant, 'sm')) {
59
+ return height - smallTitleHeight - gap;
60
+ }
61
+
62
+ return height - titleHeight - gap;
63
+ }, [titleVariant, height]);
74
64
 
75
65
  return (
76
- <div className={classes.container} style={{ width }}>
77
- <div className={classes.svgWrapper}>
78
- {title && (
79
- <div
80
- className={cx(classes.title, isSmallHeight && classes.smallTitle)}
81
- data-testid="Title"
82
- ref={titleRef}
83
- >
84
- {`${numeral(total).format('0a').toUpperCase()} `} {t(title)}
85
- </div>
86
- )}
87
- <div
88
- className={classes.svgContainer}
89
- data-testid="barStack"
90
- style={{
91
- width: svgContainerSize.width
92
- }}
66
+ <div
67
+ className={classes.container}
68
+ data-has-title={!!title}
69
+ data-title-variant={titleVariant}
70
+ data-variant={variant}
71
+ >
72
+ {title && (
73
+ <Typography
74
+ data-testid="Title"
75
+ variant={equals(titleVariant, 'md') ? 'h6' : 'body1'}
76
+ textAlign="center"
77
+ fontWeight="bold"
78
+ className={cx(equals(titleVariant, 'md') && classes.clippedTitle)}
93
79
  >
94
- <svg
95
- data-variant={variant}
96
- height={barSize.height}
97
- width={barSize.width}
98
- >
99
- <Group>
100
- <BarStackComponent
101
- color={colorScale}
102
- data={[input]}
103
- keys={keys}
104
- {...(isVerticalBar
105
- ? { x: () => undefined }
106
- : { y: () => undefined })}
107
- xScale={xScale}
108
- yScale={yScale}
109
- >
110
- {(barStacks) =>
111
- barStacks.map((barStack) =>
112
- barStack.bars.map((bar) => {
113
- const shouldDisplayValues = (): boolean => {
114
- if (bar.height < 10) {
115
- return false;
116
- }
117
-
118
- return (
119
- (equals(unit, 'number') && bar.width > 10) ||
120
- (equals(unit, 'percentage') && bar.width > 25)
121
- );
122
- };
123
-
124
- const TextX = bar.x + bar.width / 2;
125
- const TextY = bar.y + bar.height / 2;
126
-
127
- const onClick = (): void => {
128
- onSingleBarClick?.(bar);
129
- };
130
-
131
- return (
132
- <Tooltip
133
- hasCaret
134
- classes={{
135
- tooltip: classes.barStackTooltip
136
- }}
137
- followCursor={false}
138
- key={`bar-stack-${barStack.index}-${bar.index}`}
139
- label={
140
- TooltipContent && (
141
- <TooltipContent
142
- color={bar.color}
143
- label={bar.key}
144
- title={title}
145
- total={total}
146
- value={barStack.bars[0].bar.data[barStack.key]}
147
- {...tooltipProps}
148
- />
149
- )
150
- }
151
- position={
152
- isVerticalBar ? 'right-start' : 'bottom-start'
153
- }
154
- >
155
- <g
156
- data-testid={bar.key}
157
- onClick={onClick}
158
- onKeyUp={() => undefined}
159
- >
160
- <rect
161
- cursor="pointer"
162
- fill={bar.color}
163
- height={
164
- isVerticalBar ? bar.height - 1 : bar.height
165
- }
166
- key={`bar-stack-${barStack.index}-${bar.index}`}
167
- ry={4}
168
- width={isVerticalBar ? bar.width : bar.width - 1}
169
- x={bar.x}
170
- y={bar.y}
171
- />
172
- {displayValues && shouldDisplayValues() && (
173
- <Text
174
- cursor="pointer"
175
- data-testid="value"
176
- fill="#000"
177
- fontSize={12}
178
- fontWeight={600}
179
- textAnchor="middle"
180
- verticalAnchor="middle"
181
- x={TextX}
182
- y={TextY}
183
- >
184
- {getValueByUnit({
185
- total,
186
- unit,
187
- value: barStack.bars[0].bar.data[barStack.key]
188
- })}
189
- </Text>
190
- )}
191
- </g>
192
- </Tooltip>
193
- );
194
- })
195
- )
196
- }
197
- </BarStackComponent>
198
- </Group>
199
- </svg>
200
- </div>
201
- </div>
202
- {mustDisplayLegend && (
203
- <div data-testid="Legend" ref={legendRef}>
80
+ {`${numeral(total).format('0a')}`} {t(title)}
81
+ </Typography>
82
+ )}
83
+ <GraphAndLegend
84
+ height={graphAndLegendHeight}
85
+ width={width}
86
+ isVerticalBar={isVerticalBar}
87
+ displayLegend={displayLegend}
88
+ colorScale={colorScale}
89
+ total={total}
90
+ data={data}
91
+ unit={unit}
92
+ displayValues={displayValues}
93
+ onSingleBarClick={onSingleBarClick}
94
+ tooltipProps={tooltipProps}
95
+ TooltipContent={TooltipContent}
96
+ legend={
204
97
  <Legend
205
98
  data={data}
206
- direction={legendDirection}
99
+ direction={formattedLegendDirection}
207
100
  scale={legendScale}
208
101
  title={title}
209
102
  total={total}
210
103
  unit={unit}
211
104
  />
212
- </div>
213
- )}
105
+ }
106
+ />
214
107
  </div>
215
108
  );
216
109
  };
@@ -0,0 +1,5 @@
1
+ export const legendMaxWidth = 85;
2
+ export const legendMaxHeight = 43;
3
+ export const titleHeight = 36;
4
+ export const smallTitleHeight = 20;
5
+ export const gap = 4;
@@ -12,7 +12,6 @@ export type BarStackProps = {
12
12
  displayValues?: boolean;
13
13
  legendDirection?: 'row' | 'column';
14
14
  onSingleBarClick?: (barData) => void;
15
- size?: number;
16
15
  title?: string;
17
16
  tooltipProps?: object;
18
17
  unit?: 'percentage' | 'number';
@@ -0,0 +1,84 @@
1
+ import { scaleBand, scaleLinear } from '@visx/scale';
2
+ import { pluck } from 'ramda';
3
+ import { useMemo } from 'react';
4
+ import { BarType } from './models';
5
+
6
+ interface UseGraphandLegendProps {
7
+ data: Array<BarType>;
8
+ isVerticalBar: boolean;
9
+ total: number;
10
+ width: number;
11
+ height: number;
12
+ }
13
+
14
+ interface UseGraphAndLegendState {
15
+ barStackData: Record<string, number>;
16
+ xScale;
17
+ yScale;
18
+ keys: Array<string>;
19
+ }
20
+
21
+ export const useGraphAndLegend = ({
22
+ data,
23
+ isVerticalBar,
24
+ total,
25
+ width,
26
+ height
27
+ }: UseGraphandLegendProps): UseGraphAndLegendState => {
28
+ const dataWithNonEmptyValue = useMemo(
29
+ () => data.filter(({ value }) => value),
30
+ [data]
31
+ );
32
+
33
+ const keys = useMemo(
34
+ () => pluck('label', dataWithNonEmptyValue),
35
+ [dataWithNonEmptyValue]
36
+ );
37
+
38
+ const barStackData = useMemo(
39
+ () =>
40
+ dataWithNonEmptyValue.reduce((acc, { label, value }) => {
41
+ acc[label] = value;
42
+
43
+ return acc;
44
+ }, {}),
45
+ [dataWithNonEmptyValue]
46
+ );
47
+
48
+ const yScale = useMemo(
49
+ () =>
50
+ isVerticalBar
51
+ ? scaleLinear({
52
+ domain: [0, total],
53
+ range: [height, 0]
54
+ })
55
+ : scaleBand({
56
+ domain: [0, 0],
57
+ padding: 0,
58
+ range: [height, 0]
59
+ }),
60
+ [isVerticalBar, total, height]
61
+ );
62
+
63
+ const xScale = useMemo(
64
+ () =>
65
+ isVerticalBar
66
+ ? scaleBand({
67
+ domain: [0, 0],
68
+ padding: 0,
69
+ range: [0, width]
70
+ })
71
+ : scaleLinear({
72
+ domain: [0, total],
73
+ range: [0, width]
74
+ }),
75
+ [total, width, isVerticalBar]
76
+ );
77
+
78
+ return {
79
+ barStackData,
80
+ xScale,
81
+ yScale,
82
+ keys
83
+ };
84
+ };
@@ -1,37 +1,27 @@
1
- import { scaleBand, scaleLinear, scaleOrdinal } from '@visx/scale';
2
- import { equals, gt, pluck } from 'ramda';
3
-
1
+ import { scaleOrdinal } from '@visx/scale';
2
+ import { equals, isNil, pluck } from 'ramda';
3
+ import { useMemo } from 'react';
4
4
  import { LegendScale } from '../Legend/models';
5
5
  import { getValueByUnit } from '../common/utils';
6
-
7
6
  import { BarType } from './models';
8
7
 
9
- interface Size {
10
- height: number;
11
- width: number;
12
- }
13
-
14
8
  interface UseBarStackProps {
15
9
  data: Array<BarType>;
16
10
  height: number;
17
- legendRef;
18
- size: number;
19
- titleRef;
11
+ width: number;
20
12
  unit?: 'percentage' | 'number';
21
13
  variant?: 'vertical' | 'horizontal';
22
- width: number;
14
+ legendDirection?: 'column' | 'row';
23
15
  }
16
+
24
17
  interface UseBarStackState {
25
- barSize: Size;
26
- colorScale;
27
- input;
18
+ total: number;
19
+ isSmall: boolean;
20
+ titleVariant: 'xs' | 'sm' | 'md';
28
21
  isVerticalBar: boolean;
29
- keys: Array<string>;
30
22
  legendScale: LegendScale;
31
- svgContainerSize: Size;
32
- total: number;
33
- xScale;
34
- yScale;
23
+ colorScale;
24
+ formattedLegendDirection: 'column' | 'row';
35
25
  }
36
26
 
37
27
  const useResponsiveBarStack = ({
@@ -40,87 +30,73 @@ const useResponsiveBarStack = ({
40
30
  height,
41
31
  width,
42
32
  unit = 'number',
43
- titleRef,
44
- legendRef,
45
- size
33
+ legendDirection
46
34
  }: UseBarStackProps): UseBarStackState => {
47
- const isVerticalBar = equals(variant, 'vertical');
48
-
49
- const heightOfTitle = titleRef.current?.offsetHeight || 0;
50
- const widthOfLegend = legendRef.current?.offsetWidth || 0;
51
-
52
- const horizontalGap = widthOfLegend > 0 ? 12 : 0;
53
- const verticalGap = heightOfTitle > 0 ? 8 : 0;
54
-
55
- const svgContainerSize = {
56
- height: isVerticalBar ? height - heightOfTitle - verticalGap : size,
57
- width: isVerticalBar ? size : width - widthOfLegend - horizontalGap
58
- };
59
-
60
- const barSize = {
61
- height: gt(height / 2, svgContainerSize.height - 16)
62
- ? svgContainerSize.height - 16
63
- : svgContainerSize.height - 46,
64
- width: svgContainerSize.width - 16
65
- };
66
-
67
- const total = Math.floor(data.reduce((acc, { value }) => acc + value, 0));
68
-
69
- const yScale = isVerticalBar
70
- ? scaleLinear({
71
- domain: [0, total]
72
- })
73
- : scaleBand({
74
- domain: [0, 0],
75
- padding: 0
76
- });
77
-
78
- const xScale = isVerticalBar
79
- ? scaleBand({
80
- domain: [0, 0],
81
- padding: 0
82
- })
83
- : scaleLinear({
84
- domain: [0, total]
85
- });
86
-
87
- const keys = pluck('label', data);
88
-
89
- const colorsRange = pluck('color', data);
90
-
91
- const colorScale = scaleOrdinal({
92
- domain: keys,
93
- range: colorsRange
94
- });
95
-
96
- const legendScale = {
97
- domain: data.map(({ value }) => getValueByUnit({ total, unit, value })),
98
- range: colorsRange
99
- };
100
-
101
- const xMax = barSize.width;
102
- const yMax = barSize.height;
103
-
104
- xScale.rangeRound([0, xMax]);
105
- yScale.range([yMax, 0]);
106
-
107
- const input = data.reduce((acc, { label, value }) => {
108
- acc[label] = value;
109
-
110
- return acc;
111
- }, {});
35
+ const total = useMemo(
36
+ () => Math.floor(data.reduce((acc, { value }) => acc + value, 0)),
37
+ [data]
38
+ );
39
+
40
+ const isVerticalBar = useMemo(() => equals(variant, 'vertical'), [variant]);
41
+
42
+ const isSmall = useMemo(
43
+ () => Math.floor(height) < 90,
44
+ [isVerticalBar, height]
45
+ );
46
+
47
+ const titleVariant = useMemo(() => {
48
+ if (width <= 105) {
49
+ return 'xs';
50
+ }
51
+
52
+ if (width <= 150 || isSmall) {
53
+ return 'sm';
54
+ }
55
+
56
+ return 'md';
57
+ }, [isSmall, width]);
58
+
59
+ const keys = useMemo(() => pluck('label', data), [data]);
60
+
61
+ const colorsRange = useMemo(() => pluck('color', data), [data]);
62
+
63
+ const colorScale = useMemo(
64
+ () =>
65
+ scaleOrdinal({
66
+ domain: keys,
67
+ range: colorsRange
68
+ }),
69
+ [keys, colorsRange]
70
+ );
71
+
72
+ const legendScale = useMemo(
73
+ () => ({
74
+ domain: data.map(({ value }) => getValueByUnit({ total, unit, value })),
75
+ range: colorsRange
76
+ }),
77
+ [data, colorsRange]
78
+ );
79
+
80
+ const formattedLegendDirection = useMemo(() => {
81
+ if (!isNil(legendDirection)) {
82
+ return legendDirection;
83
+ }
84
+
85
+ if (equals(variant, 'horizontal')) {
86
+ return 'row';
87
+ }
88
+
89
+ return 'column';
90
+ }, [legendDirection, variant]);
112
91
 
113
92
  return {
114
- barSize,
115
- colorScale,
116
- input,
93
+ total,
94
+ isSmall,
117
95
  isVerticalBar,
118
- keys,
96
+ titleVariant,
119
97
  legendScale,
120
- svgContainerSize,
121
- total,
122
- xScale,
123
- yScale
98
+ colorScale,
99
+ formattedLegendDirection
124
100
  };
125
101
  };
126
102