@codecademy/gamut 67.6.4 → 67.6.5-alpha.263bae.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/BarChart/BarChartProvider.d.ts +19 -0
- package/dist/BarChart/BarChartProvider.js +31 -0
- package/dist/BarChart/BarRow/elements.d.ts +713 -0
- package/dist/BarChart/BarRow/elements.js +89 -0
- package/dist/BarChart/BarRow/index.d.ts +26 -0
- package/dist/BarChart/BarRow/index.js +254 -0
- package/dist/BarChart/GENERIC_EXAMPLE.d.ts +14 -0
- package/dist/BarChart/GENERIC_EXAMPLE.js +333 -0
- package/dist/BarChart/index.d.ts +4 -0
- package/dist/BarChart/index.js +158 -0
- package/dist/BarChart/layout/GridLines.d.ts +7 -0
- package/dist/BarChart/layout/GridLines.js +78 -0
- package/dist/BarChart/layout/ScaleChartHeader.d.ts +10 -0
- package/dist/BarChart/layout/ScaleChartHeader.js +89 -0
- package/dist/BarChart/layout/VerticalSpacer.d.ts +6 -0
- package/dist/BarChart/layout/VerticalSpacer.js +56 -0
- package/dist/BarChart/shared/elements.d.ts +7 -0
- package/dist/BarChart/shared/elements.js +12 -0
- package/dist/BarChart/shared/styles.d.ts +4 -0
- package/dist/BarChart/shared/styles.js +4 -0
- package/dist/BarChart/shared/translations.d.ts +17 -0
- package/dist/BarChart/shared/translations.js +16 -0
- package/dist/BarChart/shared/types.d.ts +88 -0
- package/dist/BarChart/shared/types.js +1 -0
- package/dist/BarChart/utils/hooks.d.ts +93 -0
- package/dist/BarChart/utils/hooks.js +301 -0
- package/dist/BarChart/utils/index.d.ts +86 -0
- package/dist/BarChart/utils/index.js +165 -0
- package/dist/ConnectedForm/utils.d.ts +1 -1
- package/dist/Form/SelectDropdown/styles.d.ts +1 -1
- package/dist/Form/elements/Form.d.ts +1 -1
- package/dist/Form/elements/FormGroupLabel.js +2 -2
- package/dist/Form/inputs/Select.js +6 -5
- package/dist/List/elements.d.ts +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { useColorModes } from '@codecademy/gamut-styles';
|
|
2
|
+
import { getContrast } from 'polished';
|
|
3
|
+
import { useCallback, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
4
|
+
import { BarChartContext } from '../BarChartProvider';
|
|
5
|
+
import { calculatePositionPercent, getLabel, sortBars } from './index';
|
|
6
|
+
const defaultStyleConfig = {
|
|
7
|
+
textColor: 'text',
|
|
8
|
+
foregroundBarColor: 'feedback-warning',
|
|
9
|
+
backgroundBarColor: 'background-primary',
|
|
10
|
+
seriesOneLabel: 'text-secondary',
|
|
11
|
+
seriesTwoLabel: 'primary'
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Hook that calculates label positions for a given range and count
|
|
16
|
+
* Returns an array of { value, positionPercent } objects
|
|
17
|
+
*/
|
|
18
|
+
export const useLabelPositions = ({
|
|
19
|
+
min,
|
|
20
|
+
max,
|
|
21
|
+
count
|
|
22
|
+
}) => {
|
|
23
|
+
return useMemo(() => Array.from({
|
|
24
|
+
length: count
|
|
25
|
+
}, (_, i) => {
|
|
26
|
+
const value = getLabel({
|
|
27
|
+
labelCount: count,
|
|
28
|
+
labelIndex: i,
|
|
29
|
+
min,
|
|
30
|
+
max
|
|
31
|
+
});
|
|
32
|
+
const positionPercent = calculatePositionPercent({
|
|
33
|
+
value,
|
|
34
|
+
min,
|
|
35
|
+
max
|
|
36
|
+
});
|
|
37
|
+
return {
|
|
38
|
+
value,
|
|
39
|
+
positionPercent
|
|
40
|
+
};
|
|
41
|
+
}), [min, max, count]);
|
|
42
|
+
};
|
|
43
|
+
export const useBarChartContext = () => {
|
|
44
|
+
return useContext(BarChartContext);
|
|
45
|
+
};
|
|
46
|
+
export const useBarChart = ({
|
|
47
|
+
minRange,
|
|
48
|
+
maxRange,
|
|
49
|
+
xScale,
|
|
50
|
+
unit = '',
|
|
51
|
+
styleConfig,
|
|
52
|
+
animate = false,
|
|
53
|
+
barCount = 0,
|
|
54
|
+
translations
|
|
55
|
+
}) => {
|
|
56
|
+
const [widestLeftLabelWidth, setWidestLeftLabelWidthState] = useState(null);
|
|
57
|
+
const [widestRightLabelWidth, setWidestRightLabelWidthState] = useState(null);
|
|
58
|
+
const [isMeasuring, setIsMeasuring] = useState(true);
|
|
59
|
+
const measuredCountRef = useRef(0);
|
|
60
|
+
const maxLeftWidthRef = useRef(0);
|
|
61
|
+
const maxRightWidthRef = useRef(0);
|
|
62
|
+
const setWidestLeftLabelWidth = useCallback(width => {
|
|
63
|
+
if (width > maxLeftWidthRef.current) {
|
|
64
|
+
maxLeftWidthRef.current = width;
|
|
65
|
+
setWidestLeftLabelWidthState(width);
|
|
66
|
+
}
|
|
67
|
+
measuredCountRef.current += 1;
|
|
68
|
+
// Only stop measuring when we've received measurements from all bars
|
|
69
|
+
if (measuredCountRef.current >= barCount * 2 && barCount > 0) {
|
|
70
|
+
setIsMeasuring(false);
|
|
71
|
+
}
|
|
72
|
+
}, [barCount]);
|
|
73
|
+
const setWidestRightLabelWidth = useCallback(width => {
|
|
74
|
+
if (width > maxRightWidthRef.current) {
|
|
75
|
+
maxRightWidthRef.current = width;
|
|
76
|
+
setWidestRightLabelWidthState(width);
|
|
77
|
+
}
|
|
78
|
+
measuredCountRef.current += 1;
|
|
79
|
+
// Only stop measuring when we've received measurements from all bars (left + right)
|
|
80
|
+
if (measuredCountRef.current >= barCount * 2 && barCount > 0) {
|
|
81
|
+
setIsMeasuring(false);
|
|
82
|
+
}
|
|
83
|
+
}, [barCount]);
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (barCount > 0) {
|
|
86
|
+
measuredCountRef.current = 0;
|
|
87
|
+
maxLeftWidthRef.current = 0;
|
|
88
|
+
maxRightWidthRef.current = 0;
|
|
89
|
+
setIsMeasuring(true);
|
|
90
|
+
}
|
|
91
|
+
}, [barCount]);
|
|
92
|
+
return useMemo(() => ({
|
|
93
|
+
minRange,
|
|
94
|
+
maxRange,
|
|
95
|
+
xScale: xScale ?? Math.ceil((maxRange - minRange) / 5),
|
|
96
|
+
unit,
|
|
97
|
+
styleConfig: {
|
|
98
|
+
...defaultStyleConfig,
|
|
99
|
+
...styleConfig
|
|
100
|
+
},
|
|
101
|
+
animate,
|
|
102
|
+
widestLeftLabelWidth,
|
|
103
|
+
setWidestLeftLabelWidth,
|
|
104
|
+
widestRightLabelWidth,
|
|
105
|
+
setWidestRightLabelWidth,
|
|
106
|
+
isMeasuring,
|
|
107
|
+
translations
|
|
108
|
+
}), [minRange, maxRange, xScale, unit, styleConfig, animate, widestLeftLabelWidth, setWidestLeftLabelWidth, widestRightLabelWidth, setWidestRightLabelWidth, isMeasuring, translations]);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Checks if a color is a color alias (exists in the color mode shape)
|
|
113
|
+
*/
|
|
114
|
+
const isColorAlias = (mode, color) => Object.keys(mode).includes(color);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Hook that returns a function to get the highest contrast border color
|
|
118
|
+
* (white or navy-900) for a given background color.
|
|
119
|
+
*
|
|
120
|
+
* Similar to the Background component, this resolves color aliases and
|
|
121
|
+
* compares contrast ratios to determine the best border color.
|
|
122
|
+
*
|
|
123
|
+
* @returns A function that takes a background color and returns either 'white' or 'navy-900'
|
|
124
|
+
*/
|
|
125
|
+
export const useBarBorderColor = () => {
|
|
126
|
+
const [, activeColors,, getColorValue] = useColorModes();
|
|
127
|
+
const getBorderColor = useCallback(bg => {
|
|
128
|
+
/** If a color alias was used then look up the true color key from the active mode */
|
|
129
|
+
const trueColor = isColorAlias(activeColors, bg) ? activeColors[bg] : bg;
|
|
130
|
+
const backgroundColor = getColorValue(trueColor);
|
|
131
|
+
const whiteContrast = getContrast(getColorValue('white'), backgroundColor);
|
|
132
|
+
const navyContrast = getContrast(getColorValue('navy-900'), backgroundColor);
|
|
133
|
+
return whiteContrast > navyContrast ? 'white' : 'navy-900';
|
|
134
|
+
}, [activeColors, getColorValue]);
|
|
135
|
+
return getBorderColor;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Generic hook for measuring element width and reporting to a callback.
|
|
140
|
+
* Used internally by useMeasureLeftLabelWidth and useMeasureRightLabelWidth.
|
|
141
|
+
*/
|
|
142
|
+
const useMeasureWidth = ({
|
|
143
|
+
ref,
|
|
144
|
+
onMeasure,
|
|
145
|
+
isMeasuring
|
|
146
|
+
}) => {
|
|
147
|
+
const hasMeasuredRef = useRef(false);
|
|
148
|
+
|
|
149
|
+
// Reset measurement flag when a new measurement cycle starts
|
|
150
|
+
const prevIsMeasuringRef = useRef(isMeasuring);
|
|
151
|
+
useEffect(() => {
|
|
152
|
+
if (isMeasuring && !prevIsMeasuringRef.current) {
|
|
153
|
+
// New measurement cycle started
|
|
154
|
+
hasMeasuredRef.current = false;
|
|
155
|
+
}
|
|
156
|
+
prevIsMeasuringRef.current = isMeasuring;
|
|
157
|
+
}, [isMeasuring]);
|
|
158
|
+
useLayoutEffect(() => {
|
|
159
|
+
if (!ref.current || hasMeasuredRef.current || !isMeasuring) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const element = ref.current;
|
|
163
|
+
const width = element?.getBoundingClientRect()?.width;
|
|
164
|
+
if (width > 0) {
|
|
165
|
+
onMeasure(width);
|
|
166
|
+
hasMeasuredRef.current = true;
|
|
167
|
+
}
|
|
168
|
+
}, [ref, onMeasure, isMeasuring]);
|
|
169
|
+
};
|
|
170
|
+
export const useMeasureLeftLabelWidth = ({
|
|
171
|
+
ref
|
|
172
|
+
}) => {
|
|
173
|
+
const {
|
|
174
|
+
setWidestLeftLabelWidth,
|
|
175
|
+
isMeasuring
|
|
176
|
+
} = useBarChartContext();
|
|
177
|
+
useMeasureWidth({
|
|
178
|
+
ref,
|
|
179
|
+
onMeasure: setWidestLeftLabelWidth,
|
|
180
|
+
isMeasuring
|
|
181
|
+
});
|
|
182
|
+
};
|
|
183
|
+
export const useMeasureRightLabelWidth = ({
|
|
184
|
+
ref
|
|
185
|
+
}) => {
|
|
186
|
+
const {
|
|
187
|
+
setWidestRightLabelWidth,
|
|
188
|
+
isMeasuring
|
|
189
|
+
} = useBarChartContext();
|
|
190
|
+
useMeasureWidth({
|
|
191
|
+
ref,
|
|
192
|
+
onMeasure: setWidestRightLabelWidth,
|
|
193
|
+
isMeasuring
|
|
194
|
+
});
|
|
195
|
+
};
|
|
196
|
+
/**
|
|
197
|
+
* Hook that manages bar sorting state and provides memoized sorted bars.
|
|
198
|
+
* Supports predefined sort options (via string literals) and custom sort functions.
|
|
199
|
+
* Only returns selectProps if sortFns is provided.
|
|
200
|
+
*/
|
|
201
|
+
export const useBarChartSort = ({
|
|
202
|
+
bars,
|
|
203
|
+
sortFns,
|
|
204
|
+
translations
|
|
205
|
+
}) => {
|
|
206
|
+
// Build options map and custom sort map from sortFns array
|
|
207
|
+
const {
|
|
208
|
+
allSortOptions,
|
|
209
|
+
customSortMap,
|
|
210
|
+
defaultSortValue
|
|
211
|
+
} = useMemo(() => {
|
|
212
|
+
if (!sortFns || sortFns.length === 0) {
|
|
213
|
+
return {
|
|
214
|
+
allSortOptions: null,
|
|
215
|
+
customSortMap: new Map(),
|
|
216
|
+
defaultSortValue: 'none'
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
const options = {};
|
|
220
|
+
const customMap = new Map();
|
|
221
|
+
const availableValues = [];
|
|
222
|
+
sortFns.forEach(item => {
|
|
223
|
+
if (typeof item === 'string') {
|
|
224
|
+
if (item === 'alphabetically') {
|
|
225
|
+
options['label-asc'] = translations.sortOptions.labelAsc;
|
|
226
|
+
options['label-desc'] = translations.sortOptions.labelDesc;
|
|
227
|
+
availableValues.push('label-asc', 'label-desc');
|
|
228
|
+
} else if (item === 'numerically') {
|
|
229
|
+
options['value-asc'] = translations.sortOptions.valueAsc;
|
|
230
|
+
options['value-desc'] = translations.sortOptions.valueDesc;
|
|
231
|
+
availableValues.push('value-asc', 'value-desc');
|
|
232
|
+
} else if (item === 'none') {
|
|
233
|
+
options.none = translations.sortOptions.none;
|
|
234
|
+
availableValues.push('none');
|
|
235
|
+
}
|
|
236
|
+
} else {
|
|
237
|
+
// CustomSortOption
|
|
238
|
+
options[item.value] = item.label;
|
|
239
|
+
customMap.set(item.value, item.sortFn);
|
|
240
|
+
availableValues.push(item.value);
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Default to "none" if available, otherwise first option
|
|
245
|
+
const defaultVal = availableValues.includes('none') ? 'none' : availableValues[0] || 'none';
|
|
246
|
+
return {
|
|
247
|
+
allSortOptions: options,
|
|
248
|
+
customSortMap: customMap,
|
|
249
|
+
defaultSortValue: defaultVal
|
|
250
|
+
};
|
|
251
|
+
}, [sortFns, translations]);
|
|
252
|
+
const [sortValue, setSortValue] = useState(defaultSortValue);
|
|
253
|
+
|
|
254
|
+
// Update sortValue when defaultSortValue changes (e.g., when sortFns changes)
|
|
255
|
+
useEffect(() => {
|
|
256
|
+
setSortValue(defaultSortValue);
|
|
257
|
+
}, [defaultSortValue]);
|
|
258
|
+
const sortedBars = useMemo(() => {
|
|
259
|
+
// Check if current selection is a custom sort function
|
|
260
|
+
const customSortFn = customSortMap.get(sortValue);
|
|
261
|
+
if (customSortFn) {
|
|
262
|
+
return customSortFn([...bars]);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Otherwise use predefined sort options
|
|
266
|
+
if (sortValue === 'none') {
|
|
267
|
+
return bars;
|
|
268
|
+
}
|
|
269
|
+
const [sortBy, order] = sortValue.split('-');
|
|
270
|
+
const sortByValue = sortBy;
|
|
271
|
+
const orderValue = order === 'desc' ? 'descending' : 'ascending';
|
|
272
|
+
return sortBars({
|
|
273
|
+
bars: bars,
|
|
274
|
+
sortBy: sortByValue,
|
|
275
|
+
order: orderValue
|
|
276
|
+
});
|
|
277
|
+
}, [bars, sortValue, customSortMap]);
|
|
278
|
+
const onSortChange = useCallback(value => {
|
|
279
|
+
setSortValue(value);
|
|
280
|
+
}, []);
|
|
281
|
+
const selectId = useRef(`bar-chart-sort-${Math.random().toString(36).slice(2, 11)}`);
|
|
282
|
+
const selectProps = useMemo(() => {
|
|
283
|
+
if (!allSortOptions) {
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
options: allSortOptions,
|
|
288
|
+
value: sortValue,
|
|
289
|
+
onChange: e => {
|
|
290
|
+
onSortChange(e.target.value);
|
|
291
|
+
},
|
|
292
|
+
id: selectId.current
|
|
293
|
+
};
|
|
294
|
+
}, [sortValue, onSortChange, allSortOptions]);
|
|
295
|
+
return {
|
|
296
|
+
sortedBars,
|
|
297
|
+
sortValue,
|
|
298
|
+
onSortChange,
|
|
299
|
+
selectProps
|
|
300
|
+
};
|
|
301
|
+
};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { BarChartTranslations } from '../shared/translations';
|
|
2
|
+
import { BarChartRange, BarChartUnit, BarProps } from '../shared/types';
|
|
3
|
+
export declare const numDigits: ({ num }: {
|
|
4
|
+
num: number;
|
|
5
|
+
}) => number;
|
|
6
|
+
export declare const columnBaseSize: ({ experience }: {
|
|
7
|
+
experience?: number | undefined;
|
|
8
|
+
}) => {
|
|
9
|
+
sm: number;
|
|
10
|
+
md: number;
|
|
11
|
+
lg: number;
|
|
12
|
+
xl: number;
|
|
13
|
+
};
|
|
14
|
+
export declare const calculatePercent: ({ value, total, }: {
|
|
15
|
+
value: number;
|
|
16
|
+
total: number;
|
|
17
|
+
}) => number;
|
|
18
|
+
export declare const calculateBarWidth: ({ value, minRange, maxRange, }: {
|
|
19
|
+
value: number;
|
|
20
|
+
} & BarChartRange) => number;
|
|
21
|
+
/**
|
|
22
|
+
* Calculate tick spacing and nice minimum and maximum data points on the axis.
|
|
23
|
+
*/
|
|
24
|
+
export declare const calculateTicksAndRange: ({ maxTicks, min, max, }: {
|
|
25
|
+
maxTicks: number;
|
|
26
|
+
} & {
|
|
27
|
+
min: BarChartRange['minRange'];
|
|
28
|
+
max: BarChartRange['maxRange'];
|
|
29
|
+
}) => [number, number, number];
|
|
30
|
+
/**
|
|
31
|
+
* Returns a "nice" number approximately equal to range
|
|
32
|
+
* Rounds the number if round = true
|
|
33
|
+
* Takes the ceiling if round = false.
|
|
34
|
+
* A nice number is a simple decimal number, for example if a number is 1234, a nice number would be 1000 or 2000.
|
|
35
|
+
*/
|
|
36
|
+
export declare const niceNum: ({ range, roundDown, }: {
|
|
37
|
+
range: number;
|
|
38
|
+
roundDown: boolean;
|
|
39
|
+
}) => number;
|
|
40
|
+
export declare const getPercentDiff: ({ v1, v2 }: {
|
|
41
|
+
v1: number;
|
|
42
|
+
v2: number;
|
|
43
|
+
}) => number;
|
|
44
|
+
export declare const formatNumberUS: ({ num, locale, }: {
|
|
45
|
+
num: number;
|
|
46
|
+
locale?: string | undefined;
|
|
47
|
+
}) => string;
|
|
48
|
+
export declare const formatNumberUSCompact: ({ num, locale, }: {
|
|
49
|
+
num: number;
|
|
50
|
+
locale?: string | undefined;
|
|
51
|
+
}) => string;
|
|
52
|
+
/**
|
|
53
|
+
* Sort bars based on sortBy and order configuration
|
|
54
|
+
*/
|
|
55
|
+
export declare const sortBars: <T extends BarProps>({ bars, sortBy, order, }: {
|
|
56
|
+
bars: T[];
|
|
57
|
+
sortBy: 'label' | 'value' | 'none';
|
|
58
|
+
order: 'ascending' | 'descending';
|
|
59
|
+
}) => T[];
|
|
60
|
+
/**
|
|
61
|
+
* Generates an accessible summary of the bar values
|
|
62
|
+
*/
|
|
63
|
+
export declare const getValuesSummary: ({ isInteractive, seriesOneValue, seriesTwoValue, unit, yLabel, translations, }: Pick<BarProps, "yLabel" | "seriesOneValue" | "seriesTwoValue"> & Required<Pick<BarChartUnit, "unit">> & {
|
|
64
|
+
isInteractive: boolean;
|
|
65
|
+
translations: BarChartTranslations;
|
|
66
|
+
}) => string;
|
|
67
|
+
/**
|
|
68
|
+
* Calculates the value for a given label position
|
|
69
|
+
*/
|
|
70
|
+
export declare const getLabel: ({ labelCount, labelIndex, min, max, }: {
|
|
71
|
+
labelCount: number;
|
|
72
|
+
labelIndex: number;
|
|
73
|
+
} & {
|
|
74
|
+
min: BarChartRange['minRange'];
|
|
75
|
+
max: BarChartRange['maxRange'];
|
|
76
|
+
}) => number;
|
|
77
|
+
/**
|
|
78
|
+
* Calculates the percentage position for a given value within a range
|
|
79
|
+
* Returns a value between 0 and 100 representing the position percentage
|
|
80
|
+
*/
|
|
81
|
+
export declare const calculatePositionPercent: ({ value, min, max, }: {
|
|
82
|
+
value: number;
|
|
83
|
+
} & {
|
|
84
|
+
min: BarChartRange['minRange'];
|
|
85
|
+
max: BarChartRange['maxRange'];
|
|
86
|
+
}) => number;
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
export const numDigits = ({
|
|
2
|
+
num
|
|
3
|
+
}) => {
|
|
4
|
+
return Math.max(Math.floor(Math.log10(Math.abs(num))), 0) + 1;
|
|
5
|
+
};
|
|
6
|
+
export const columnBaseSize = ({
|
|
7
|
+
experience = 3
|
|
8
|
+
}) => {
|
|
9
|
+
const digits = numDigits({
|
|
10
|
+
num: experience
|
|
11
|
+
});
|
|
12
|
+
return {
|
|
13
|
+
sm: digits > 4 ? 5 : 4,
|
|
14
|
+
md: digits > 4 ? 5 : 4,
|
|
15
|
+
lg: digits > 4 ? 4 : 5,
|
|
16
|
+
xl: digits > 4 ? 5 : 4
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
export const calculatePercent = ({
|
|
20
|
+
value,
|
|
21
|
+
total
|
|
22
|
+
}) => {
|
|
23
|
+
return value / total * 100;
|
|
24
|
+
};
|
|
25
|
+
export const calculateBarWidth = ({
|
|
26
|
+
value,
|
|
27
|
+
minRange,
|
|
28
|
+
maxRange
|
|
29
|
+
}) => {
|
|
30
|
+
const range = maxRange - minRange;
|
|
31
|
+
const adjustedValue = value - minRange;
|
|
32
|
+
return Math.floor(calculatePercent({
|
|
33
|
+
value: adjustedValue,
|
|
34
|
+
total: range
|
|
35
|
+
}));
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Calculate tick spacing and nice minimum and maximum data points on the axis.
|
|
40
|
+
*/
|
|
41
|
+
export const calculateTicksAndRange = ({
|
|
42
|
+
maxTicks,
|
|
43
|
+
min,
|
|
44
|
+
max
|
|
45
|
+
}) => {
|
|
46
|
+
const range = niceNum({
|
|
47
|
+
range: max - min,
|
|
48
|
+
roundDown: false
|
|
49
|
+
});
|
|
50
|
+
const tickSpacing = niceNum({
|
|
51
|
+
range: range / (maxTicks - 1),
|
|
52
|
+
roundDown: true
|
|
53
|
+
});
|
|
54
|
+
const niceMin = Math.floor(min / tickSpacing) * tickSpacing;
|
|
55
|
+
const niceMax = Math.ceil(max / tickSpacing) * tickSpacing;
|
|
56
|
+
const tickCount = range / tickSpacing;
|
|
57
|
+
return [tickCount, niceMin, niceMax];
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Returns a "nice" number approximately equal to range
|
|
62
|
+
* Rounds the number if round = true
|
|
63
|
+
* Takes the ceiling if round = false.
|
|
64
|
+
* A nice number is a simple decimal number, for example if a number is 1234, a nice number would be 1000 or 2000.
|
|
65
|
+
*/
|
|
66
|
+
export const niceNum = ({
|
|
67
|
+
range,
|
|
68
|
+
roundDown
|
|
69
|
+
}) => {
|
|
70
|
+
const exponent = Math.floor(Math.log10(range));
|
|
71
|
+
const fraction = range / 10 ** exponent;
|
|
72
|
+
let niceFraction;
|
|
73
|
+
if (roundDown) {
|
|
74
|
+
if (fraction < 1.5) niceFraction = 1;else if (fraction < 3) niceFraction = 2;else if (fraction < 7) niceFraction = 5;else niceFraction = 10;
|
|
75
|
+
} else if (fraction <= 1) niceFraction = 1;else if (fraction <= 2) niceFraction = 2;else if (fraction <= 5) niceFraction = 5;else niceFraction = 10;
|
|
76
|
+
return niceFraction * 10 ** exponent;
|
|
77
|
+
};
|
|
78
|
+
export const getPercentDiff = ({
|
|
79
|
+
v1,
|
|
80
|
+
v2
|
|
81
|
+
}) => {
|
|
82
|
+
return Math.abs(v1 - v2) / ((v1 + v2) / 2) * 100;
|
|
83
|
+
};
|
|
84
|
+
export const formatNumberUS = ({
|
|
85
|
+
num,
|
|
86
|
+
locale = 'en'
|
|
87
|
+
}) => Intl.NumberFormat(locale).format(num);
|
|
88
|
+
export const formatNumberUSCompact = ({
|
|
89
|
+
num,
|
|
90
|
+
locale = 'en'
|
|
91
|
+
}) => Intl.NumberFormat(locale, {
|
|
92
|
+
notation: 'compact',
|
|
93
|
+
compactDisplay: 'short'
|
|
94
|
+
}).format(num);
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Sort bars based on sortBy and order configuration
|
|
98
|
+
*/
|
|
99
|
+
export const sortBars = ({
|
|
100
|
+
bars,
|
|
101
|
+
sortBy,
|
|
102
|
+
order
|
|
103
|
+
}) => {
|
|
104
|
+
if (sortBy === 'none' || !sortBy) {
|
|
105
|
+
return bars;
|
|
106
|
+
}
|
|
107
|
+
const sorted = [...bars].sort((a, b) => {
|
|
108
|
+
if (sortBy === 'label') {
|
|
109
|
+
return a.yLabel.localeCompare(b.yLabel);
|
|
110
|
+
}
|
|
111
|
+
// sortBy === 'value' - use seriesTwoValue if available, otherwise seriesOneValue
|
|
112
|
+
const aValue = a.seriesTwoValue ?? a.seriesOneValue;
|
|
113
|
+
const bValue = b.seriesTwoValue ?? b.seriesOneValue;
|
|
114
|
+
return aValue - bValue;
|
|
115
|
+
});
|
|
116
|
+
return order === 'descending' ? sorted.reverse() : sorted;
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Generates an accessible summary of the bar values
|
|
121
|
+
*/
|
|
122
|
+
export const getValuesSummary = ({
|
|
123
|
+
isInteractive,
|
|
124
|
+
seriesOneValue,
|
|
125
|
+
seriesTwoValue,
|
|
126
|
+
unit,
|
|
127
|
+
yLabel,
|
|
128
|
+
translations
|
|
129
|
+
}) => {
|
|
130
|
+
const unitText = unit ? ` ${unit}` : '';
|
|
131
|
+
if (seriesTwoValue !== undefined) {
|
|
132
|
+
const gained = seriesOneValue;
|
|
133
|
+
return `${gained}${unitText} ${translations.accessibility.gainedNowAt} ${seriesTwoValue}${unitText} ${translations.accessibility.inLabel} ${yLabel}`;
|
|
134
|
+
}
|
|
135
|
+
return isInteractive ? `${seriesOneValue}${unitText} ${translations.accessibility.inLabel} ${yLabel}` : `${seriesOneValue}${unitText} ${translations.accessibility.inOnly}`;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Calculates the value for a given label position
|
|
140
|
+
*/
|
|
141
|
+
export const getLabel = ({
|
|
142
|
+
labelCount,
|
|
143
|
+
labelIndex,
|
|
144
|
+
min,
|
|
145
|
+
max
|
|
146
|
+
}) => {
|
|
147
|
+
if (labelCount <= 1) return max;
|
|
148
|
+
const incrementalDecimal = labelIndex / (labelCount - 1);
|
|
149
|
+
return Math.floor(min + incrementalDecimal * (max - min));
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Calculates the percentage position for a given value within a range
|
|
154
|
+
* Returns a value between 0 and 100 representing the position percentage
|
|
155
|
+
*/
|
|
156
|
+
export const calculatePositionPercent = ({
|
|
157
|
+
value,
|
|
158
|
+
min,
|
|
159
|
+
max
|
|
160
|
+
}) => {
|
|
161
|
+
if (max === min) return 0;
|
|
162
|
+
const range = max - min;
|
|
163
|
+
const adjustedValue = value - min;
|
|
164
|
+
return adjustedValue / range * 100;
|
|
165
|
+
};
|
|
@@ -122,9 +122,9 @@ export declare function useDebouncedField<T extends InputTypes>({ name, watchUpd
|
|
|
122
122
|
value: T extends "checkbox" ? boolean : string;
|
|
123
123
|
error: string | FieldError | Merge<FieldError, FieldErrorsImpl<any>> | undefined;
|
|
124
124
|
ref: import("react-hook-form").UseFormRegisterReturn<string>;
|
|
125
|
-
control: import("react-hook-form").Control<import("react-hook-form").FieldValues, any, import("react-hook-form").FieldValues>;
|
|
126
125
|
isDisabled: boolean;
|
|
127
126
|
isLoading: boolean | undefined;
|
|
127
|
+
control: import("react-hook-form").Control<import("react-hook-form").FieldValues, any, import("react-hook-form").FieldValues>;
|
|
128
128
|
isSoloField: boolean | undefined;
|
|
129
129
|
validation: RegisterOptions | undefined;
|
|
130
130
|
getValues: import("react-hook-form").UseFormGetValues<import("react-hook-form").FieldValues>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { theme as GamutTheme } from '@codecademy/gamut-styles';
|
|
2
2
|
import { StylesConfig } from 'react-select';
|
|
3
|
-
export declare const conditionalBorderStates: (props: Partial<Record<"error" | "
|
|
3
|
+
export declare const conditionalBorderStates: (props: Partial<Record<"error" | "activated" | "isDisabled" | "isFocused", boolean>> & {
|
|
4
4
|
theme?: import("@emotion/react").Theme | undefined;
|
|
5
5
|
}) => import("@codecademy/variance").CSSObject;
|
|
6
6
|
export declare const getMemoizedStyles: (theme: typeof GamutTheme, zIndex?: number) => StylesConfig<any, false>;
|
|
@@ -315,7 +315,7 @@ declare const StyledForm: import("@emotion/styled").StyledComponent<{
|
|
|
315
315
|
}>;
|
|
316
316
|
} & {
|
|
317
317
|
theme?: import("@emotion/react").Theme | undefined;
|
|
318
|
-
}, Pick<React.DetailedHTMLProps<React.FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>, "name" | "slot" | "style" | "title" | "dir" | "children" | "className" | "aria-hidden" | "onAnimationStart" | "onDragStart" | "onDragEnd" | "onDrag" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoFocus" | "contentEditable" | "contextMenu" | "draggable" | "hidden" | "id" | "lang" | "nonce" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "content" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onResize" | "onResizeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDragCapture" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "method" | "target" | "
|
|
318
|
+
}, Pick<React.DetailedHTMLProps<React.FormHTMLAttributes<HTMLFormElement>, HTMLFormElement>, "name" | "slot" | "style" | "title" | "dir" | "children" | "className" | "aria-hidden" | "onAnimationStart" | "onDragStart" | "onDragEnd" | "onDrag" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "autoFocus" | "contentEditable" | "contextMenu" | "draggable" | "hidden" | "id" | "lang" | "nonce" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "content" | "datatype" | "inlist" | "prefix" | "property" | "rel" | "resource" | "rev" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-braillelabel" | "aria-brailleroledescription" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colindextext" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-description" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowindextext" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onResize" | "onResizeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDragCapture" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerLeave" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "method" | "target" | "autoComplete" | "acceptCharset" | "action" | "encType" | "noValidate" | keyof React.ClassAttributes<HTMLFormElement>>, {}>;
|
|
319
319
|
export type FormProps = ComponentProps<typeof StyledForm>;
|
|
320
320
|
export declare const Form: React.FC<FormProps>;
|
|
321
321
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _styled from "@emotion/styled/base";
|
|
2
2
|
import { states, variant } from '@codecademy/gamut-styles';
|
|
3
3
|
import * as React from 'react';
|
|
4
|
-
import { FlexBox } from '
|
|
4
|
+
import { FlexBox } from '../../Box';
|
|
5
5
|
import { InfoTip } from '../../Tip/InfoTip';
|
|
6
6
|
import { Text } from '../../Typography/Text';
|
|
7
7
|
import { formBaseStyles, formFieldTextDisabledStyles } from '../styles';
|
|
@@ -30,7 +30,7 @@ const labelStates = states({
|
|
|
30
30
|
const Label = /*#__PURE__*/_styled("label", {
|
|
31
31
|
target: "e1t0n89n0",
|
|
32
32
|
label: "Label"
|
|
33
|
-
})(labelSizeVariants, labelStates, process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,
|
|
33
|
+
})(labelSizeVariants, labelStates, process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9Gb3JtL2VsZW1lbnRzL0Zvcm1Hcm91cExhYmVsLnRzeCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFtRGMiLCJmaWxlIjoiLi4vLi4vLi4vc3JjL0Zvcm0vZWxlbWVudHMvRm9ybUdyb3VwTGFiZWwudHN4Iiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgc3RhdGVzLCB2YXJpYW50IH0gZnJvbSAnQGNvZGVjYWRlbXkvZ2FtdXQtc3R5bGVzJztcbmltcG9ydCB7IFN0eWxlUHJvcHMgfSBmcm9tICdAY29kZWNhZGVteS92YXJpYW5jZSc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCc7XG5pbXBvcnQgeyBIVE1MQXR0cmlidXRlcyB9IGZyb20gJ3JlYWN0JztcbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0JztcblxuaW1wb3J0IHsgRmxleEJveCB9IGZyb20gJy4uLy4uL0JveCc7XG5pbXBvcnQgeyBJbmZvVGlwLCBJbmZvVGlwUHJvcHMgfSBmcm9tICcuLi8uLi9UaXAvSW5mb1RpcCc7XG5pbXBvcnQgeyBUZXh0IH0gZnJvbSAnLi4vLi4vVHlwb2dyYXBoeS9UZXh0JztcbmltcG9ydCB7IGZvcm1CYXNlU3R5bGVzLCBmb3JtRmllbGRUZXh0RGlzYWJsZWRTdHlsZXMgfSBmcm9tICcuLi9zdHlsZXMnO1xuaW1wb3J0IHsgQmFzZUlucHV0UHJvcHMgfSBmcm9tICcuLi90eXBlcyc7XG5cbmNvbnN0IGxhYmVsU2l6ZVZhcmlhbnRzID0gdmFyaWFudCh7XG4gIGRlZmF1bHRWYXJpYW50OiAnc21hbGwnLFxuICBwcm9wOiAnc2l6ZScsXG4gIGJhc2U6IHsgZGlzcGxheTogJ2Jsb2NrJywgLi4uZm9ybUJhc2VTdHlsZXMgfSxcbiAgdmFyaWFudHM6IHtcbiAgICBzbWFsbDoge1xuICAgICAgbGluZUhlaWdodDogJ2Jhc2UnLFxuICAgIH0sXG4gICAgbGFyZ2U6IHtcbiAgICAgIGZvbnRTaXplOiAyMixcbiAgICAgIGxpbmVIZWlnaHQ6ICdiYXNlJyxcbiAgICAgIGZvbnRXZWlnaHQ6ICd0aXRsZScsXG4gICAgfSxcbiAgfSxcbn0pO1xuXG5jb25zdCBsYWJlbFN0YXRlcyA9IHN0YXRlcyh7XG4gIGRpc2FibGVkOiBmb3JtRmllbGRUZXh0RGlzYWJsZWRTdHlsZXMsXG59KTtcblxuZXhwb3J0IGludGVyZmFjZSBMYWJlbFZhcmlhbnRzXG4gIGV4dGVuZHMgU3R5bGVQcm9wczx0eXBlb2YgbGFiZWxTaXplVmFyaWFudHM+LFxuICAgIFN0eWxlUHJvcHM8dHlwZW9mIGxhYmVsU3RhdGVzPiB7fVxuXG5leHBvcnQgdHlwZSBGb3JtR3JvdXBMYWJlbFByb3BzID0gSFRNTEF0dHJpYnV0ZXM8SFRNTERpdkVsZW1lbnQ+ICZcbiAgSFRNTEF0dHJpYnV0ZXM8SFRNTExhYmVsRWxlbWVudD4gJlxuICBMYWJlbFZhcmlhbnRzICZcbiAgUGljazxCYXNlSW5wdXRQcm9wcywgJ2h0bWxGb3InIHwgJ3JlcXVpcmVkJz4gJiB7XG4gICAgLyoqXG4gICAgICogW1RoZSBmb3IvaWQgc3RyaW5nIG9mIGEgbGFiZWwgb3IgbGFiZWxhYmxlIGZvcm0tcmVsYXRlZCBlbGVtZW50XShodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvSFRNTExhYmVsRWxlbWVudC9odG1sRm9yKS4gVGhlIG91dGVyIEZvcm1Hcm91cCBvciBGb3JtTGFiZWwgc2hvdWxkIGhhdmUgYW4gaWRlbnRpY2FsIHN0cmluZyBhcyB0aGUgaW5uZXIgRm9ybUVsZW1lbnQgZm9yIGFjY2Vzc2liaWxpdHkgcHVycG9zZXMuXG4gICAgICovXG4gICAgaW5mb3RpcD86IEluZm9UaXBQcm9wcztcbiAgICBzaXplPzogJ3NtYWxsJyB8ICdsYXJnZSc7XG4gICAgLyoqXG4gICAgICogU29sbyBmaWVsZHMgc2hvdWxkIGFsd2F5cyBiZSByZXF1aXJlZCBhbmQgaGF2ZSBubyBvcHRpb25hbC9yZXF1aXJlZCB0ZXh0XG4gICAgICovXG4gICAgaXNTb2xvRmllbGQ/OiBib29sZWFuO1xuICB9O1xuXG5jb25zdCBMYWJlbCA9IHN0eWxlZC5sYWJlbDxGb3JtR3JvdXBMYWJlbFByb3BzPihsYWJlbFNpemVWYXJpYW50cywgbGFiZWxTdGF0ZXMpO1xuXG5leHBvcnQgY29uc3QgRm9ybUdyb3VwTGFiZWw6IFJlYWN0LkZDPEZvcm1Hcm91cExhYmVsUHJvcHM+ID0gKHtcbiAgY2hpbGRyZW4sXG4gIGNsYXNzTmFtZSxcbiAgZGlzYWJsZWQsXG4gIGh0bWxGb3IsXG4gIGluZm90aXAsXG4gIGlzU29sb0ZpZWxkLFxuICByZXF1aXJlZCxcbiAgc2l6ZSxcbiAgLi4ucmVzdFxufSkgPT4ge1xuICByZXR1cm4gKFxuICAgIDxGbGV4Qm94IGp1c3RpZnlDb250ZW50PVwic3BhY2UtYmV0d2VlblwiIG1iPXs0fT5cbiAgICAgIDxMYWJlbFxuICAgICAgICB7Li4ucmVzdH1cbiAgICAgICAgYXM9e2h0bWxGb3IgPyAnbGFiZWwnIDogJ2Rpdid9XG4gICAgICAgIGNsYXNzTmFtZT17Y2xhc3NOYW1lfVxuICAgICAgICBkaXNhYmxlZD17ZGlzYWJsZWR9XG4gICAgICAgIGh0bWxGb3I9e2h0bWxGb3J9XG4gICAgICAgIHNpemU9e3NpemV9XG4gICAgICA+XG4gICAgICAgIHtjaGlsZHJlbn1cbiAgICAgICAgeyFpc1NvbG9GaWVsZCAmJlxuICAgICAgICAgIChyZXF1aXJlZCA/IChcbiAgICAgICAgICAgIDxUZXh0IGFyaWEtaGlkZGVuIGFzPVwic3BhblwiPlxuICAgICAgICAgICAgICAqXG4gICAgICAgICAgICA8L1RleHQ+XG4gICAgICAgICAgKSA6IChcbiAgICAgICAgICAgICdcXHUwMEEwKG9wdGlvbmFsKSdcbiAgICAgICAgICApKX1cbiAgICAgIDwvTGFiZWw+XG4gICAgICB7aW5mb3RpcCAmJiA8SW5mb1RpcCB7Li4uaW5mb3RpcH0gLz59XG4gICAgPC9GbGV4Qm94PlxuICApO1xufTtcbiJdfQ== */");
|
|
34
34
|
export const FormGroupLabel = ({
|
|
35
35
|
children,
|
|
36
36
|
className,
|