@coinbase/cds-web-visualization 0.0.0 → 3.3.2
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/CHANGELOG.md +25 -0
- package/README.md +3 -0
- package/dts/index.d.ts +2 -0
- package/dts/index.d.ts.map +1 -0
- package/dts/sparkline/Counter.d.ts +8 -0
- package/dts/sparkline/Counter.d.ts.map +1 -0
- package/dts/sparkline/Sparkline.d.ts +32 -0
- package/dts/sparkline/Sparkline.d.ts.map +1 -0
- package/dts/sparkline/SparklineArea.d.ts +11 -0
- package/dts/sparkline/SparklineArea.d.ts.map +1 -0
- package/dts/sparkline/SparklineAreaPattern.d.ts +9 -0
- package/dts/sparkline/SparklineAreaPattern.d.ts.map +1 -0
- package/dts/sparkline/SparklineGradient.d.ts +18 -0
- package/dts/sparkline/SparklineGradient.d.ts.map +1 -0
- package/dts/sparkline/SparklinePath.d.ts +12 -0
- package/dts/sparkline/SparklinePath.d.ts.map +1 -0
- package/dts/sparkline/__figma__/Sparkline.figma.d.ts +2 -0
- package/dts/sparkline/__figma__/Sparkline.figma.d.ts.map +1 -0
- package/dts/sparkline/generateSparklineWithId.d.ts +10 -0
- package/dts/sparkline/generateSparklineWithId.d.ts.map +1 -0
- package/dts/sparkline/index.d.ts +6 -0
- package/dts/sparkline/index.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/InnerSparklineInteractiveProvider.d.ts +13 -0
- package/dts/sparkline/sparkline-interactive/InnerSparklineInteractiveProvider.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts +190 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractive.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts +23 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts +5 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.d.ts +5 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts +8 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts +17 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts +24 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractivePaths.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts +25 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts +25 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveProvider.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.d.ts +30 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubProvider.d.ts +18 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveScrubProvider.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts +31 -0
- package/dts/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts +2 -0
- package/dts/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/fade.d.ts +3 -0
- package/dts/sparkline/sparkline-interactive/fade.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts +13 -0
- package/dts/sparkline/sparkline-interactive/useSparklineInteractiveConstants.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.d.ts +112 -0
- package/dts/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.d.ts.map +1 -0
- package/dts/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.d.ts +2 -0
- package/dts/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.d.ts.map +1 -0
- package/esm/index.js +1 -0
- package/esm/sparkline/Counter.css +3 -0
- package/esm/sparkline/Counter.js +35 -0
- package/esm/sparkline/Sparkline.js +50 -0
- package/esm/sparkline/SparklineArea.js +13 -0
- package/esm/sparkline/SparklineAreaPattern.js +35 -0
- package/esm/sparkline/SparklineGradient.js +72 -0
- package/esm/sparkline/SparklinePath.js +19 -0
- package/esm/sparkline/__figma__/Sparkline.figma.js +24 -0
- package/esm/sparkline/generateSparklineWithId.js +6 -0
- package/esm/sparkline/index.js +5 -0
- package/esm/sparkline/sparkline-interactive/InnerSparklineInteractiveProvider.js +21 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractive.js +313 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveAnimatedPath.js +105 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.css +2 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverDate.js +26 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.css +2 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveHoverPrice.js +24 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.css +4 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveLineVertical.js +65 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.css +1 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveMarkerDates.js +84 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractivePaths.js +52 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractivePeriodSelector.js +70 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveProvider.js +45 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.css +5 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveScrubHandler.js +199 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveScrubProvider.js +39 -0
- package/esm/sparkline/sparkline-interactive/SparklineInteractiveTimeseriesPaths.js +92 -0
- package/esm/sparkline/sparkline-interactive/__figma__/SparklineInteractive.figma.js +89 -0
- package/esm/sparkline/sparkline-interactive/fade.css +2 -0
- package/esm/sparkline/sparkline-interactive/fade.js +14 -0
- package/esm/sparkline/sparkline-interactive/useSparklineInteractiveConstants.js +28 -0
- package/esm/sparkline/sparkline-interactive-header/SparklineInteractiveHeader.js +225 -0
- package/esm/sparkline/sparkline-interactive-header/__figma__/SparklineInteractiveHeader.figma.js +108 -0
- package/package.json +64 -6
- package/index.js +0 -1
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React, { memo, useCallback, useRef } from 'react';
|
|
2
|
+
import { chartCompactHeight, chartHeight } from '@coinbase/cds-common/tokens/sparkline';
|
|
3
|
+
import { SparklineInteractiveAnimatedPath } from './SparklineInteractiveAnimatedPath';
|
|
4
|
+
import { SparklineInteractiveTimeseriesPaths } from './SparklineInteractiveTimeseriesPaths';
|
|
5
|
+
import { useSparklineInteractiveConstants } from './useSparklineInteractiveConstants';
|
|
6
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
7
|
+
function SparklineInteractivePathsWithGeneric(_ref) {
|
|
8
|
+
let {
|
|
9
|
+
showHoverData,
|
|
10
|
+
fill,
|
|
11
|
+
path,
|
|
12
|
+
area,
|
|
13
|
+
selectedPeriod,
|
|
14
|
+
yAxisScalingFactor,
|
|
15
|
+
strokeColor,
|
|
16
|
+
hoverData,
|
|
17
|
+
compact
|
|
18
|
+
} = _ref;
|
|
19
|
+
const hoverPathRef = useRef(undefined);
|
|
20
|
+
const hoverAreaRef = useRef(undefined);
|
|
21
|
+
const shouldShowFill = !!fill;
|
|
22
|
+
const {
|
|
23
|
+
chartWidth
|
|
24
|
+
} = useSparklineInteractiveConstants();
|
|
25
|
+
const innerSparklineInteractiveHeight = compact ? chartCompactHeight : chartHeight;
|
|
26
|
+
const handleMultiTimeseriesRender = useCallback(_ref2 => {
|
|
27
|
+
let {
|
|
28
|
+
area: timeseriesArea,
|
|
29
|
+
path: timeseriesPath
|
|
30
|
+
} = _ref2;
|
|
31
|
+
hoverPathRef.current = timeseriesPath;
|
|
32
|
+
hoverAreaRef.current = timeseriesArea;
|
|
33
|
+
}, []);
|
|
34
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
35
|
+
children: [!showHoverData && /*#__PURE__*/_jsx(SparklineInteractiveAnimatedPath, {
|
|
36
|
+
area: shouldShowFill ? area : undefined,
|
|
37
|
+
color: strokeColor,
|
|
38
|
+
d: path,
|
|
39
|
+
initialArea: hoverAreaRef.current,
|
|
40
|
+
initialPath: hoverPathRef.current,
|
|
41
|
+
selectedPeriod: selectedPeriod,
|
|
42
|
+
yAxisScalingFactor: yAxisScalingFactor
|
|
43
|
+
}), !!showHoverData && /*#__PURE__*/_jsx(SparklineInteractiveTimeseriesPaths, {
|
|
44
|
+
data: hoverData === null || hoverData === void 0 ? void 0 : hoverData[selectedPeriod],
|
|
45
|
+
height: innerSparklineInteractiveHeight,
|
|
46
|
+
initialPath: path,
|
|
47
|
+
onRender: handleMultiTimeseriesRender,
|
|
48
|
+
width: chartWidth
|
|
49
|
+
})]
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
export const SparklineInteractivePaths = /*#__PURE__*/memo(SparklineInteractivePathsWithGeneric);
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import React, { memo, useCallback, useMemo } from 'react';
|
|
2
|
+
import { periodLabelMap } from '@coinbase/cds-common/tokens/sparkline';
|
|
3
|
+
import { getAccessibleColor } from '@coinbase/cds-common/utils/getAccessibleColor';
|
|
4
|
+
import { useTheme } from '@coinbase/cds-web/hooks/useTheme';
|
|
5
|
+
import { Box, HStack } from '@coinbase/cds-web/layout';
|
|
6
|
+
import { Pressable } from '@coinbase/cds-web/system/Pressable';
|
|
7
|
+
import { TextLabel1 } from '@coinbase/cds-web/typography/TextLabel1';
|
|
8
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
9
|
+
function SparklineInteractivePeriodWithGeneric(_ref) {
|
|
10
|
+
var _periodLabelMap$perio;
|
|
11
|
+
let {
|
|
12
|
+
period,
|
|
13
|
+
selectedPeriod,
|
|
14
|
+
setSelectedPeriod,
|
|
15
|
+
color
|
|
16
|
+
} = _ref;
|
|
17
|
+
const periodLabel = (_periodLabelMap$perio = periodLabelMap[period.label]) !== null && _periodLabelMap$perio !== void 0 ? _periodLabelMap$perio : period.label;
|
|
18
|
+
const isSelected = period.value === selectedPeriod;
|
|
19
|
+
const handleOnClick = useCallback(() => {
|
|
20
|
+
setSelectedPeriod(period.value);
|
|
21
|
+
}, [period, setSelectedPeriod]);
|
|
22
|
+
const background = useMemo(() => isSelected ? 'bgPrimaryWash' : 'transparent', [isSelected]);
|
|
23
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
24
|
+
alignItems: "center",
|
|
25
|
+
height: "fit-content",
|
|
26
|
+
justifyContent: "center",
|
|
27
|
+
children: /*#__PURE__*/_jsx(Pressable, {
|
|
28
|
+
accessibilityLabel: periodLabel,
|
|
29
|
+
"aria-pressed": isSelected,
|
|
30
|
+
background: background,
|
|
31
|
+
borderRadius: 200,
|
|
32
|
+
onClick: handleOnClick,
|
|
33
|
+
children: /*#__PURE__*/_jsx(TextLabel1, {
|
|
34
|
+
noWrap: true,
|
|
35
|
+
as: "span",
|
|
36
|
+
dangerouslySetColor: isSelected ? color : 'var(--color-fgMuted)',
|
|
37
|
+
display: "block",
|
|
38
|
+
paddingX: 2,
|
|
39
|
+
paddingY: 1,
|
|
40
|
+
children: period.label
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
const SparklineInteractivePeriod = /*#__PURE__*/memo(SparklineInteractivePeriodWithGeneric);
|
|
46
|
+
export const SparklineInteractivePeriodSelector = _ref2 => {
|
|
47
|
+
let {
|
|
48
|
+
selectedPeriod,
|
|
49
|
+
setSelectedPeriod,
|
|
50
|
+
periods,
|
|
51
|
+
color
|
|
52
|
+
} = _ref2;
|
|
53
|
+
const theme = useTheme();
|
|
54
|
+
const accessibleForeground = color !== 'auto' ? color : getAccessibleColor({
|
|
55
|
+
background: theme.color.bg,
|
|
56
|
+
foreground: 'auto',
|
|
57
|
+
enhanced: true
|
|
58
|
+
});
|
|
59
|
+
return /*#__PURE__*/_jsx(HStack, {
|
|
60
|
+
justifyContent: "space-between",
|
|
61
|
+
paddingX: 1,
|
|
62
|
+
width: "100%",
|
|
63
|
+
children: periods.map(period => /*#__PURE__*/_jsx(SparklineInteractivePeriod, {
|
|
64
|
+
color: accessibleForeground,
|
|
65
|
+
period: period,
|
|
66
|
+
selectedPeriod: selectedPeriod,
|
|
67
|
+
setSelectedPeriod: setSelectedPeriod
|
|
68
|
+
}, period.value))
|
|
69
|
+
});
|
|
70
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React, { createContext, memo, useCallback, useContext, useMemo, useState } from 'react';
|
|
2
|
+
import { noop } from '@coinbase/cds-utils';
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
const SparklineInteractiveContext = /*#__PURE__*/createContext({
|
|
5
|
+
isFallbackVisible: true,
|
|
6
|
+
compact: false,
|
|
7
|
+
width: 0,
|
|
8
|
+
height: 0,
|
|
9
|
+
showFallback: noop,
|
|
10
|
+
hideFallback: noop,
|
|
11
|
+
setWidth: noop,
|
|
12
|
+
setHeight: noop
|
|
13
|
+
});
|
|
14
|
+
export const SparklineInteractiveProvider = /*#__PURE__*/memo(_ref => {
|
|
15
|
+
let {
|
|
16
|
+
children,
|
|
17
|
+
compact = false
|
|
18
|
+
} = _ref;
|
|
19
|
+
const [isFallbackVisible, setIsFallbackVisible] = useState(true);
|
|
20
|
+
const [width, setWidth] = useState(0);
|
|
21
|
+
const [height, setHeight] = useState(0);
|
|
22
|
+
const showFallback = useCallback(() => {
|
|
23
|
+
setIsFallbackVisible(true);
|
|
24
|
+
}, [setIsFallbackVisible]);
|
|
25
|
+
const hideFallback = useCallback(() => {
|
|
26
|
+
setIsFallbackVisible(false);
|
|
27
|
+
}, [setIsFallbackVisible]);
|
|
28
|
+
const value = useMemo(() => ({
|
|
29
|
+
compact,
|
|
30
|
+
width,
|
|
31
|
+
height,
|
|
32
|
+
showFallback,
|
|
33
|
+
hideFallback,
|
|
34
|
+
isFallbackVisible,
|
|
35
|
+
setHeight,
|
|
36
|
+
setWidth
|
|
37
|
+
}), [compact, height, hideFallback, isFallbackVisible, showFallback, width]);
|
|
38
|
+
return /*#__PURE__*/_jsx(SparklineInteractiveContext.Provider, {
|
|
39
|
+
value: value,
|
|
40
|
+
children: children
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
export function useSparklineInteractiveContext() {
|
|
44
|
+
return useContext(SparklineInteractiveContext);
|
|
45
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
.cds-insetFocusRingCss-is0dyrn{position:relative;}.cds-insetFocusRingCss-is0dyrn:focus{outline:none;}.cds-insetFocusRingCss-is0dyrn:focus-visible{outline-style:solid;outline-width:2px;outline-color:var(--color-bgPrimary);outline-offset:0;}
|
|
2
|
+
.cds-scrubHandlerContainerCss-s9euk9d{position:relative;width:100%;height:100%;}
|
|
3
|
+
.cds-scrubHandlerCss-s6b8h5z.cds-sparkline--scrubhandler{position:absolute;width:100%;height:100%;top:0;left:0;}
|
|
4
|
+
.cds-fadeInMaskCss-f1bwvdrs.cds-fadeInMaskCss-f1bwvdrs{-webkit-animation:cdsSparklineInteractiveScrubFadeInMask-cds-fadeInMaskCss-f1bwvdrs 200ms cubic-bezier(0.6,0,0.15,1);animation:cdsSparklineInteractiveScrubFadeInMask-cds-fadeInMaskCss-f1bwvdrs 200ms cubic-bezier(0.6,0,0.15,1);opacity:0.8;}@-webkit-keyframes cdsSparklineInteractiveScrubFadeInMask-cds-fadeInMaskCss-f1bwvdrs{0%{opacity:0;}100%{opacity:0.8;}}@keyframes cdsSparklineInteractiveScrubFadeInMask-cds-fadeInMaskCss-f1bwvdrs{0%{opacity:0;}100%{opacity:0.8;}}
|
|
5
|
+
.cds-fadeOutMaskCss-f19rjrl4.cds-fadeOutMaskCss-f19rjrl4{-webkit-animation:cdsSparklineInteractiveScrubFadeOutMask-cds-fadeOutMaskCss-f19rjrl4 200ms cubic-bezier(0.6,0,0.15,1);animation:cdsSparklineInteractiveScrubFadeOutMask-cds-fadeOutMaskCss-f19rjrl4 200ms cubic-bezier(0.6,0,0.15,1);opacity:0;}@-webkit-keyframes cdsSparklineInteractiveScrubFadeOutMask-cds-fadeOutMaskCss-f19rjrl4{0%{opacity:0.8;}100%{opacity:0;}}@keyframes cdsSparklineInteractiveScrubFadeOutMask-cds-fadeOutMaskCss-f19rjrl4{0%{opacity:0.8;}100%{opacity:0;}}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import React, { memo, useCallback, useMemo, useRef, useState } from 'react';
|
|
2
|
+
import { fadeDuration, maskOpacity } from '@coinbase/cds-common/tokens/sparkline';
|
|
3
|
+
import { debounce } from '@coinbase/cds-common/utils/debounce';
|
|
4
|
+
import { noop } from '@coinbase/cds-utils';
|
|
5
|
+
import { cx } from '@coinbase/cds-web';
|
|
6
|
+
import { cubicBezier } from '@coinbase/cds-web/animation/convertMotionConfig';
|
|
7
|
+
import { useDimensions } from '@coinbase/cds-web/hooks/useDimensions';
|
|
8
|
+
import { fadeIn, fadeOut } from './fade';
|
|
9
|
+
import { useSparklineInteractiveContext } from './SparklineInteractiveProvider';
|
|
10
|
+
import { useSparklineInteractiveScrubContext } from './SparklineInteractiveScrubProvider';
|
|
11
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
|
+
export const scrubHandlerStaticClassName = 'cds-sparkline--scrubhandler';
|
|
13
|
+
const insetFocusRingCss = "cds-insetFocusRingCss-is0dyrn";
|
|
14
|
+
const scrubHandlerContainerCss = "cds-scrubHandlerContainerCss-s9euk9d";
|
|
15
|
+
const scrubHandlerCss = "cds-scrubHandlerCss-s6b8h5z";
|
|
16
|
+
const fadeInMaskCss = "cds-fadeInMaskCss-f1bwvdrs";
|
|
17
|
+
const fadeOutMaskCss = "cds-fadeOutMaskCss-f19rjrl4";
|
|
18
|
+
|
|
19
|
+
// Number of steps for keyboard users to navigate through the sparkline
|
|
20
|
+
const STEPS = 100;
|
|
21
|
+
const STEPS_ARRAY = Array.from(Array(STEPS).keys());
|
|
22
|
+
const padding = 8;
|
|
23
|
+
function fadeOutMask(domNode) {
|
|
24
|
+
domNode === null || domNode === void 0 || domNode.classList.remove(fadeInMaskCss);
|
|
25
|
+
domNode === null || domNode === void 0 || domNode.classList.add(fadeOutMaskCss);
|
|
26
|
+
}
|
|
27
|
+
export function fadeInMask(domNode) {
|
|
28
|
+
domNode === null || domNode === void 0 || domNode.classList.add(fadeInMaskCss);
|
|
29
|
+
domNode === null || domNode === void 0 || domNode.classList.remove(fadeOutMaskCss);
|
|
30
|
+
}
|
|
31
|
+
const SparklineInteractiveScrubHandlerWithGeneric = _ref => {
|
|
32
|
+
let {
|
|
33
|
+
onScrubEnd = noop,
|
|
34
|
+
onScrubStart = noop,
|
|
35
|
+
children,
|
|
36
|
+
disabled,
|
|
37
|
+
onScrub,
|
|
38
|
+
getMarker,
|
|
39
|
+
selectedPeriod,
|
|
40
|
+
formatHoverDate,
|
|
41
|
+
formatHoverPrice
|
|
42
|
+
} = _ref;
|
|
43
|
+
const containerRef = useRef(null);
|
|
44
|
+
const {
|
|
45
|
+
lineDOMNode,
|
|
46
|
+
maskDOMNode,
|
|
47
|
+
hoverDateDOMNode,
|
|
48
|
+
hoverPriceDOMNode
|
|
49
|
+
} = useSparklineInteractiveScrubContext();
|
|
50
|
+
const {
|
|
51
|
+
width: chartWidth
|
|
52
|
+
} = useSparklineInteractiveContext();
|
|
53
|
+
const scrubHandlerCssWithFocus = cx(scrubHandlerStaticClassName, scrubHandlerCss, insetFocusRingCss);
|
|
54
|
+
const [xPos, setXPos] = useState(0);
|
|
55
|
+
const {
|
|
56
|
+
width,
|
|
57
|
+
observe
|
|
58
|
+
} = useDimensions();
|
|
59
|
+
const steps = useMemo(() => {
|
|
60
|
+
const sparklineSteps = STEPS_ARRAY.map(step => {
|
|
61
|
+
return Math.floor(Number(width) / STEPS * step) || 1;
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Make sure each step is within the sparkline container
|
|
65
|
+
sparklineSteps[0] = 1;
|
|
66
|
+
sparklineSteps[STEPS] = Math.floor(width) - 1;
|
|
67
|
+
return sparklineSteps;
|
|
68
|
+
}, [width]);
|
|
69
|
+
const debouncedUpdatePositionHandler = useMemo(() => debounce(position => {
|
|
70
|
+
setXPos(position);
|
|
71
|
+
}, 20), [setXPos]);
|
|
72
|
+
const safelyUpdatePosition = useCallback(debouncedUpdatePositionHandler, [debouncedUpdatePositionHandler]);
|
|
73
|
+
|
|
74
|
+
// This method is used by mouseMove and keyboard events
|
|
75
|
+
const updateScrubber = useCallback(position => {
|
|
76
|
+
const dataPoint = getMarker(position);
|
|
77
|
+
if (dataPoint) {
|
|
78
|
+
onScrub === null || onScrub === void 0 || onScrub({
|
|
79
|
+
point: dataPoint,
|
|
80
|
+
period: selectedPeriod
|
|
81
|
+
});
|
|
82
|
+
if (lineDOMNode) {
|
|
83
|
+
lineDOMNode.style.transform = "translateX(".concat(position, "px)");
|
|
84
|
+
}
|
|
85
|
+
if (maskDOMNode) {
|
|
86
|
+
maskDOMNode.style.transform = "translateX(".concat(position, "px)");
|
|
87
|
+
}
|
|
88
|
+
if (hoverDateDOMNode && formatHoverDate) {
|
|
89
|
+
fadeIn(hoverDateDOMNode);
|
|
90
|
+
hoverDateDOMNode.innerText = formatHoverDate(dataPoint.date, selectedPeriod);
|
|
91
|
+
const textWidth = hoverDateDOMNode.offsetWidth;
|
|
92
|
+
const halfTextWidth = textWidth / 2;
|
|
93
|
+
let textPos = position - halfTextWidth;
|
|
94
|
+
textPos = Math.max(padding, textPos);
|
|
95
|
+
textPos = Math.min(textPos, chartWidth - textWidth - padding);
|
|
96
|
+
hoverDateDOMNode.style.transform = "translateX(".concat(textPos, "px)");
|
|
97
|
+
}
|
|
98
|
+
if (hoverPriceDOMNode && formatHoverPrice) {
|
|
99
|
+
fadeIn(hoverPriceDOMNode);
|
|
100
|
+
hoverPriceDOMNode.innerText = formatHoverPrice(dataPoint.value);
|
|
101
|
+
const textWidth = hoverPriceDOMNode.offsetWidth;
|
|
102
|
+
const halfTextWidth = textWidth / 2;
|
|
103
|
+
let textPos = position - halfTextWidth;
|
|
104
|
+
textPos = Math.max(padding, textPos);
|
|
105
|
+
textPos = Math.min(textPos, chartWidth - textWidth - padding);
|
|
106
|
+
hoverPriceDOMNode.style.transform = "translateX(".concat(textPos, "px)");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Keep track of the position for a seamless
|
|
112
|
+
* transition from MouseMove to Keyboard interaction
|
|
113
|
+
*/
|
|
114
|
+
safelyUpdatePosition(position);
|
|
115
|
+
}, [getMarker, safelyUpdatePosition, onScrub, selectedPeriod, lineDOMNode, maskDOMNode, hoverDateDOMNode, formatHoverDate, formatHoverPrice, hoverPriceDOMNode, chartWidth]);
|
|
116
|
+
|
|
117
|
+
// Show the scrub UI
|
|
118
|
+
const handleMouseEnter = useCallback(() => {
|
|
119
|
+
onScrubStart === null || onScrubStart === void 0 || onScrubStart();
|
|
120
|
+
fadeIn(lineDOMNode);
|
|
121
|
+
fadeInMask(maskDOMNode);
|
|
122
|
+
}, [lineDOMNode, maskDOMNode, onScrubStart]);
|
|
123
|
+
const handleMouseMove = useCallback(event => {
|
|
124
|
+
var _containerRef$current, _containerRef$current2;
|
|
125
|
+
const xPosition = Math.max(0, event.clientX - ((_containerRef$current = (_containerRef$current2 = containerRef.current) === null || _containerRef$current2 === void 0 ? void 0 : _containerRef$current2.getBoundingClientRect().left) !== null && _containerRef$current !== void 0 ? _containerRef$current : 0));
|
|
126
|
+
|
|
127
|
+
// Update UI
|
|
128
|
+
updateScrubber(xPosition);
|
|
129
|
+
}, [updateScrubber]);
|
|
130
|
+
const getPosition = useCallback((direction, multiSkip) => {
|
|
131
|
+
// Use the xPos to find the nearest step
|
|
132
|
+
const closestStep = steps.reduce((prev, curr) => {
|
|
133
|
+
return Math.abs(curr - xPos) < Math.abs(prev - xPos) ? curr : prev;
|
|
134
|
+
});
|
|
135
|
+
// The index of the closest step
|
|
136
|
+
const currentIndex = steps.findIndex(pos => pos === closestStep);
|
|
137
|
+
// Holding the shift key allows users to jump 10 steps
|
|
138
|
+
const stepIncrement = multiSkip ? 10 : 1;
|
|
139
|
+
|
|
140
|
+
// The location to move to
|
|
141
|
+
const nextLocation = currentIndex + (direction === 'next' ? stepIncrement : -stepIncrement);
|
|
142
|
+
|
|
143
|
+
// return the location if we're within bounds of the chart
|
|
144
|
+
return nextLocation > 0 && nextLocation < STEPS ? nextLocation : null;
|
|
145
|
+
}, [steps, xPos]);
|
|
146
|
+
const handleKeyDown = useCallback(e => {
|
|
147
|
+
const multiSkip = !!e.shiftKey;
|
|
148
|
+
|
|
149
|
+
// Go to the correct step
|
|
150
|
+
if (e.key === 'ArrowRight') {
|
|
151
|
+
var _getPosition;
|
|
152
|
+
e.preventDefault();
|
|
153
|
+
const nextStep = (_getPosition = getPosition('next', multiSkip)) !== null && _getPosition !== void 0 ? _getPosition : STEPS;
|
|
154
|
+
updateScrubber(steps[nextStep] - 1);
|
|
155
|
+
}
|
|
156
|
+
if (e.key === 'ArrowLeft') {
|
|
157
|
+
var _getPosition2;
|
|
158
|
+
e.preventDefault();
|
|
159
|
+
const previousStep = (_getPosition2 = getPosition('previous', multiSkip)) !== null && _getPosition2 !== void 0 ? _getPosition2 : 0;
|
|
160
|
+
updateScrubber(steps[previousStep]);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Jump to beginning or end
|
|
164
|
+
if (e.key === 'ArrowDown') {
|
|
165
|
+
e.preventDefault();
|
|
166
|
+
updateScrubber(steps[STEPS] - 1);
|
|
167
|
+
}
|
|
168
|
+
if (e.key === 'ArrowUp') {
|
|
169
|
+
e.preventDefault();
|
|
170
|
+
updateScrubber(0);
|
|
171
|
+
}
|
|
172
|
+
}, [getPosition, updateScrubber, steps]);
|
|
173
|
+
const handleMouseLeave = useCallback(() => {
|
|
174
|
+
onScrubEnd === null || onScrubEnd === void 0 || onScrubEnd();
|
|
175
|
+
fadeOut(lineDOMNode);
|
|
176
|
+
fadeOutMask(maskDOMNode);
|
|
177
|
+
fadeOut(hoverDateDOMNode);
|
|
178
|
+
fadeOut(hoverPriceDOMNode);
|
|
179
|
+
}, [hoverDateDOMNode, lineDOMNode, maskDOMNode, hoverPriceDOMNode, onScrubEnd]);
|
|
180
|
+
return /*#__PURE__*/_jsxs("div", {
|
|
181
|
+
ref: containerRef,
|
|
182
|
+
className: scrubHandlerContainerCss,
|
|
183
|
+
children: [children, !disabled && /*#__PURE__*/_jsx("div", {
|
|
184
|
+
ref: observe,
|
|
185
|
+
"aria-label": "Price chart (use arrow keys to adjust view)",
|
|
186
|
+
className: scrubHandlerCssWithFocus,
|
|
187
|
+
onBlur: handleMouseLeave,
|
|
188
|
+
onFocus: handleMouseEnter,
|
|
189
|
+
onKeyDown: handleKeyDown,
|
|
190
|
+
onMouseEnter: handleMouseEnter,
|
|
191
|
+
onMouseLeave: handleMouseLeave,
|
|
192
|
+
onMouseMove: handleMouseMove,
|
|
193
|
+
role: "button",
|
|
194
|
+
tabIndex: 0
|
|
195
|
+
})]
|
|
196
|
+
});
|
|
197
|
+
};
|
|
198
|
+
export const SparklineInteractiveScrubHandler = /*#__PURE__*/memo(SparklineInteractiveScrubHandlerWithGeneric);
|
|
199
|
+
import "./SparklineInteractiveScrubHandler.css";
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React, { createContext, memo, useContext, useMemo, useState } from 'react';
|
|
2
|
+
import { noop } from '@coinbase/cds-utils';
|
|
3
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
4
|
+
const SparklineInteractiveScrubContext = /*#__PURE__*/createContext({
|
|
5
|
+
setLineDOMNode: noop,
|
|
6
|
+
setMaskDOMNode: noop,
|
|
7
|
+
setHoverDateDOMNode: noop,
|
|
8
|
+
setHoverPriceDOMNode: noop,
|
|
9
|
+
lineDOMNode: null,
|
|
10
|
+
maskDOMNode: null,
|
|
11
|
+
hoverDateDOMNode: null,
|
|
12
|
+
hoverPriceDOMNode: null
|
|
13
|
+
});
|
|
14
|
+
export const SparklineInteractiveScrubProvider = /*#__PURE__*/memo(_ref => {
|
|
15
|
+
let {
|
|
16
|
+
children
|
|
17
|
+
} = _ref;
|
|
18
|
+
const [lineDOMNode, setLineDOMNode] = useState(null);
|
|
19
|
+
const [maskDOMNode, setMaskDOMNode] = useState(null);
|
|
20
|
+
const [hoverDateDOMNode, setHoverDateDOMNode] = useState(null);
|
|
21
|
+
const [hoverPriceDOMNode, setHoverPriceDOMNode] = useState(null);
|
|
22
|
+
const value = useMemo(() => ({
|
|
23
|
+
setLineDOMNode,
|
|
24
|
+
setMaskDOMNode,
|
|
25
|
+
lineDOMNode,
|
|
26
|
+
maskDOMNode,
|
|
27
|
+
hoverDateDOMNode,
|
|
28
|
+
setHoverDateDOMNode,
|
|
29
|
+
setHoverPriceDOMNode,
|
|
30
|
+
hoverPriceDOMNode
|
|
31
|
+
}), [hoverDateDOMNode, lineDOMNode, maskDOMNode, hoverPriceDOMNode]);
|
|
32
|
+
return /*#__PURE__*/_jsx(SparklineInteractiveScrubContext.Provider, {
|
|
33
|
+
value: value,
|
|
34
|
+
children: children
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
export function useSparklineInteractiveScrubContext() {
|
|
38
|
+
return useContext(SparklineInteractiveScrubContext);
|
|
39
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
3
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
6
|
+
import React, { memo, useCallback, useEffect, useMemo, useRef } from 'react';
|
|
7
|
+
import { animatedPathConfig } from '@coinbase/cds-common/animation/sparkline';
|
|
8
|
+
import { getAccessibleColor } from '@coinbase/cds-common/utils/getAccessibleColor';
|
|
9
|
+
import { getSparklineTransform } from '@coinbase/cds-common/visualizations/getSparklineTransform';
|
|
10
|
+
import { useTimeseriesPaths } from '@coinbase/cds-common/visualizations/useTimeseriesPaths';
|
|
11
|
+
import { useTheme } from '@coinbase/cds-web/hooks/useTheme';
|
|
12
|
+
import { interpolatePath } from 'd3-interpolate-path';
|
|
13
|
+
import { select } from 'd3-selection';
|
|
14
|
+
import { SparklinePath } from '../SparklinePath';
|
|
15
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
16
|
+
const {
|
|
17
|
+
duration,
|
|
18
|
+
easing
|
|
19
|
+
} = animatedPathConfig;
|
|
20
|
+
const TimeseriesPath = /*#__PURE__*/memo(_ref => {
|
|
21
|
+
let {
|
|
22
|
+
timeseries,
|
|
23
|
+
lineFn,
|
|
24
|
+
initialPath,
|
|
25
|
+
onRender,
|
|
26
|
+
areaFn
|
|
27
|
+
} = _ref;
|
|
28
|
+
const theme = useTheme();
|
|
29
|
+
const pathRef = useRef(null);
|
|
30
|
+
const {
|
|
31
|
+
strokeColor
|
|
32
|
+
} = timeseries;
|
|
33
|
+
const lineColor = strokeColor !== 'auto' ? strokeColor : getAccessibleColor({
|
|
34
|
+
background: theme.color.bg,
|
|
35
|
+
foreground: 'auto',
|
|
36
|
+
usage: 'graphic'
|
|
37
|
+
});
|
|
38
|
+
const newPath = useMemo(() => lineFn(timeseries.points), [lineFn, timeseries.points]);
|
|
39
|
+
const newArea = useMemo(() => onRender ? areaFn(timeseries.points) : null, [areaFn, onRender, timeseries.points]);
|
|
40
|
+
const playAnimation = useCallback(() => {
|
|
41
|
+
select(pathRef.current).transition().duration(duration).ease(easing).attrTween('d', function tween() {
|
|
42
|
+
const current = newPath;
|
|
43
|
+
return interpolatePath(initialPath, current);
|
|
44
|
+
});
|
|
45
|
+
}, [initialPath, newPath]);
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
playAnimation();
|
|
48
|
+
onRender === null || onRender === void 0 || onRender({
|
|
49
|
+
path: newPath,
|
|
50
|
+
area: newArea
|
|
51
|
+
});
|
|
52
|
+
}, [newArea, newPath, onRender, playAnimation]);
|
|
53
|
+
return /*#__PURE__*/_jsx(SparklinePath, {
|
|
54
|
+
ref: pathRef,
|
|
55
|
+
path: initialPath,
|
|
56
|
+
stroke: lineColor
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
export const SparklineInteractiveTimeseriesPaths = /*#__PURE__*/memo(_ref2 => {
|
|
60
|
+
let {
|
|
61
|
+
data,
|
|
62
|
+
width,
|
|
63
|
+
height,
|
|
64
|
+
initialPath,
|
|
65
|
+
onRender
|
|
66
|
+
} = _ref2;
|
|
67
|
+
const {
|
|
68
|
+
lineFn,
|
|
69
|
+
areaFn
|
|
70
|
+
} = useTimeseriesPaths({
|
|
71
|
+
data,
|
|
72
|
+
width,
|
|
73
|
+
height
|
|
74
|
+
});
|
|
75
|
+
const translateProps = useMemo(() => getSparklineTransform(width, height), [width, height]);
|
|
76
|
+
const paths = data.map((timeseries, index) => {
|
|
77
|
+
return /*#__PURE__*/_jsx(TimeseriesPath, {
|
|
78
|
+
areaFn: areaFn,
|
|
79
|
+
initialPath: initialPath,
|
|
80
|
+
lineFn: lineFn,
|
|
81
|
+
onRender: index === 0 ? onRender : undefined,
|
|
82
|
+
timeseries: timeseries
|
|
83
|
+
}, timeseries.id);
|
|
84
|
+
});
|
|
85
|
+
return /*#__PURE__*/_jsx("svg", {
|
|
86
|
+
height: height,
|
|
87
|
+
width: width,
|
|
88
|
+
children: /*#__PURE__*/_jsx("g", _objectSpread(_objectSpread({}, translateProps), {}, {
|
|
89
|
+
children: paths
|
|
90
|
+
}))
|
|
91
|
+
});
|
|
92
|
+
});
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
2
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
3
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
4
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
5
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { figma } from '@figma/code-connect';
|
|
8
|
+
import { SparklineInteractive } from '../SparklineInteractive';
|
|
9
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
|
+
figma.connect(SparklineInteractive, 'https://www.figma.com/design/k5CtyJccNQUGMI5bI4lJ2g/✨-CDS-Components?node-id=320-14858&m=dev', {
|
|
11
|
+
imports: ["import { SparklineInteractive } from '@coinbase/cds-web-visualization';"],
|
|
12
|
+
props: {
|
|
13
|
+
compact: figma.boolean('compact'),
|
|
14
|
+
disableScrubbing: figma.boolean('scrubbing', {
|
|
15
|
+
false: true,
|
|
16
|
+
true: false
|
|
17
|
+
})
|
|
18
|
+
},
|
|
19
|
+
example: props => {
|
|
20
|
+
const periods = [{
|
|
21
|
+
label: '1H',
|
|
22
|
+
value: 'hour'
|
|
23
|
+
}, {
|
|
24
|
+
label: '1D',
|
|
25
|
+
value: 'day'
|
|
26
|
+
}, {
|
|
27
|
+
label: '1W',
|
|
28
|
+
value: 'week'
|
|
29
|
+
}, {
|
|
30
|
+
label: '1M',
|
|
31
|
+
value: 'month'
|
|
32
|
+
}, {
|
|
33
|
+
label: '1Y',
|
|
34
|
+
value: 'year'
|
|
35
|
+
}, {
|
|
36
|
+
label: 'All',
|
|
37
|
+
value: 'all'
|
|
38
|
+
}];
|
|
39
|
+
const data = {
|
|
40
|
+
hour: [],
|
|
41
|
+
day: [{
|
|
42
|
+
value: 49259.38,
|
|
43
|
+
date: new Date('2021-12-05T04:00:00.000Z')
|
|
44
|
+
}, {
|
|
45
|
+
value: 49163.79,
|
|
46
|
+
date: new Date('2021-12-05T04:05:00.000Z')
|
|
47
|
+
}, {
|
|
48
|
+
value: 49146.66,
|
|
49
|
+
date: new Date('2021-12-05T04:10:00.000Z')
|
|
50
|
+
}, {
|
|
51
|
+
value: 49083.92,
|
|
52
|
+
date: new Date('2021-12-05T04:15:00.000Z')
|
|
53
|
+
}, {
|
|
54
|
+
value: 49115.3,
|
|
55
|
+
date: new Date('2021-12-05T04:20:00.000Z')
|
|
56
|
+
}, {
|
|
57
|
+
value: 48992.14,
|
|
58
|
+
date: new Date('2021-12-05T04:25:00.000Z')
|
|
59
|
+
}, {
|
|
60
|
+
value: 49075.75,
|
|
61
|
+
date: new Date('2021-12-05T04:30:00.000Z')
|
|
62
|
+
}, {
|
|
63
|
+
value: 49025.78,
|
|
64
|
+
date: new Date('2021-12-05T04:35:00.000Z')
|
|
65
|
+
}, {
|
|
66
|
+
value: 49066.23,
|
|
67
|
+
date: new Date('2021-12-05T04:40:00.000Z')
|
|
68
|
+
}, {
|
|
69
|
+
value: 49247.82,
|
|
70
|
+
date: new Date('2021-12-05T04:45:00.000Z')
|
|
71
|
+
}],
|
|
72
|
+
week: [],
|
|
73
|
+
month: [],
|
|
74
|
+
year: [],
|
|
75
|
+
all: []
|
|
76
|
+
};
|
|
77
|
+
return /*#__PURE__*/_jsx(SparklineInteractive, _objectSpread({
|
|
78
|
+
data: data,
|
|
79
|
+
defaultPeriod: "day",
|
|
80
|
+
formatDate: date => date.toLocaleString('en-US', {
|
|
81
|
+
timeZone: 'America/New_York',
|
|
82
|
+
hour: 'numeric',
|
|
83
|
+
minute: 'numeric'
|
|
84
|
+
}),
|
|
85
|
+
periods: periods,
|
|
86
|
+
strokeColor: "#cb51bb"
|
|
87
|
+
}, props));
|
|
88
|
+
}
|
|
89
|
+
});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
.cds-fadeInCss-f1sjpdr1.cds-fadeInCss-f1sjpdr1{-webkit-animation:cdsSparklineInteractiveFadeIn-cds-fadeInCss-f1sjpdr1 200ms cubic-bezier(0.6,0,0.15,1);animation:cdsSparklineInteractiveFadeIn-cds-fadeInCss-f1sjpdr1 200ms cubic-bezier(0.6,0,0.15,1);opacity:1;}@-webkit-keyframes cdsSparklineInteractiveFadeIn-cds-fadeInCss-f1sjpdr1{0%{opacity:0;}100%{opacity:1;}}@keyframes cdsSparklineInteractiveFadeIn-cds-fadeInCss-f1sjpdr1{0%{opacity:0;}100%{opacity:1;}}
|
|
2
|
+
.cds-fadeOutCss-fsxar9z.cds-fadeOutCss-fsxar9z{-webkit-animation:cdsSparklineInteractiveFadeOut-cds-fadeOutCss-fsxar9z 200ms cubic-bezier(0.6,0,0.15,1);animation:cdsSparklineInteractiveFadeOut-cds-fadeOutCss-fsxar9z 200ms cubic-bezier(0.6,0,0.15,1);opacity:0;}@-webkit-keyframes cdsSparklineInteractiveFadeOut-cds-fadeOutCss-fsxar9z{0%{opacity:1;}100%{opacity:0;}}@keyframes cdsSparklineInteractiveFadeOut-cds-fadeOutCss-fsxar9z{0%{opacity:1;}100%{opacity:0;}}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { fadeDuration } from '@coinbase/cds-common/tokens/sparkline';
|
|
2
|
+
import { cubicBezier } from '@coinbase/cds-web/animation/convertMotionConfig';
|
|
3
|
+
// keyframes are global so they should be namespaced
|
|
4
|
+
const fadeInCss = "cds-fadeInCss-f1sjpdr1";
|
|
5
|
+
const fadeOutCss = "cds-fadeOutCss-fsxar9z";
|
|
6
|
+
export function fadeOut(domNode) {
|
|
7
|
+
domNode === null || domNode === void 0 || domNode.classList.remove(fadeInCss);
|
|
8
|
+
domNode === null || domNode === void 0 || domNode.classList.add(fadeOutCss);
|
|
9
|
+
}
|
|
10
|
+
export function fadeIn(domNode) {
|
|
11
|
+
domNode === null || domNode === void 0 || domNode.classList.add(fadeInCss);
|
|
12
|
+
domNode === null || domNode === void 0 || domNode.classList.remove(fadeOutCss);
|
|
13
|
+
}
|
|
14
|
+
import "./fade.css";
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { borderWidth, chartCompactHeight, chartHeight as chartHeightToken } from '@coinbase/cds-common/tokens/sparkline';
|
|
3
|
+
import { useSparklineInteractiveContext } from './SparklineInteractiveProvider';
|
|
4
|
+
export function useSparklineInteractiveConstants() {
|
|
5
|
+
const {
|
|
6
|
+
width: chartWidth,
|
|
7
|
+
compact
|
|
8
|
+
} = useSparklineInteractiveContext();
|
|
9
|
+
return useMemo(() => {
|
|
10
|
+
const chartHeight = compact ? chartCompactHeight : chartHeightToken;
|
|
11
|
+
const xRange = [borderWidth, chartWidth - borderWidth];
|
|
12
|
+
const yRange = [chartHeight - borderWidth, borderWidth];
|
|
13
|
+
const startX = 0;
|
|
14
|
+
const endX = xRange[1];
|
|
15
|
+
return {
|
|
16
|
+
chartWidth,
|
|
17
|
+
chartHeight,
|
|
18
|
+
chartDimensionStyles: {
|
|
19
|
+
height: chartHeight,
|
|
20
|
+
width: chartWidth
|
|
21
|
+
},
|
|
22
|
+
xRange,
|
|
23
|
+
yRange,
|
|
24
|
+
startX,
|
|
25
|
+
endX
|
|
26
|
+
};
|
|
27
|
+
}, [chartWidth, compact]);
|
|
28
|
+
}
|