@quillsql/react 1.7.5 → 1.7.6
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/lib/ReportBuilder.js +1 -0
- package/lib/ReportBuilder.js.map +1 -1
- package/lib/SQLEditor.js +3 -3
- package/lib/SQLEditor.js.map +1 -1
- package/lib/Table.js +1 -1
- package/lib/Table.js.map +1 -1
- package/lib/components/BigModal/BigModal.js +1 -0
- package/lib/components/BigModal/BigModal.js.map +1 -1
- package/lib/components/Modal/Modal.js +1 -0
- package/lib/components/Modal/Modal.js.map +1 -1
- package/lib/hooks/useQuill.js +1 -0
- package/lib/hooks/useQuill.js.map +1 -1
- package/package.json +11 -4
- package/.eslintrc.json +0 -19
- package/.prettierrc +0 -11
- package/.vscode/settings.json +0 -10
- package/src/AddToDashboardModal.tsx +0 -1220
- package/src/BarList.tsx +0 -580
- package/src/Chart.tsx +0 -1337
- package/src/Context.tsx +0 -252
- package/src/Dashboard.tsx +0 -820
- package/src/DateRangePicker/Calendar.tsx +0 -442
- package/src/DateRangePicker/DateRangePicker.tsx +0 -261
- package/src/DateRangePicker/DateRangePickerButton.tsx +0 -250
- package/src/DateRangePicker/dateRangePickerUtils.tsx +0 -480
- package/src/DateRangePicker/index.ts +0 -4
- package/src/PieChart.tsx +0 -845
- package/src/QuillProvider.tsx +0 -81
- package/src/ReportBuilder.tsx +0 -2208
- package/src/SQLEditor.tsx +0 -1093
- package/src/Table.tsx +0 -1074
- package/src/TableChart.tsx +0 -428
- package/src/assets/ArrowDownHeadIcon.tsx +0 -11
- package/src/assets/ArrowDownIcon.tsx +0 -14
- package/src/assets/ArrowDownRightIcon.tsx +0 -14
- package/src/assets/ArrowLeftHeadIcon.tsx +0 -11
- package/src/assets/ArrowRightHeadIcon.tsx +0 -11
- package/src/assets/ArrowRightIcon.tsx +0 -14
- package/src/assets/ArrowUpHeadIcon.tsx +0 -11
- package/src/assets/ArrowUpIcon.tsx +0 -14
- package/src/assets/ArrowUpRightIcon.tsx +0 -14
- package/src/assets/CalendarIcon.tsx +0 -14
- package/src/assets/DoubleArrowLeftHeadIcon.tsx +0 -18
- package/src/assets/DoubleArrowRightHeadIcon.tsx +0 -20
- package/src/assets/ExclamationFilledIcon.tsx +0 -14
- package/src/assets/LoadingSpinner.tsx +0 -11
- package/src/assets/SearchIcon.tsx +0 -14
- package/src/assets/XCircleIcon.tsx +0 -14
- package/src/assets/index.ts +0 -16
- package/src/components/BigModal/BigModal.tsx +0 -108
- package/src/components/Dropdown/Dropdown.tsx +0 -169
- package/src/components/Dropdown/DropdownItem.tsx +0 -68
- package/src/components/Dropdown/index.ts +0 -2
- package/src/components/Modal/Modal.tsx +0 -132
- package/src/components/Modal/index.ts +0 -1
- package/src/components/selectUtils.ts +0 -60
- package/src/contexts/BaseColorContext.tsx +0 -5
- package/src/contexts/HoveredValueContext.tsx +0 -12
- package/src/contexts/RootStylesContext.tsx +0 -5
- package/src/contexts/SelectedValueContext.tsx +0 -13
- package/src/contexts/index.ts +0 -4
- package/src/hooks/index.ts +0 -4
- package/src/hooks/useInternalState.tsx +0 -18
- package/src/hooks/useOnClickOutside.tsx +0 -23
- package/src/hooks/useOnWindowResize.tsx +0 -17
- package/src/hooks/useQuill.ts +0 -138
- package/src/hooks/useSelectOnKeyDown.tsx +0 -80
- package/src/index.ts +0 -9
- package/src/lib/font.ts +0 -14
- package/src/lib/index.ts +0 -3
- package/src/lib/inputTypes.ts +0 -81
- package/src/lib/utils.tsx +0 -46
- package/tsconfig.json +0 -22
package/src/PieChart.tsx
DELETED
|
@@ -1,845 +0,0 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
|
2
|
-
/* eslint-disable react/display-name */
|
|
3
|
-
// @ts-nocheck
|
|
4
|
-
import React, { useRef, useState, useEffect, CSSProperties } from 'react';
|
|
5
|
-
import { Pie, PieChart, ResponsiveContainer, Tooltip, Legend } from 'recharts';
|
|
6
|
-
|
|
7
|
-
// const data = [
|
|
8
|
-
// {
|
|
9
|
-
// name: 'Project Nile',
|
|
10
|
-
// pct_of_the_total: 0.208266213458027,
|
|
11
|
-
// },
|
|
12
|
-
// {
|
|
13
|
-
// name: 'GA_Columbus',
|
|
14
|
-
// pct_of_the_total: 0.102192710707096,
|
|
15
|
-
// },
|
|
16
|
-
// {
|
|
17
|
-
// name: 'IN_Indianapolis',
|
|
18
|
-
// pct_of_the_total: 0.0965229750772778,
|
|
19
|
-
// },
|
|
20
|
-
// {
|
|
21
|
-
// name: 'MO_St Louis',
|
|
22
|
-
// pct_of_the_total: 0.0732235559304729,
|
|
23
|
-
// },
|
|
24
|
-
// {
|
|
25
|
-
// name: 'AL_Birmingham',
|
|
26
|
-
// pct_of_the_total: 0.0555956813239389,
|
|
27
|
-
// },
|
|
28
|
-
// {
|
|
29
|
-
// name: 'FL_Fort Myers',
|
|
30
|
-
// pct_of_the_total: 0.0479532568651074,
|
|
31
|
-
// },
|
|
32
|
-
// {
|
|
33
|
-
// name: 'GA_Macon',
|
|
34
|
-
// pct_of_the_total: 0.0431507654834117,
|
|
35
|
-
// },
|
|
36
|
-
// {
|
|
37
|
-
// name: 'NC_Charlotte',
|
|
38
|
-
// pct_of_the_total: 0.034166792944838,
|
|
39
|
-
// },
|
|
40
|
-
// {
|
|
41
|
-
// name: 'AL_Montgomery',
|
|
42
|
-
// pct_of_the_total: 0.0298663023800594,
|
|
43
|
-
// },
|
|
44
|
-
// {
|
|
45
|
-
// name: 'TN_Memphis',
|
|
46
|
-
// pct_of_the_total: 0.0292140477651036,
|
|
47
|
-
// },
|
|
48
|
-
// {
|
|
49
|
-
// name: 'SC_Greenville',
|
|
50
|
-
// pct_of_the_total: 0.0288115667542858,
|
|
51
|
-
// },
|
|
52
|
-
// {
|
|
53
|
-
// name: 'SC_Columbia',
|
|
54
|
-
// pct_of_the_total: 0.0285805316472631,
|
|
55
|
-
// },
|
|
56
|
-
// {
|
|
57
|
-
// name: 'NC_Fayetteville',
|
|
58
|
-
// pct_of_the_total: 0.0279000448849207,
|
|
59
|
-
// },
|
|
60
|
-
// {
|
|
61
|
-
// name: 'SC_Spartanburg',
|
|
62
|
-
// pct_of_the_total: 0.0260196308313896,
|
|
63
|
-
// },
|
|
64
|
-
// {
|
|
65
|
-
// name: 'NC_Greensboro',
|
|
66
|
-
// pct_of_the_total: 0.0169521323221251,
|
|
67
|
-
// },
|
|
68
|
-
// {
|
|
69
|
-
// name: 'FL_Orlando',
|
|
70
|
-
// pct_of_the_total: 0.0167433815522564,
|
|
71
|
-
// },
|
|
72
|
-
// {
|
|
73
|
-
// name: 'FL_Tampa',
|
|
74
|
-
// pct_of_the_total: 0.0155513189530513,
|
|
75
|
-
// },
|
|
76
|
-
// {
|
|
77
|
-
// name: 'NC_Raleigh',
|
|
78
|
-
// pct_of_the_total: 0.0154308010765727,
|
|
79
|
-
// },
|
|
80
|
-
// {
|
|
81
|
-
// name: 'FL_Jacksonville',
|
|
82
|
-
// pct_of_the_total: 0.0152275224173022,
|
|
83
|
-
// },
|
|
84
|
-
// {
|
|
85
|
-
// name: 'GA_LaGrange',
|
|
86
|
-
// pct_of_the_total: 0.00867900369362145,
|
|
87
|
-
// },
|
|
88
|
-
// {
|
|
89
|
-
// name: 'GA_Augusta',
|
|
90
|
-
// pct_of_the_total: 0.0084582649800033,
|
|
91
|
-
// },
|
|
92
|
-
// {
|
|
93
|
-
// name: 'TX_San Antonio',
|
|
94
|
-
// pct_of_the_total: 0.00682971823492258,
|
|
95
|
-
// },
|
|
96
|
-
// {
|
|
97
|
-
// name: 'FL_North Port',
|
|
98
|
-
// pct_of_the_total: 0.00637954051173961,
|
|
99
|
-
// },
|
|
100
|
-
// {
|
|
101
|
-
// name: 'No Portfolio',
|
|
102
|
-
// pct_of_the_total: 0.00522734435854761,
|
|
103
|
-
// },
|
|
104
|
-
// ];
|
|
105
|
-
|
|
106
|
-
const useOnWindowResize = (
|
|
107
|
-
handler: { (): void },
|
|
108
|
-
initialWindowSize?: number
|
|
109
|
-
) => {
|
|
110
|
-
const [windowSize, setWindowSize] = useState<undefined | number>(
|
|
111
|
-
initialWindowSize
|
|
112
|
-
);
|
|
113
|
-
useEffect(() => {
|
|
114
|
-
const handleResize = () => {
|
|
115
|
-
setWindowSize(window.innerWidth);
|
|
116
|
-
handler();
|
|
117
|
-
};
|
|
118
|
-
handleResize();
|
|
119
|
-
window.addEventListener('resize', handleResize);
|
|
120
|
-
|
|
121
|
-
return () => window.removeEventListener('resize', handleResize);
|
|
122
|
-
}, [handler, windowSize]);
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
const ChartLegend = (categories: string[], colors: string[]) => {
|
|
126
|
-
const legendRef = useRef<HTMLDivElement>(null);
|
|
127
|
-
|
|
128
|
-
// useOnWindowResize(() => {
|
|
129
|
-
// const calculateHeight = (height: number | undefined) =>
|
|
130
|
-
// height
|
|
131
|
-
// ? Number(height) + 20 // 20px extra padding
|
|
132
|
-
// : 60; // default height
|
|
133
|
-
// setLegendHeight(calculateHeight(legendRef.current?.clientHeight));
|
|
134
|
-
// });
|
|
135
|
-
|
|
136
|
-
return (
|
|
137
|
-
<div ref={legendRef} className="qq-flex qq-items-center qq-justify-end">
|
|
138
|
-
<Legend
|
|
139
|
-
// @ts-ignore
|
|
140
|
-
categories={categories}
|
|
141
|
-
colors={colors}
|
|
142
|
-
/>
|
|
143
|
-
</div>
|
|
144
|
-
);
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
export type ValueFormatter = {
|
|
148
|
-
(value: number): string;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
const iconVariantValues = [
|
|
152
|
-
'simple',
|
|
153
|
-
'light',
|
|
154
|
-
'shadow',
|
|
155
|
-
'solid',
|
|
156
|
-
'outlined',
|
|
157
|
-
] as const;
|
|
158
|
-
|
|
159
|
-
export type IconVariant = (typeof iconVariantValues)[number];
|
|
160
|
-
|
|
161
|
-
export type HorizontalPosition = 'left' | 'right';
|
|
162
|
-
|
|
163
|
-
export type VerticalPosition = 'top' | 'bottom';
|
|
164
|
-
|
|
165
|
-
export type ButtonVariant = 'primary' | 'secondary' | 'light';
|
|
166
|
-
|
|
167
|
-
const deltaTypeValues = [
|
|
168
|
-
'increase',
|
|
169
|
-
'moderateIncrease',
|
|
170
|
-
'decrease',
|
|
171
|
-
'moderateDecrease',
|
|
172
|
-
'unchanged',
|
|
173
|
-
] as const;
|
|
174
|
-
|
|
175
|
-
export type DeltaType = (typeof deltaTypeValues)[number];
|
|
176
|
-
|
|
177
|
-
const sizeValues = ['xs', 'sm', 'md', 'lg', 'xl'] as const;
|
|
178
|
-
|
|
179
|
-
export type Size = (typeof sizeValues)[number];
|
|
180
|
-
|
|
181
|
-
const colorValues = [
|
|
182
|
-
'slate',
|
|
183
|
-
'gray',
|
|
184
|
-
'zinc',
|
|
185
|
-
'neutral',
|
|
186
|
-
'stone',
|
|
187
|
-
'red',
|
|
188
|
-
'orange',
|
|
189
|
-
'amber',
|
|
190
|
-
'yellow',
|
|
191
|
-
'lime',
|
|
192
|
-
'green',
|
|
193
|
-
'emerald',
|
|
194
|
-
'teal',
|
|
195
|
-
'cyan',
|
|
196
|
-
'sky',
|
|
197
|
-
'blue',
|
|
198
|
-
'indigo',
|
|
199
|
-
'violet',
|
|
200
|
-
'purple',
|
|
201
|
-
'fuchsia',
|
|
202
|
-
'pink',
|
|
203
|
-
'rose',
|
|
204
|
-
] as const;
|
|
205
|
-
|
|
206
|
-
export type Color = (typeof colorValues)[number];
|
|
207
|
-
|
|
208
|
-
const justifyContentValues = [
|
|
209
|
-
'start',
|
|
210
|
-
'end',
|
|
211
|
-
'center',
|
|
212
|
-
'between',
|
|
213
|
-
'around',
|
|
214
|
-
'evenly',
|
|
215
|
-
] as const;
|
|
216
|
-
export type JustifyContent = (typeof justifyContentValues)[number];
|
|
217
|
-
|
|
218
|
-
const alignItemsValues = [
|
|
219
|
-
'start',
|
|
220
|
-
'end',
|
|
221
|
-
'center',
|
|
222
|
-
'baseline',
|
|
223
|
-
'stretch',
|
|
224
|
-
] as const;
|
|
225
|
-
export type AlignItems = (typeof alignItemsValues)[number];
|
|
226
|
-
|
|
227
|
-
export type FlexDirection = 'row' | 'col' | 'row-reverse' | 'col-reverse';
|
|
228
|
-
|
|
229
|
-
export const defaultValueFormatter: ValueFormatter = (value: number) =>
|
|
230
|
-
(value * 1).toFixed(1) + '%';
|
|
231
|
-
|
|
232
|
-
export const sumNumericArray = (arr: number[]) =>
|
|
233
|
-
arr.reduce((prefixSum, num) => prefixSum + num, 0);
|
|
234
|
-
|
|
235
|
-
// export const parseData = (data: any[], colors: any[]) =>
|
|
236
|
-
// data.map((dataPoint: any, idx: number) => {
|
|
237
|
-
// const baseColor = idx < colors.length ? colors[idx] : BaseColors.Gray;
|
|
238
|
-
// const hexCode = hexColors[baseColor ?? BaseColors.Gray];
|
|
239
|
-
// return {
|
|
240
|
-
// ...dataPoint,
|
|
241
|
-
// color: colors[idx],
|
|
242
|
-
// fill: colors[idx],
|
|
243
|
-
// };
|
|
244
|
-
// });
|
|
245
|
-
|
|
246
|
-
// @ts-ignore
|
|
247
|
-
export const parseData = (data, colors, categoryKey, valueKey) => {
|
|
248
|
-
const maxItems = 20;
|
|
249
|
-
const slicedData = data.slice(0, maxItems);
|
|
250
|
-
|
|
251
|
-
let totalValue = slicedData.reduce(
|
|
252
|
-
(acc, dataPoint) => acc + Number(dataPoint[valueKey]),
|
|
253
|
-
0
|
|
254
|
-
);
|
|
255
|
-
|
|
256
|
-
if (totalValue !== 100) {
|
|
257
|
-
slicedData.forEach(dataPoint => {
|
|
258
|
-
dataPoint[valueKey] = (Number(dataPoint[valueKey]) * 100) / totalValue;
|
|
259
|
-
});
|
|
260
|
-
totalValue = 100;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
const parsedData = slicedData.map((dataPoint, idx) => {
|
|
264
|
-
const baseColor =
|
|
265
|
-
idx < colors.length ? colors[idx] : colors[colors.length - 1];
|
|
266
|
-
return {
|
|
267
|
-
...dataPoint,
|
|
268
|
-
color: baseColor,
|
|
269
|
-
fill: baseColor,
|
|
270
|
-
};
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
if (data.length > maxItems) {
|
|
274
|
-
const otherData = data.slice(maxItems);
|
|
275
|
-
const otherSum = otherData.reduce(
|
|
276
|
-
(acc, dataPoint) => acc + Number(dataPoint[valueKey]),
|
|
277
|
-
0
|
|
278
|
-
);
|
|
279
|
-
const otherColor = colors[colors.length - 1];
|
|
280
|
-
const normalizedOtherSum = (otherSum * 100) / totalValue;
|
|
281
|
-
parsedData.push({
|
|
282
|
-
[categoryKey]: 'Other',
|
|
283
|
-
[valueKey]: normalizedOtherSum,
|
|
284
|
-
color: otherColor,
|
|
285
|
-
fill: otherColor,
|
|
286
|
-
});
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
return parsedData;
|
|
290
|
-
};
|
|
291
|
-
|
|
292
|
-
const calculateDefaultLabel = (data: any[], category: string) =>
|
|
293
|
-
sumNumericArray(data.map(dataPoint => dataPoint[category]));
|
|
294
|
-
|
|
295
|
-
export const parseLabelInput = (
|
|
296
|
-
labelInput: string | undefined,
|
|
297
|
-
valueFormatter: ValueFormatter,
|
|
298
|
-
data: any[],
|
|
299
|
-
category: string
|
|
300
|
-
) =>
|
|
301
|
-
labelInput
|
|
302
|
-
? labelInput
|
|
303
|
-
: valueFormatter(calculateDefaultLabel(data, category));
|
|
304
|
-
|
|
305
|
-
export const ChartTooltipFrame = ({
|
|
306
|
-
children,
|
|
307
|
-
theme,
|
|
308
|
-
}: {
|
|
309
|
-
children: React.ReactNode;
|
|
310
|
-
}) => (
|
|
311
|
-
<div
|
|
312
|
-
style={{
|
|
313
|
-
borderStyle: 'solid',
|
|
314
|
-
borderColor: theme?.borderColor || '#E5E7EB',
|
|
315
|
-
borderWidth: 1,
|
|
316
|
-
background: theme?.backgroundColor || '#ffffff',
|
|
317
|
-
fontSize: theme?.fontSize || '14px',
|
|
318
|
-
borderRadius: '6px',
|
|
319
|
-
boxShadow:
|
|
320
|
-
'0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
|
|
321
|
-
}}
|
|
322
|
-
// style={{ transform: 'translateX(-120px)' }}
|
|
323
|
-
// className="qq-bg-white qq-text-sm qq-rounded-md qq-shadow-lg"
|
|
324
|
-
// className={twMerge(
|
|
325
|
-
// 'bg-white',
|
|
326
|
-
// 'font-normal',
|
|
327
|
-
// 'border-[12px]',
|
|
328
|
-
// 'border-[1px]',
|
|
329
|
-
// 'text-[#212121]'
|
|
330
|
-
// // boxShadow.lg
|
|
331
|
-
// )}
|
|
332
|
-
>
|
|
333
|
-
{children}
|
|
334
|
-
</div>
|
|
335
|
-
);
|
|
336
|
-
|
|
337
|
-
export interface ChartTooltipRowProps {
|
|
338
|
-
value: string;
|
|
339
|
-
name: string;
|
|
340
|
-
color: Color;
|
|
341
|
-
theme: any;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
export const ChartTooltipRow = ({
|
|
345
|
-
value,
|
|
346
|
-
name,
|
|
347
|
-
color,
|
|
348
|
-
theme,
|
|
349
|
-
}: ChartTooltipRowProps) => (
|
|
350
|
-
<div
|
|
351
|
-
style={{
|
|
352
|
-
display: 'flex',
|
|
353
|
-
alignItems: 'center',
|
|
354
|
-
justifyContent: 'space-between',
|
|
355
|
-
minWidth: 120,
|
|
356
|
-
// minHeight: 27,
|
|
357
|
-
// margin: '0 2rem',
|
|
358
|
-
}}
|
|
359
|
-
>
|
|
360
|
-
<div
|
|
361
|
-
style={{
|
|
362
|
-
display: 'flex',
|
|
363
|
-
alignItems: 'center',
|
|
364
|
-
justifyContent: 'space-between',
|
|
365
|
-
// margin: '0 0.5rem',
|
|
366
|
-
// minWidth: 120,
|
|
367
|
-
}}
|
|
368
|
-
>
|
|
369
|
-
<span
|
|
370
|
-
style={{
|
|
371
|
-
background: color,
|
|
372
|
-
borderWidth: 2,
|
|
373
|
-
borderStyle: 'solid',
|
|
374
|
-
borderColor: 'white',
|
|
375
|
-
height: '8px',
|
|
376
|
-
width: '8px',
|
|
377
|
-
boxShadow:
|
|
378
|
-
'0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
|
|
379
|
-
borderRadius: '9999px',
|
|
380
|
-
marginRight: 5,
|
|
381
|
-
}}
|
|
382
|
-
// className={twMerge(
|
|
383
|
-
// 'shrink-0',
|
|
384
|
-
// 'bg-black',
|
|
385
|
-
// 'bg-white',
|
|
386
|
-
// 'border-black',
|
|
387
|
-
// sizing.sm.height,
|
|
388
|
-
// sizing.sm.width,
|
|
389
|
-
// 'qq-h-3',
|
|
390
|
-
// 'qq-w-3',
|
|
391
|
-
// 'qq-shadow',
|
|
392
|
-
// 'qq-rounded-full'
|
|
393
|
-
// border.md.all,
|
|
394
|
-
// boxShadow.md
|
|
395
|
-
// )}
|
|
396
|
-
/>
|
|
397
|
-
<p
|
|
398
|
-
// className={twMerge(
|
|
399
|
-
// 'font-medium tabular-nums text-right whitespace-nowrap',
|
|
400
|
-
// 'text-[#212121] !important'
|
|
401
|
-
// )}
|
|
402
|
-
style={{
|
|
403
|
-
marginTop: 0,
|
|
404
|
-
marginBottom: 0,
|
|
405
|
-
fontFamily: theme?.fontFamily,
|
|
406
|
-
color: theme?.primaryTextColor,
|
|
407
|
-
paddingTop: 2,
|
|
408
|
-
paddingBottom: 2,
|
|
409
|
-
fontSize: theme?.fontSizeSmall || '14px',
|
|
410
|
-
fontWeight: theme?.fontWeightMedium || '500',
|
|
411
|
-
}}
|
|
412
|
-
// className="qq-font-medium qq-tabular-nums qq-text-right qq-whitespace-nowrap"
|
|
413
|
-
>
|
|
414
|
-
{value}
|
|
415
|
-
</p>
|
|
416
|
-
</div>
|
|
417
|
-
<p
|
|
418
|
-
style={{
|
|
419
|
-
marginTop: 0,
|
|
420
|
-
marginBottom: 0,
|
|
421
|
-
fontFamily: theme?.fontFamily,
|
|
422
|
-
color: theme?.secondaryTextColor,
|
|
423
|
-
whiteSpace: 'nowrap',
|
|
424
|
-
overflow: 'hidden',
|
|
425
|
-
textOverflow: 'ellipsis',
|
|
426
|
-
textAlign: 'right',
|
|
427
|
-
fontSize: theme?.fontSizeSmall || '14px',
|
|
428
|
-
fontWeight: theme?.fontWeightNormal || '400',
|
|
429
|
-
}}
|
|
430
|
-
// className={twMerge(
|
|
431
|
-
// 'qq-text-right qq-whitespace-nowrap'
|
|
432
|
-
// getColorClassNames(DEFAULT_COLOR, colorPalette.text).textColor,
|
|
433
|
-
// 'qq-text-gray-500'
|
|
434
|
-
// fontWeight.sm
|
|
435
|
-
// )}
|
|
436
|
-
>
|
|
437
|
-
{name}
|
|
438
|
-
</p>
|
|
439
|
-
</div>
|
|
440
|
-
);
|
|
441
|
-
|
|
442
|
-
export interface DonutChartTooltipProps {
|
|
443
|
-
active: boolean | undefined;
|
|
444
|
-
payload: any;
|
|
445
|
-
valueFormatter: ValueFormatter;
|
|
446
|
-
theme: any;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
export const DonutChartTooltip = ({
|
|
450
|
-
active,
|
|
451
|
-
payload,
|
|
452
|
-
valueFormatter,
|
|
453
|
-
theme,
|
|
454
|
-
}: DonutChartTooltipProps) => {
|
|
455
|
-
if (active && payload[0]) {
|
|
456
|
-
const payloadRow = payload[0];
|
|
457
|
-
return (
|
|
458
|
-
<ChartTooltipFrame theme={theme}>
|
|
459
|
-
<div
|
|
460
|
-
// style={{ transform: 'translateX(-120px)' }}
|
|
461
|
-
// className={twMerge('qq-px-4', 'qq-py-2')}
|
|
462
|
-
style={{
|
|
463
|
-
paddingLeft: '1rem',
|
|
464
|
-
paddingRight: '1rem',
|
|
465
|
-
paddingTop: '8px',
|
|
466
|
-
paddingBottom: '8px',
|
|
467
|
-
}}
|
|
468
|
-
>
|
|
469
|
-
<ChartTooltipRow
|
|
470
|
-
value={valueFormatter(payloadRow.value)}
|
|
471
|
-
name={payloadRow.name}
|
|
472
|
-
color={payloadRow.payload.color}
|
|
473
|
-
theme={theme}
|
|
474
|
-
/>
|
|
475
|
-
</div>
|
|
476
|
-
</ChartTooltipFrame>
|
|
477
|
-
);
|
|
478
|
-
}
|
|
479
|
-
return null;
|
|
480
|
-
};
|
|
481
|
-
|
|
482
|
-
type DonutChartVariant = 'donut' | 'pie';
|
|
483
|
-
|
|
484
|
-
export interface DonutChartProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
485
|
-
category?: string;
|
|
486
|
-
index?: string;
|
|
487
|
-
colors?: any[];
|
|
488
|
-
data: any[];
|
|
489
|
-
variant?: DonutChartVariant;
|
|
490
|
-
valueFormatter?: ValueFormatter;
|
|
491
|
-
label?: string;
|
|
492
|
-
showLabel?: boolean;
|
|
493
|
-
showAnimation?: boolean;
|
|
494
|
-
showTooltip?: boolean;
|
|
495
|
-
containerStyle?: CSSProperties;
|
|
496
|
-
}
|
|
497
|
-
|
|
498
|
-
// @ts-ignore
|
|
499
|
-
export function findComplementaryAndAnalogousColors(color1, color2) {
|
|
500
|
-
// Calculate the hue of the first color
|
|
501
|
-
const color1HSL = rgbToHsl(hexToRgb(color1));
|
|
502
|
-
const color2HSL = rgbToHsl(hexToRgb(color2));
|
|
503
|
-
const color1Hue = color1HSL.h;
|
|
504
|
-
|
|
505
|
-
// Calculate the complementary color of the first color
|
|
506
|
-
const complementaryHue = (color1Hue + 180) % 360;
|
|
507
|
-
const complementaryColor = hslToRgb({
|
|
508
|
-
h: complementaryHue,
|
|
509
|
-
s: color1HSL.s,
|
|
510
|
-
l: color1HSL.l,
|
|
511
|
-
});
|
|
512
|
-
|
|
513
|
-
// Find an analogous hue to the first color
|
|
514
|
-
const analogousHue1 = (color1Hue + 30) % 360;
|
|
515
|
-
const analogousHue2 = (color1Hue - 30 + 360) % 360;
|
|
516
|
-
|
|
517
|
-
// Convert the analogous hues back to RGB colors
|
|
518
|
-
const analogousColor1 = hslToRgb({
|
|
519
|
-
h: analogousHue1,
|
|
520
|
-
s: color1HSL.s,
|
|
521
|
-
l: color1HSL.l,
|
|
522
|
-
});
|
|
523
|
-
const analogousColor2 = hslToRgb({
|
|
524
|
-
h: analogousHue2,
|
|
525
|
-
s: color1HSL.s,
|
|
526
|
-
l: color1HSL.l,
|
|
527
|
-
});
|
|
528
|
-
|
|
529
|
-
// Calculate the average hue between the two colors
|
|
530
|
-
const avgHue = (color1HSL.h + color2HSL.h) / 2;
|
|
531
|
-
|
|
532
|
-
// Generate a new HSL object with the average hue and the same saturation and lightness as color1
|
|
533
|
-
const analogousHsl = { h: avgHue, s: color1HSL.s, l: color1HSL.l };
|
|
534
|
-
|
|
535
|
-
return [
|
|
536
|
-
color1,
|
|
537
|
-
color2,
|
|
538
|
-
rgbToHex(hslToRgb(analogousHsl)),
|
|
539
|
-
// rgbToHex(complementaryColor),
|
|
540
|
-
// rgbToHex(analogousColor1),
|
|
541
|
-
// rgbToHex(analogousColor2),
|
|
542
|
-
];
|
|
543
|
-
}
|
|
544
|
-
|
|
545
|
-
// @ts-ignore
|
|
546
|
-
function hexToRgb(hex) {
|
|
547
|
-
const r = parseInt(hex.substring(1, 3), 16);
|
|
548
|
-
const g = parseInt(hex.substring(3, 5), 16);
|
|
549
|
-
const b = parseInt(hex.substring(5, 7), 16);
|
|
550
|
-
return { r, g, b };
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
// @ts-ignore
|
|
554
|
-
function rgbToHex(rgb) {
|
|
555
|
-
const rHex = rgb.r.toString(16).padStart(2, '0');
|
|
556
|
-
const gHex = rgb.g.toString(16).padStart(2, '0');
|
|
557
|
-
const bHex = rgb.b.toString(16).padStart(2, '0');
|
|
558
|
-
return `#${rHex}${gHex}${bHex}`;
|
|
559
|
-
}
|
|
560
|
-
|
|
561
|
-
// @ts-ignore
|
|
562
|
-
function rgbToHsl(rgb) {
|
|
563
|
-
const r = rgb.r / 255;
|
|
564
|
-
const g = rgb.g / 255;
|
|
565
|
-
const b = rgb.b / 255;
|
|
566
|
-
|
|
567
|
-
const max = Math.max(r, g, b);
|
|
568
|
-
const min = Math.min(r, g, b);
|
|
569
|
-
|
|
570
|
-
let h = 0,
|
|
571
|
-
s = 0,
|
|
572
|
-
l = (max + min) / 2;
|
|
573
|
-
|
|
574
|
-
if (max !== min) {
|
|
575
|
-
let d = max - min;
|
|
576
|
-
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
|
|
577
|
-
|
|
578
|
-
switch (max) {
|
|
579
|
-
case r:
|
|
580
|
-
h = (g - b) / d + (g < b ? 6 : 0);
|
|
581
|
-
break;
|
|
582
|
-
case g:
|
|
583
|
-
h = (b - r) / d + 2;
|
|
584
|
-
break;
|
|
585
|
-
case b:
|
|
586
|
-
h = (r - g) / d + 4;
|
|
587
|
-
break;
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
h /= 6;
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
return { h: h * 360, s: s * 100, l: l * 100 };
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
// @ts-ignore
|
|
597
|
-
function hslToRgb(hsl) {
|
|
598
|
-
const h = hsl.h / 360;
|
|
599
|
-
const s = hsl.s / 100;
|
|
600
|
-
const l = hsl.l / 100;
|
|
601
|
-
|
|
602
|
-
let r, g, b;
|
|
603
|
-
|
|
604
|
-
if (s === 0) {
|
|
605
|
-
r = g = b = l;
|
|
606
|
-
} else {
|
|
607
|
-
// @ts-ignore
|
|
608
|
-
const hue2rgb = (p, q, t) => {
|
|
609
|
-
if (t < 0) t += 1;
|
|
610
|
-
if (t > 1) t -= 1;
|
|
611
|
-
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
612
|
-
if (t < 1 / 2) return q;
|
|
613
|
-
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
614
|
-
return p;
|
|
615
|
-
};
|
|
616
|
-
|
|
617
|
-
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
618
|
-
const p = 2 * l - q;
|
|
619
|
-
r = hue2rgb(p, q, h + 1 / 3);
|
|
620
|
-
g = hue2rgb(p, q, h);
|
|
621
|
-
b = hue2rgb(p, q, h - 1 / 3);
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
return {
|
|
625
|
-
r: Math.round(r * 255),
|
|
626
|
-
g: Math.round(g * 255),
|
|
627
|
-
b: Math.round(b * 255),
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
// @ts-ignore
|
|
632
|
-
function generateColorGradientSteps(n, colors) {
|
|
633
|
-
const numColors = colors.length;
|
|
634
|
-
|
|
635
|
-
// If there are fewer than two colors, return the original array
|
|
636
|
-
if (numColors < 2) {
|
|
637
|
-
return colors;
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
// Initialize the output array with the first color
|
|
641
|
-
const output = [colors[0]];
|
|
642
|
-
|
|
643
|
-
// Calculate the number of gradient steps between each pair of colors
|
|
644
|
-
const stepsPerPair = Math.floor(n / (numColors - 1));
|
|
645
|
-
|
|
646
|
-
// Generate the gradient steps for each pair of colors
|
|
647
|
-
for (let i = 1; i < numColors; i++) {
|
|
648
|
-
const color1 = colors[i - 1];
|
|
649
|
-
const color2 = colors[i];
|
|
650
|
-
const gradientSteps = generateGradientSteps(color1, color2, stepsPerPair);
|
|
651
|
-
output.push(...gradientSteps);
|
|
652
|
-
}
|
|
653
|
-
|
|
654
|
-
// If there are remaining steps, add the last color as a stopgap measure
|
|
655
|
-
while (output.length < n) {
|
|
656
|
-
output.push(colors[numColors - 1]);
|
|
657
|
-
}
|
|
658
|
-
|
|
659
|
-
return output;
|
|
660
|
-
}
|
|
661
|
-
|
|
662
|
-
//@ts-ignore
|
|
663
|
-
function generateGradientSteps(color1, color2, n) {
|
|
664
|
-
// Convert the colors to RGB objects
|
|
665
|
-
const rgb1 = hexToRgb(color1);
|
|
666
|
-
const rgb2 = hexToRgb(color2);
|
|
667
|
-
|
|
668
|
-
// Calculate the RGB color difference between the two colors
|
|
669
|
-
const diffR = rgb2.r - rgb1.r;
|
|
670
|
-
const diffG = rgb2.g - rgb1.g;
|
|
671
|
-
const diffB = rgb2.b - rgb1.b;
|
|
672
|
-
|
|
673
|
-
// Calculate the RGB gradient step size between the two colors
|
|
674
|
-
const stepR = diffR / (n + 1);
|
|
675
|
-
const stepG = diffG / (n + 1);
|
|
676
|
-
const stepB = diffB / (n + 1);
|
|
677
|
-
|
|
678
|
-
// Generate the RGB gradient steps
|
|
679
|
-
const gradientSteps = [];
|
|
680
|
-
for (let i = 1; i <= n; i++) {
|
|
681
|
-
const r = Math.round(rgb1.r + stepR * i);
|
|
682
|
-
const g = Math.round(rgb1.g + stepG * i);
|
|
683
|
-
const b = Math.round(rgb1.b + stepB * i);
|
|
684
|
-
gradientSteps.push(rgbToHex({ r, g, b }));
|
|
685
|
-
}
|
|
686
|
-
|
|
687
|
-
return gradientSteps;
|
|
688
|
-
}
|
|
689
|
-
|
|
690
|
-
const PieChartWrapper = React.forwardRef<HTMLDivElement, DonutChartProps>(
|
|
691
|
-
(props, ref) => {
|
|
692
|
-
const {
|
|
693
|
-
category = 'pct_of_the_total',
|
|
694
|
-
index = 'status',
|
|
695
|
-
data,
|
|
696
|
-
colors = [],
|
|
697
|
-
variant = 'donut',
|
|
698
|
-
valueFormatter = defaultValueFormatter,
|
|
699
|
-
label,
|
|
700
|
-
showLabel = true,
|
|
701
|
-
showAnimation = true,
|
|
702
|
-
showTooltip = true,
|
|
703
|
-
className,
|
|
704
|
-
containerStyle,
|
|
705
|
-
theme,
|
|
706
|
-
...other
|
|
707
|
-
} = props;
|
|
708
|
-
const isDonut = variant == 'donut';
|
|
709
|
-
|
|
710
|
-
const parsedLabelInput = parseLabelInput(
|
|
711
|
-
label,
|
|
712
|
-
valueFormatter,
|
|
713
|
-
data,
|
|
714
|
-
category
|
|
715
|
-
);
|
|
716
|
-
|
|
717
|
-
const newColors = generateColorGradientSteps(
|
|
718
|
-
data.length,
|
|
719
|
-
findComplementaryAndAnalogousColors(colors[0], colors[1])
|
|
720
|
-
);
|
|
721
|
-
|
|
722
|
-
return (
|
|
723
|
-
<div
|
|
724
|
-
ref={ref}
|
|
725
|
-
style={{
|
|
726
|
-
...containerStyle,
|
|
727
|
-
width: '100%',
|
|
728
|
-
// height: '100%',
|
|
729
|
-
display: 'flex',
|
|
730
|
-
flexDirection: 'row',
|
|
731
|
-
alignItems: 'center',
|
|
732
|
-
boxSizing: 'content-box',
|
|
733
|
-
}}
|
|
734
|
-
// className={twMerge(
|
|
735
|
-
// 'w-full h-full flex flex-row items-center',
|
|
736
|
-
// className
|
|
737
|
-
// )}
|
|
738
|
-
{...other}
|
|
739
|
-
>
|
|
740
|
-
<ResponsiveContainer width="100%" height="100%">
|
|
741
|
-
<PieChart>
|
|
742
|
-
<Pie
|
|
743
|
-
// style={{ transform: 'translateX(-120px)' }}
|
|
744
|
-
data={parseData(
|
|
745
|
-
data,
|
|
746
|
-
colors.length >= data.length
|
|
747
|
-
? colors
|
|
748
|
-
: generateColorGradientSteps(Math.min(21, data.length), [
|
|
749
|
-
...findComplementaryAndAnalogousColors(
|
|
750
|
-
colors[0],
|
|
751
|
-
colors[1]
|
|
752
|
-
),
|
|
753
|
-
...colors.slice(2),
|
|
754
|
-
]),
|
|
755
|
-
index,
|
|
756
|
-
category
|
|
757
|
-
)}
|
|
758
|
-
cx="50%"
|
|
759
|
-
cy="50%"
|
|
760
|
-
startAngle={90}
|
|
761
|
-
endAngle={-270}
|
|
762
|
-
innerRadius={isDonut ? '70%' : '0%'}
|
|
763
|
-
outerRadius="100%"
|
|
764
|
-
paddingAngle={0}
|
|
765
|
-
dataKey={category}
|
|
766
|
-
nameKey={index}
|
|
767
|
-
isAnimationActive={true}
|
|
768
|
-
/>
|
|
769
|
-
{/* <Legend
|
|
770
|
-
layout="vertical"
|
|
771
|
-
align="center"
|
|
772
|
-
verticalAlign="middle"
|
|
773
|
-
wrapperStyle={{
|
|
774
|
-
paddingLeft: '20px',
|
|
775
|
-
transform: 'translateX(120px)',
|
|
776
|
-
}}
|
|
777
|
-
content={({ payload }) => (
|
|
778
|
-
<Legend2 payload={payload} colors={newColors} />
|
|
779
|
-
)}
|
|
780
|
-
/> */}
|
|
781
|
-
<Tooltip
|
|
782
|
-
wrapperStyle={{
|
|
783
|
-
outline: 'none',
|
|
784
|
-
}}
|
|
785
|
-
content={({ active, payload }) => (
|
|
786
|
-
<DonutChartTooltip
|
|
787
|
-
active={active}
|
|
788
|
-
payload={payload}
|
|
789
|
-
valueFormatter={valueFormatter}
|
|
790
|
-
theme={theme}
|
|
791
|
-
/>
|
|
792
|
-
)}
|
|
793
|
-
/>
|
|
794
|
-
</PieChart>
|
|
795
|
-
</ResponsiveContainer>
|
|
796
|
-
</div>
|
|
797
|
-
);
|
|
798
|
-
}
|
|
799
|
-
);
|
|
800
|
-
|
|
801
|
-
function Legend2({ payload, colors }: { payload: any; colors: string[] }) {
|
|
802
|
-
return (
|
|
803
|
-
<div
|
|
804
|
-
// className="flex flex-col min-w-[130px] max-w-[130px] w-full"
|
|
805
|
-
>
|
|
806
|
-
{/* @ts-ignore */}
|
|
807
|
-
{payload.map((item, idx) => {
|
|
808
|
-
if (idx > 9) {
|
|
809
|
-
return null;
|
|
810
|
-
}
|
|
811
|
-
return (
|
|
812
|
-
<div
|
|
813
|
-
key={item.value}
|
|
814
|
-
// className="flex flex-row items-center min-w-[130px] max-w-[130px]"
|
|
815
|
-
>
|
|
816
|
-
<div
|
|
817
|
-
style={{
|
|
818
|
-
height: 8,
|
|
819
|
-
width: 8,
|
|
820
|
-
borderRadius: 8,
|
|
821
|
-
background: colors[idx],
|
|
822
|
-
marginRight: 8,
|
|
823
|
-
marginTop: 2,
|
|
824
|
-
}}
|
|
825
|
-
/>
|
|
826
|
-
<div
|
|
827
|
-
style={{
|
|
828
|
-
whiteSpace: 'nowrap',
|
|
829
|
-
overflow: 'hidden',
|
|
830
|
-
textOverflow: 'ellipsis',
|
|
831
|
-
display: 'block',
|
|
832
|
-
maxWidth: 120,
|
|
833
|
-
}}
|
|
834
|
-
// className="qq-text-sm qq-text-gray-600 qq-whitespace-nowrap qq-overflow-hidden qq-overflow-ellipsis qq-text-sm qq-font-normal"
|
|
835
|
-
>
|
|
836
|
-
{item.value}
|
|
837
|
-
</div>
|
|
838
|
-
</div>
|
|
839
|
-
);
|
|
840
|
-
})}
|
|
841
|
-
</div>
|
|
842
|
-
);
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
export default PieChartWrapper;
|