@codecademy/gamut 67.6.2 → 67.6.3-alpha.22c4b5.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/Bar/Bar.d.ts +6 -0
- package/dist/BarChart/Bar/Bar.js +176 -0
- package/dist/BarChart/Bar/index.d.ts +1 -0
- package/dist/BarChart/Bar/index.js +2 -0
- package/dist/BarChart/BarChartProvider.d.ts +12 -0
- package/dist/BarChart/BarChartProvider.js +16 -0
- package/dist/BarChart/index.d.ts +3 -0
- package/dist/BarChart/index.js +69 -0
- package/dist/BarChart/layout/GridLines.d.ts +7 -0
- package/dist/BarChart/layout/GridLines.js +77 -0
- package/dist/BarChart/layout/ScaleChartHeader.d.ts +10 -0
- package/dist/BarChart/layout/ScaleChartHeader.js +88 -0
- package/dist/BarChart/layout/VerticalSpacer.d.ts +6 -0
- package/dist/BarChart/layout/VerticalSpacer.js +48 -0
- package/dist/BarChart/shared/elements.d.ts +1396 -0
- package/dist/BarChart/shared/elements.js +65 -0
- package/dist/BarChart/shared/styles.d.ts +2 -0
- package/dist/BarChart/shared/styles.js +2 -0
- package/dist/BarChart/shared/types.d.ts +56 -0
- package/dist/BarChart/shared/types.js +1 -0
- package/dist/BarChart/utils/hooks.d.ts +36 -0
- package/dist/BarChart/utils/hooks.js +61 -0
- package/dist/BarChart/utils/index.d.ts +83 -0
- package/dist/BarChart/utils/index.js +162 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import _styled from "@emotion/styled/base";
|
|
2
|
+
import { css } from '@codecademy/gamut-styles';
|
|
3
|
+
import { motion } from 'framer-motion';
|
|
4
|
+
import { Box } from '../../Box';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Container for bars with responsive height
|
|
8
|
+
*/
|
|
9
|
+
export const BarWrapper = /*#__PURE__*/_styled(Box, {
|
|
10
|
+
target: "ey0wy1t3",
|
|
11
|
+
label: "BarWrapper"
|
|
12
|
+
})(css({
|
|
13
|
+
display: 'flex',
|
|
14
|
+
overflow: 'hidden',
|
|
15
|
+
position: 'relative',
|
|
16
|
+
alignItems: 'center',
|
|
17
|
+
flex: 1,
|
|
18
|
+
height: {
|
|
19
|
+
_: 12,
|
|
20
|
+
sm: 20
|
|
21
|
+
},
|
|
22
|
+
borderRadius: {
|
|
23
|
+
_: 'md',
|
|
24
|
+
sm: 'xl'
|
|
25
|
+
}
|
|
26
|
+
}), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9CYXJDaGFydC9zaGFyZWQvZWxlbWVudHMudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQVMwQiIsImZpbGUiOiIuLi8uLi8uLi9zcmMvQmFyQ2hhcnQvc2hhcmVkL2VsZW1lbnRzLnRzeCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGNzcyB9IGZyb20gJ0Bjb2RlY2FkZW15L2dhbXV0LXN0eWxlcyc7XG5pbXBvcnQgc3R5bGVkIGZyb20gJ0BlbW90aW9uL3N0eWxlZCc7XG5pbXBvcnQgeyBtb3Rpb24gfSBmcm9tICdmcmFtZXItbW90aW9uJztcblxuaW1wb3J0IHsgQm94IH0gZnJvbSAnLi4vLi4vQm94JztcblxuLyoqXG4gKiBDb250YWluZXIgZm9yIGJhcnMgd2l0aCByZXNwb25zaXZlIGhlaWdodFxuICovXG5leHBvcnQgY29uc3QgQmFyV3JhcHBlciA9IHN0eWxlZChCb3gpKFxuICBjc3Moe1xuICAgIGRpc3BsYXk6ICdmbGV4JyxcbiAgICBvdmVyZmxvdzogJ2hpZGRlbicsXG4gICAgcG9zaXRpb246ICdyZWxhdGl2ZScsXG4gICAgYWxpZ25JdGVtczogJ2NlbnRlcicsXG4gICAgZmxleDogMSxcbiAgICBoZWlnaHQ6IHsgXzogMTIsIHNtOiAyMCB9LFxuICAgIGJvcmRlclJhZGl1czogeyBfOiAnbWQnLCBzbTogJ3hsJyB9LFxuICB9KVxuKTtcblxuY29uc3QgYmFzZUJhclN0eWxlcyA9IHtcbiAgYWxpZ25JdGVtczogJ2NlbnRlcicsXG4gIGJvcmRlcjogMSxcbiAgYm9yZGVyQ29sb3I6ICdib3JkZXItcHJpbWFyeScsXG4gIGJvcmRlclJhZGl1czogJ2luaGVyaXQnLFxuICBkaXNwbGF5OiAnZmxleCcsXG4gIGhlaWdodDogJzEwMCUnLFxuICBsZWZ0OiAwLFxuICBwb3NpdGlvbjogJ2Fic29sdXRlJyxcbn0gYXMgY29uc3Q7XG5cbi8qKlxuICogQW5pbWF0ZWQgYmFyIGVsZW1lbnQgZm9yIGJhY2tncm91bmQvdG90YWwgdmFsdWUgZGlzcGxheVxuICovXG5leHBvcnQgY29uc3QgQmFja2dyb3VuZEJhciA9IHN0eWxlZChtb3Rpb24uY3JlYXRlKEJveCkpKFxuICBjc3Moe1xuICAgIC4uLmJhc2VCYXJTdHlsZXMsXG4gIH0pXG4pO1xuXG4vKipcbiAqIEZvcmVncm91bmQgYmFyIGZvciBzdGFja2VkIGRpc3BsYXkgKHByb2dyZXNzIHZhbHVlKVxuICovXG5leHBvcnQgY29uc3QgRm9yZWdyb3VuZEJhciA9IHN0eWxlZChtb3Rpb24uY3JlYXRlKEJveCkpKFxuICBjc3Moe1xuICAgIC4uLmJhc2VCYXJTdHlsZXMsXG4gIH0pXG4pO1xuXG5leHBvcnQgY29uc3QgQmFyc0xpc3QgPSBzdHlsZWQoJ3VsJykoXG4gIGNzcyh7XG4gICAgbGlzdFN0eWxlOiAnbm9uZScsXG4gICAgJyYgbGk6bnRoLW9mLXR5cGUoZXZlbiknOiB7XG4gICAgICBiZzogJ2JhY2tncm91bmQtc2VsZWN0ZWQnLFxuICAgIH0sXG4gIH0pXG4pO1xuIl19 */");
|
|
27
|
+
const baseBarStyles = {
|
|
28
|
+
alignItems: 'center',
|
|
29
|
+
border: 1,
|
|
30
|
+
borderColor: 'border-primary',
|
|
31
|
+
borderRadius: 'inherit',
|
|
32
|
+
display: 'flex',
|
|
33
|
+
height: '100%',
|
|
34
|
+
left: 0,
|
|
35
|
+
position: 'absolute'
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Animated bar element for background/total value display
|
|
40
|
+
*/
|
|
41
|
+
export const BackgroundBar = /*#__PURE__*/_styled(motion.create(Box), {
|
|
42
|
+
target: "ey0wy1t2",
|
|
43
|
+
label: "BackgroundBar"
|
|
44
|
+
})(css({
|
|
45
|
+
...baseBarStyles
|
|
46
|
+
}), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9CYXJDaGFydC9zaGFyZWQvZWxlbWVudHMudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQW1DNkIiLCJmaWxlIjoiLi4vLi4vLi4vc3JjL0JhckNoYXJ0L3NoYXJlZC9lbGVtZW50cy50c3giLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjc3MgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnO1xuaW1wb3J0IHsgbW90aW9uIH0gZnJvbSAnZnJhbWVyLW1vdGlvbic7XG5cbmltcG9ydCB7IEJveCB9IGZyb20gJy4uLy4uL0JveCc7XG5cbi8qKlxuICogQ29udGFpbmVyIGZvciBiYXJzIHdpdGggcmVzcG9uc2l2ZSBoZWlnaHRcbiAqL1xuZXhwb3J0IGNvbnN0IEJhcldyYXBwZXIgPSBzdHlsZWQoQm94KShcbiAgY3NzKHtcbiAgICBkaXNwbGF5OiAnZmxleCcsXG4gICAgb3ZlcmZsb3c6ICdoaWRkZW4nLFxuICAgIHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuICAgIGFsaWduSXRlbXM6ICdjZW50ZXInLFxuICAgIGZsZXg6IDEsXG4gICAgaGVpZ2h0OiB7IF86IDEyLCBzbTogMjAgfSxcbiAgICBib3JkZXJSYWRpdXM6IHsgXzogJ21kJywgc206ICd4bCcgfSxcbiAgfSlcbik7XG5cbmNvbnN0IGJhc2VCYXJTdHlsZXMgPSB7XG4gIGFsaWduSXRlbXM6ICdjZW50ZXInLFxuICBib3JkZXI6IDEsXG4gIGJvcmRlckNvbG9yOiAnYm9yZGVyLXByaW1hcnknLFxuICBib3JkZXJSYWRpdXM6ICdpbmhlcml0JyxcbiAgZGlzcGxheTogJ2ZsZXgnLFxuICBoZWlnaHQ6ICcxMDAlJyxcbiAgbGVmdDogMCxcbiAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIEFuaW1hdGVkIGJhciBlbGVtZW50IGZvciBiYWNrZ3JvdW5kL3RvdGFsIHZhbHVlIGRpc3BsYXlcbiAqL1xuZXhwb3J0IGNvbnN0IEJhY2tncm91bmRCYXIgPSBzdHlsZWQobW90aW9uLmNyZWF0ZShCb3gpKShcbiAgY3NzKHtcbiAgICAuLi5iYXNlQmFyU3R5bGVzLFxuICB9KVxuKTtcblxuLyoqXG4gKiBGb3JlZ3JvdW5kIGJhciBmb3Igc3RhY2tlZCBkaXNwbGF5IChwcm9ncmVzcyB2YWx1ZSlcbiAqL1xuZXhwb3J0IGNvbnN0IEZvcmVncm91bmRCYXIgPSBzdHlsZWQobW90aW9uLmNyZWF0ZShCb3gpKShcbiAgY3NzKHtcbiAgICAuLi5iYXNlQmFyU3R5bGVzLFxuICB9KVxuKTtcblxuZXhwb3J0IGNvbnN0IEJhcnNMaXN0ID0gc3R5bGVkKCd1bCcpKFxuICBjc3Moe1xuICAgIGxpc3RTdHlsZTogJ25vbmUnLFxuICAgICcmIGxpOm50aC1vZi10eXBlKGV2ZW4pJzoge1xuICAgICAgYmc6ICdiYWNrZ3JvdW5kLXNlbGVjdGVkJyxcbiAgICB9LFxuICB9KVxuKTtcbiJdfQ== */");
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Foreground bar for stacked display (progress value)
|
|
50
|
+
*/
|
|
51
|
+
export const ForegroundBar = /*#__PURE__*/_styled(motion.create(Box), {
|
|
52
|
+
target: "ey0wy1t1",
|
|
53
|
+
label: "ForegroundBar"
|
|
54
|
+
})(css({
|
|
55
|
+
...baseBarStyles
|
|
56
|
+
}), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9CYXJDaGFydC9zaGFyZWQvZWxlbWVudHMudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQTRDNkIiLCJmaWxlIjoiLi4vLi4vLi4vc3JjL0JhckNoYXJ0L3NoYXJlZC9lbGVtZW50cy50c3giLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjc3MgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnO1xuaW1wb3J0IHsgbW90aW9uIH0gZnJvbSAnZnJhbWVyLW1vdGlvbic7XG5cbmltcG9ydCB7IEJveCB9IGZyb20gJy4uLy4uL0JveCc7XG5cbi8qKlxuICogQ29udGFpbmVyIGZvciBiYXJzIHdpdGggcmVzcG9uc2l2ZSBoZWlnaHRcbiAqL1xuZXhwb3J0IGNvbnN0IEJhcldyYXBwZXIgPSBzdHlsZWQoQm94KShcbiAgY3NzKHtcbiAgICBkaXNwbGF5OiAnZmxleCcsXG4gICAgb3ZlcmZsb3c6ICdoaWRkZW4nLFxuICAgIHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuICAgIGFsaWduSXRlbXM6ICdjZW50ZXInLFxuICAgIGZsZXg6IDEsXG4gICAgaGVpZ2h0OiB7IF86IDEyLCBzbTogMjAgfSxcbiAgICBib3JkZXJSYWRpdXM6IHsgXzogJ21kJywgc206ICd4bCcgfSxcbiAgfSlcbik7XG5cbmNvbnN0IGJhc2VCYXJTdHlsZXMgPSB7XG4gIGFsaWduSXRlbXM6ICdjZW50ZXInLFxuICBib3JkZXI6IDEsXG4gIGJvcmRlckNvbG9yOiAnYm9yZGVyLXByaW1hcnknLFxuICBib3JkZXJSYWRpdXM6ICdpbmhlcml0JyxcbiAgZGlzcGxheTogJ2ZsZXgnLFxuICBoZWlnaHQ6ICcxMDAlJyxcbiAgbGVmdDogMCxcbiAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIEFuaW1hdGVkIGJhciBlbGVtZW50IGZvciBiYWNrZ3JvdW5kL3RvdGFsIHZhbHVlIGRpc3BsYXlcbiAqL1xuZXhwb3J0IGNvbnN0IEJhY2tncm91bmRCYXIgPSBzdHlsZWQobW90aW9uLmNyZWF0ZShCb3gpKShcbiAgY3NzKHtcbiAgICAuLi5iYXNlQmFyU3R5bGVzLFxuICB9KVxuKTtcblxuLyoqXG4gKiBGb3JlZ3JvdW5kIGJhciBmb3Igc3RhY2tlZCBkaXNwbGF5IChwcm9ncmVzcyB2YWx1ZSlcbiAqL1xuZXhwb3J0IGNvbnN0IEZvcmVncm91bmRCYXIgPSBzdHlsZWQobW90aW9uLmNyZWF0ZShCb3gpKShcbiAgY3NzKHtcbiAgICAuLi5iYXNlQmFyU3R5bGVzLFxuICB9KVxuKTtcblxuZXhwb3J0IGNvbnN0IEJhcnNMaXN0ID0gc3R5bGVkKCd1bCcpKFxuICBjc3Moe1xuICAgIGxpc3RTdHlsZTogJ25vbmUnLFxuICAgICcmIGxpOm50aC1vZi10eXBlKGV2ZW4pJzoge1xuICAgICAgYmc6ICdiYWNrZ3JvdW5kLXNlbGVjdGVkJyxcbiAgICB9LFxuICB9KVxuKTtcbiJdfQ== */");
|
|
57
|
+
export const BarsList = /*#__PURE__*/_styled('ul', {
|
|
58
|
+
target: "ey0wy1t0",
|
|
59
|
+
label: "BarsList"
|
|
60
|
+
})(css({
|
|
61
|
+
listStyle: 'none',
|
|
62
|
+
'& li:nth-of-type(even)': {
|
|
63
|
+
bg: 'background-selected'
|
|
64
|
+
}
|
|
65
|
+
}), process.env.NODE_ENV === "production" ? "" : "/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9CYXJDaGFydC9zaGFyZWQvZWxlbWVudHMudHN4Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQWtEd0IiLCJmaWxlIjoiLi4vLi4vLi4vc3JjL0JhckNoYXJ0L3NoYXJlZC9lbGVtZW50cy50c3giLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBjc3MgfSBmcm9tICdAY29kZWNhZGVteS9nYW11dC1zdHlsZXMnO1xuaW1wb3J0IHN0eWxlZCBmcm9tICdAZW1vdGlvbi9zdHlsZWQnO1xuaW1wb3J0IHsgbW90aW9uIH0gZnJvbSAnZnJhbWVyLW1vdGlvbic7XG5cbmltcG9ydCB7IEJveCB9IGZyb20gJy4uLy4uL0JveCc7XG5cbi8qKlxuICogQ29udGFpbmVyIGZvciBiYXJzIHdpdGggcmVzcG9uc2l2ZSBoZWlnaHRcbiAqL1xuZXhwb3J0IGNvbnN0IEJhcldyYXBwZXIgPSBzdHlsZWQoQm94KShcbiAgY3NzKHtcbiAgICBkaXNwbGF5OiAnZmxleCcsXG4gICAgb3ZlcmZsb3c6ICdoaWRkZW4nLFxuICAgIHBvc2l0aW9uOiAncmVsYXRpdmUnLFxuICAgIGFsaWduSXRlbXM6ICdjZW50ZXInLFxuICAgIGZsZXg6IDEsXG4gICAgaGVpZ2h0OiB7IF86IDEyLCBzbTogMjAgfSxcbiAgICBib3JkZXJSYWRpdXM6IHsgXzogJ21kJywgc206ICd4bCcgfSxcbiAgfSlcbik7XG5cbmNvbnN0IGJhc2VCYXJTdHlsZXMgPSB7XG4gIGFsaWduSXRlbXM6ICdjZW50ZXInLFxuICBib3JkZXI6IDEsXG4gIGJvcmRlckNvbG9yOiAnYm9yZGVyLXByaW1hcnknLFxuICBib3JkZXJSYWRpdXM6ICdpbmhlcml0JyxcbiAgZGlzcGxheTogJ2ZsZXgnLFxuICBoZWlnaHQ6ICcxMDAlJyxcbiAgbGVmdDogMCxcbiAgcG9zaXRpb246ICdhYnNvbHV0ZScsXG59IGFzIGNvbnN0O1xuXG4vKipcbiAqIEFuaW1hdGVkIGJhciBlbGVtZW50IGZvciBiYWNrZ3JvdW5kL3RvdGFsIHZhbHVlIGRpc3BsYXlcbiAqL1xuZXhwb3J0IGNvbnN0IEJhY2tncm91bmRCYXIgPSBzdHlsZWQobW90aW9uLmNyZWF0ZShCb3gpKShcbiAgY3NzKHtcbiAgICAuLi5iYXNlQmFyU3R5bGVzLFxuICB9KVxuKTtcblxuLyoqXG4gKiBGb3JlZ3JvdW5kIGJhciBmb3Igc3RhY2tlZCBkaXNwbGF5IChwcm9ncmVzcyB2YWx1ZSlcbiAqL1xuZXhwb3J0IGNvbnN0IEZvcmVncm91bmRCYXIgPSBzdHlsZWQobW90aW9uLmNyZWF0ZShCb3gpKShcbiAgY3NzKHtcbiAgICAuLi5iYXNlQmFyU3R5bGVzLFxuICB9KVxuKTtcblxuZXhwb3J0IGNvbnN0IEJhcnNMaXN0ID0gc3R5bGVkKCd1bCcpKFxuICBjc3Moe1xuICAgIGxpc3RTdHlsZTogJ25vbmUnLFxuICAgICcmIGxpOm50aC1vZi10eXBlKGV2ZW4pJzoge1xuICAgICAgYmc6ICdiYWNrZ3JvdW5kLXNlbGVjdGVkJyxcbiAgICB9LFxuICB9KVxuKTtcbiJdfQ== */");
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { GamutIconProps } from '@codecademy/gamut-icons';
|
|
2
|
+
import { ColorAlias } from '@codecademy/gamut-styles';
|
|
3
|
+
import { HTMLProps } from 'react';
|
|
4
|
+
import { ButtonProps } from '../../Button';
|
|
5
|
+
type BarChartAriaLabel = {
|
|
6
|
+
'aria-label': string;
|
|
7
|
+
'aria-labelledby'?: never;
|
|
8
|
+
};
|
|
9
|
+
type BarChartAriaLabelledBy = {
|
|
10
|
+
'aria-label'?: never;
|
|
11
|
+
'aria-labelledby': string;
|
|
12
|
+
};
|
|
13
|
+
type BarChartLabel = BarChartAriaLabel | BarChartAriaLabelledBy;
|
|
14
|
+
export type BarChartStyles = {
|
|
15
|
+
/** Color for text labels. Defaults to 'text' */
|
|
16
|
+
textColor?: ColorAlias;
|
|
17
|
+
/** Color for the foreground/progress bar. Defaults to 'feedback-warning' */
|
|
18
|
+
foregroundBarColor?: ColorAlias;
|
|
19
|
+
/** Color for the background/total bar. Defaults to 'paleBlue' */
|
|
20
|
+
backgroundBarColor?: ColorAlias;
|
|
21
|
+
};
|
|
22
|
+
export type BarProps = {
|
|
23
|
+
/** Label displayed on the y-axis for this bar */
|
|
24
|
+
yLabel: string;
|
|
25
|
+
/** The foreground/progress bar value (always shown) */
|
|
26
|
+
seriesOneValue: number;
|
|
27
|
+
/** The background/total bar value (optional - creates stacked effect when provided) */
|
|
28
|
+
seriesTwoValue?: number;
|
|
29
|
+
/** Optional gamut-icon to display next to the label */
|
|
30
|
+
icon?: React.ComponentType<GamutIconProps>;
|
|
31
|
+
/** Click handler - makes row interactive as a button */
|
|
32
|
+
onClick?: ButtonProps['onClick'];
|
|
33
|
+
/** Link href - makes row interactive as an anchor */
|
|
34
|
+
href?: HTMLProps<HTMLAnchorElement>['href'];
|
|
35
|
+
};
|
|
36
|
+
export type BarChartProps = BarChartLabel & {
|
|
37
|
+
/** Whether to animate bars on mount */
|
|
38
|
+
animate?: boolean;
|
|
39
|
+
/** Array of bar data to render */
|
|
40
|
+
barValues: BarProps[];
|
|
41
|
+
/** Maximum value for the x-axis scale */
|
|
42
|
+
maxRange: number;
|
|
43
|
+
/** Minimum value for the x-axis scale (usually 0) */
|
|
44
|
+
minRange: number;
|
|
45
|
+
/** Sort order for bars */
|
|
46
|
+
order?: 'ascending' | 'descending';
|
|
47
|
+
/** Property to sort bars by */
|
|
48
|
+
sortBy?: 'label' | 'value' | 'none';
|
|
49
|
+
/** Unit label to display (e.g., "XP") */
|
|
50
|
+
unit?: string;
|
|
51
|
+
/** Style configuration for colors */
|
|
52
|
+
styleConfig?: BarChartStyles;
|
|
53
|
+
/** Interval for x-axis scale markers */
|
|
54
|
+
xScale?: number;
|
|
55
|
+
};
|
|
56
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { BarChartContextProps } from '../BarChartProvider';
|
|
2
|
+
import { BarChartStyles } from '../shared/types';
|
|
3
|
+
export interface LabelPosition {
|
|
4
|
+
value: number;
|
|
5
|
+
positionPercent: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Hook that calculates label positions for a given range and count
|
|
9
|
+
* Returns an array of { value, positionPercent } objects
|
|
10
|
+
*/
|
|
11
|
+
export declare const useLabelPositions: ({ min, max, count, }: {
|
|
12
|
+
min: number;
|
|
13
|
+
max: number;
|
|
14
|
+
count: number;
|
|
15
|
+
}) => LabelPosition[];
|
|
16
|
+
export declare function useBarChartContext(): BarChartContextProps;
|
|
17
|
+
export interface UseBarChartOptions {
|
|
18
|
+
minRange: number;
|
|
19
|
+
maxRange: number;
|
|
20
|
+
xScale?: number;
|
|
21
|
+
unit?: string;
|
|
22
|
+
styleConfig?: BarChartStyles;
|
|
23
|
+
animate?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare function useBarChart({ minRange, maxRange, xScale, unit, styleConfig, animate, }: UseBarChartOptions): {
|
|
26
|
+
minRange: number;
|
|
27
|
+
maxRange: number;
|
|
28
|
+
xScale: number;
|
|
29
|
+
unit: string;
|
|
30
|
+
styleConfig: {
|
|
31
|
+
textColor: "text" | "background" | "primary" | "secondary" | "danger" | "interface" | "text-secondary" | "text-accent" | "text-disabled" | "feedback-error" | "feedback-success" | "feedback-warning" | "background-primary" | "background-disabled" | "background-error" | "background-success" | "background-warning" | "background-contrast" | "background-current" | "background-selected" | "background-hover" | "shadow-primary" | "shadow-secondary" | "primary-hover" | "primary-inverse" | "secondary-hover" | "danger-hover" | "interface-hover" | "border-primary" | "border-secondary" | "border-disabled" | "border-tertiary";
|
|
32
|
+
foregroundBarColor: "text" | "background" | "primary" | "secondary" | "danger" | "interface" | "text-secondary" | "text-accent" | "text-disabled" | "feedback-error" | "feedback-success" | "feedback-warning" | "background-primary" | "background-disabled" | "background-error" | "background-success" | "background-warning" | "background-contrast" | "background-current" | "background-selected" | "background-hover" | "shadow-primary" | "shadow-secondary" | "primary-hover" | "primary-inverse" | "secondary-hover" | "danger-hover" | "interface-hover" | "border-primary" | "border-secondary" | "border-disabled" | "border-tertiary";
|
|
33
|
+
backgroundBarColor: "text" | "background" | "primary" | "secondary" | "danger" | "interface" | "text-secondary" | "text-accent" | "text-disabled" | "feedback-error" | "feedback-success" | "feedback-warning" | "background-primary" | "background-disabled" | "background-error" | "background-success" | "background-warning" | "background-contrast" | "background-current" | "background-selected" | "background-hover" | "shadow-primary" | "shadow-secondary" | "primary-hover" | "primary-inverse" | "secondary-hover" | "danger-hover" | "interface-hover" | "border-primary" | "border-secondary" | "border-disabled" | "border-tertiary";
|
|
34
|
+
};
|
|
35
|
+
animate: boolean;
|
|
36
|
+
};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { useContext, useMemo } from 'react';
|
|
2
|
+
import { BarChartContext } from '../BarChartProvider';
|
|
3
|
+
import { calculatePositionPercent, getLabel } from './index';
|
|
4
|
+
const defaultStyleConfig = {
|
|
5
|
+
textColor: 'text',
|
|
6
|
+
foregroundBarColor: 'feedback-warning',
|
|
7
|
+
backgroundBarColor: 'background-primary'
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Hook that calculates label positions for a given range and count
|
|
12
|
+
* Returns an array of { value, positionPercent } objects
|
|
13
|
+
*/
|
|
14
|
+
export const useLabelPositions = ({
|
|
15
|
+
min,
|
|
16
|
+
max,
|
|
17
|
+
count
|
|
18
|
+
}) => {
|
|
19
|
+
return useMemo(() => Array.from({
|
|
20
|
+
length: count
|
|
21
|
+
}, (_, i) => {
|
|
22
|
+
const value = getLabel({
|
|
23
|
+
labelCount: count,
|
|
24
|
+
labelIndex: i,
|
|
25
|
+
min,
|
|
26
|
+
max
|
|
27
|
+
});
|
|
28
|
+
const positionPercent = calculatePositionPercent({
|
|
29
|
+
value,
|
|
30
|
+
min,
|
|
31
|
+
max
|
|
32
|
+
});
|
|
33
|
+
return {
|
|
34
|
+
value,
|
|
35
|
+
positionPercent
|
|
36
|
+
};
|
|
37
|
+
}), [min, max, count]);
|
|
38
|
+
};
|
|
39
|
+
export function useBarChartContext() {
|
|
40
|
+
return useContext(BarChartContext);
|
|
41
|
+
}
|
|
42
|
+
export function useBarChart({
|
|
43
|
+
minRange,
|
|
44
|
+
maxRange,
|
|
45
|
+
xScale,
|
|
46
|
+
unit = '',
|
|
47
|
+
styleConfig,
|
|
48
|
+
animate = false
|
|
49
|
+
}) {
|
|
50
|
+
return useMemo(() => ({
|
|
51
|
+
minRange,
|
|
52
|
+
maxRange,
|
|
53
|
+
xScale: xScale ?? Math.ceil((maxRange - minRange) / 5),
|
|
54
|
+
unit,
|
|
55
|
+
styleConfig: {
|
|
56
|
+
...defaultStyleConfig,
|
|
57
|
+
...styleConfig
|
|
58
|
+
},
|
|
59
|
+
animate
|
|
60
|
+
}), [minRange, maxRange, xScale, unit, styleConfig, animate]);
|
|
61
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { BarChartProps, BarProps } from '../shared/types';
|
|
2
|
+
export declare const numDigits: ({ num }: {
|
|
3
|
+
num: number;
|
|
4
|
+
}) => number;
|
|
5
|
+
export declare const columnBaseSize: ({ experience }: {
|
|
6
|
+
experience?: number | undefined;
|
|
7
|
+
}) => {
|
|
8
|
+
sm: number;
|
|
9
|
+
md: number;
|
|
10
|
+
lg: number;
|
|
11
|
+
xl: number;
|
|
12
|
+
};
|
|
13
|
+
export declare const calculatePercent: ({ value, total, }: {
|
|
14
|
+
value: number;
|
|
15
|
+
total: number;
|
|
16
|
+
}) => number;
|
|
17
|
+
export declare const calculateBarWidth: ({ value, minRange, maxRange, }: {
|
|
18
|
+
value: number;
|
|
19
|
+
minRange: number;
|
|
20
|
+
maxRange: number;
|
|
21
|
+
}) => number;
|
|
22
|
+
export declare const calculateTicksAndRange: ({ maxTicks, minPoint, maxPoint, }: {
|
|
23
|
+
maxTicks: number;
|
|
24
|
+
minPoint: number;
|
|
25
|
+
maxPoint: number;
|
|
26
|
+
}) => [number, number, number];
|
|
27
|
+
/**
|
|
28
|
+
* Returns a "nice" number approximately equal to range
|
|
29
|
+
* Rounds the number if round = true
|
|
30
|
+
* Takes the ceiling if round = false.
|
|
31
|
+
* A nice number is a simple decimal number, for example if a number is 1234, a nice number would be 1000 or 2000.
|
|
32
|
+
*/
|
|
33
|
+
export declare const niceNum: ({ range, roundDown, }: {
|
|
34
|
+
range: number;
|
|
35
|
+
roundDown: boolean;
|
|
36
|
+
}) => number;
|
|
37
|
+
export declare const getPercentDiff: ({ v1, v2 }: {
|
|
38
|
+
v1: number;
|
|
39
|
+
v2: number;
|
|
40
|
+
}) => number;
|
|
41
|
+
export declare const formatNumberUS: ({ num }: {
|
|
42
|
+
num: number;
|
|
43
|
+
}) => string;
|
|
44
|
+
export declare const formatNumberUSCompact: ({ num }: {
|
|
45
|
+
num: number;
|
|
46
|
+
}) => string;
|
|
47
|
+
/**
|
|
48
|
+
* Sort bars based on sortBy and order configuration
|
|
49
|
+
*/
|
|
50
|
+
export declare const sortBars: ({ bars, sortBy, order, }: {
|
|
51
|
+
bars: BarProps[];
|
|
52
|
+
sortBy: BarChartProps['sortBy'];
|
|
53
|
+
order: BarChartProps['order'];
|
|
54
|
+
}) => BarProps[];
|
|
55
|
+
/**
|
|
56
|
+
* Generates an accessible summary of the bar values
|
|
57
|
+
*/
|
|
58
|
+
export declare const getValuesSummary: ({ yLabel, seriesOneValue, seriesTwoValue, unit, }: {
|
|
59
|
+
yLabel: string;
|
|
60
|
+
seriesOneValue: number;
|
|
61
|
+
seriesTwoValue?: number | undefined;
|
|
62
|
+
unit: string;
|
|
63
|
+
}) => string;
|
|
64
|
+
/**
|
|
65
|
+
* Calculates the value for a given label position
|
|
66
|
+
*/
|
|
67
|
+
export declare const getLabel: ({ labelCount, labelIndex, min, max, }: {
|
|
68
|
+
labelCount: number;
|
|
69
|
+
labelIndex: number;
|
|
70
|
+
min: number;
|
|
71
|
+
max: number;
|
|
72
|
+
}) => number;
|
|
73
|
+
/**
|
|
74
|
+
* Calculates the percentage position for a given value within a range
|
|
75
|
+
* Returns a value between 0 and 100 representing the position percentage
|
|
76
|
+
*/
|
|
77
|
+
export declare const calculatePositionPercent: ({ value, min, max, }: {
|
|
78
|
+
value: number;
|
|
79
|
+
min: number;
|
|
80
|
+
max: number;
|
|
81
|
+
}) => number;
|
|
82
|
+
export { useBarChart, useBarChartContext, useLabelPositions } from './hooks';
|
|
83
|
+
export type { LabelPosition, UseBarChartOptions } from './hooks';
|
|
@@ -0,0 +1,162 @@
|
|
|
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
|
+
// Calculate tick spacing and nice minimum and maximum data points on the axis.
|
|
39
|
+
|
|
40
|
+
export const calculateTicksAndRange = ({
|
|
41
|
+
maxTicks,
|
|
42
|
+
minPoint,
|
|
43
|
+
maxPoint
|
|
44
|
+
}) => {
|
|
45
|
+
const range = niceNum({
|
|
46
|
+
range: maxPoint - minPoint,
|
|
47
|
+
roundDown: false
|
|
48
|
+
});
|
|
49
|
+
const tickSpacing = niceNum({
|
|
50
|
+
range: range / (maxTicks - 1),
|
|
51
|
+
roundDown: true
|
|
52
|
+
});
|
|
53
|
+
const niceMin = Math.floor(minPoint / tickSpacing) * tickSpacing;
|
|
54
|
+
const niceMax = Math.ceil(maxPoint / tickSpacing) * tickSpacing;
|
|
55
|
+
const tickCount = range / tickSpacing;
|
|
56
|
+
return [tickCount, niceMin, niceMax];
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Returns a "nice" number approximately equal to range
|
|
61
|
+
* Rounds the number if round = true
|
|
62
|
+
* Takes the ceiling if round = false.
|
|
63
|
+
* A nice number is a simple decimal number, for example if a number is 1234, a nice number would be 1000 or 2000.
|
|
64
|
+
*/
|
|
65
|
+
export const niceNum = ({
|
|
66
|
+
range,
|
|
67
|
+
roundDown
|
|
68
|
+
}) => {
|
|
69
|
+
const exponent = Math.floor(Math.log10(range));
|
|
70
|
+
const fraction = range / 10 ** exponent;
|
|
71
|
+
let niceFraction;
|
|
72
|
+
if (roundDown) {
|
|
73
|
+
if (fraction < 1.5) niceFraction = 1;else if (fraction < 3) niceFraction = 2;else if (fraction < 7) niceFraction = 5;else niceFraction = 10;
|
|
74
|
+
} else if (fraction <= 1) niceFraction = 1;else if (fraction <= 2) niceFraction = 2;else if (fraction <= 5) niceFraction = 5;else niceFraction = 10;
|
|
75
|
+
return niceFraction * 10 ** exponent;
|
|
76
|
+
};
|
|
77
|
+
export const getPercentDiff = ({
|
|
78
|
+
v1,
|
|
79
|
+
v2
|
|
80
|
+
}) => {
|
|
81
|
+
return Math.abs(v1 - v2) / ((v1 + v2) / 2) * 100;
|
|
82
|
+
};
|
|
83
|
+
export const formatNumberUS = ({
|
|
84
|
+
num
|
|
85
|
+
}) => Intl.NumberFormat('en').format(num);
|
|
86
|
+
export const formatNumberUSCompact = ({
|
|
87
|
+
num
|
|
88
|
+
}) => Intl.NumberFormat('en', {
|
|
89
|
+
notation: 'compact',
|
|
90
|
+
compactDisplay: 'short'
|
|
91
|
+
}).format(num);
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Sort bars based on sortBy and order configuration
|
|
95
|
+
*/
|
|
96
|
+
export const sortBars = ({
|
|
97
|
+
bars,
|
|
98
|
+
sortBy,
|
|
99
|
+
order
|
|
100
|
+
}) => {
|
|
101
|
+
if (sortBy === 'none' || !sortBy) {
|
|
102
|
+
return bars;
|
|
103
|
+
}
|
|
104
|
+
const sorted = [...bars].sort((a, b) => {
|
|
105
|
+
if (sortBy === 'label') {
|
|
106
|
+
return a.yLabel.localeCompare(b.yLabel);
|
|
107
|
+
}
|
|
108
|
+
// sortBy === 'value' - use seriesTwoValue if available, otherwise seriesOneValue
|
|
109
|
+
const aValue = a.seriesTwoValue ?? a.seriesOneValue;
|
|
110
|
+
const bValue = b.seriesTwoValue ?? b.seriesOneValue;
|
|
111
|
+
return aValue - bValue;
|
|
112
|
+
});
|
|
113
|
+
return order === 'descending' ? sorted.reverse() : sorted;
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Generates an accessible summary of the bar values
|
|
118
|
+
*/
|
|
119
|
+
export const getValuesSummary = ({
|
|
120
|
+
yLabel,
|
|
121
|
+
seriesOneValue,
|
|
122
|
+
seriesTwoValue,
|
|
123
|
+
unit
|
|
124
|
+
}) => {
|
|
125
|
+
if (seriesTwoValue !== undefined) {
|
|
126
|
+
const gained = seriesOneValue;
|
|
127
|
+
return `${gained} ${unit} gained - now at ${seriesTwoValue} ${unit} in ${yLabel} category`;
|
|
128
|
+
}
|
|
129
|
+
return `${seriesOneValue} ${unit} in ${yLabel} category`;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Calculates the value for a given label position
|
|
134
|
+
*/
|
|
135
|
+
export const getLabel = ({
|
|
136
|
+
labelCount,
|
|
137
|
+
labelIndex,
|
|
138
|
+
min,
|
|
139
|
+
max
|
|
140
|
+
}) => {
|
|
141
|
+
if (labelCount <= 1) return max;
|
|
142
|
+
const incrementalDecimal = labelIndex / (labelCount - 1);
|
|
143
|
+
return Math.floor(min + incrementalDecimal * (max - min));
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Calculates the percentage position for a given value within a range
|
|
148
|
+
* Returns a value between 0 and 100 representing the position percentage
|
|
149
|
+
*/
|
|
150
|
+
export const calculatePositionPercent = ({
|
|
151
|
+
value,
|
|
152
|
+
min,
|
|
153
|
+
max
|
|
154
|
+
}) => {
|
|
155
|
+
if (max === min) return 0;
|
|
156
|
+
const range = max - min;
|
|
157
|
+
const adjustedValue = value - min;
|
|
158
|
+
return adjustedValue / range * 100;
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
// Re-export hooks
|
|
162
|
+
export { useBarChart, useBarChartContext, useLabelPositions } from './hooks';
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codecademy/gamut",
|
|
3
3
|
"description": "Styleguide & Component library for Codecademy",
|
|
4
|
-
"version": "67.6.
|
|
4
|
+
"version": "67.6.3-alpha.22c4b5.0",
|
|
5
5
|
"author": "Codecademy Engineering <dev@codecademy.com>",
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@codecademy/gamut-icons": "9.54.0",
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"dist/**/[A-Z]**/[A-Z]*.js",
|
|
57
57
|
"dist/**/[A-Z]**/index.js"
|
|
58
58
|
],
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "6595237ef4895b7e05deba508a22738f9cdf07aa"
|
|
60
60
|
}
|