From 457ebfa490e6809f567155eb8789fb45d03cc05c Mon Sep 17 00:00:00 2001 From: plouc Date: Tue, 16 Jun 2020 08:58:29 +0900 Subject: [PATCH] feat(website): add the ability to control react-spring config --- packages/funnel/src/PartLabel.js | 8 +- .../src/components/controls/ControlsGroup.js | 14 ++ .../controls/MotionConfigControl.js | 186 ++++++++++++++++++ website/src/components/controls/Radio.js | 2 +- website/src/lib/componentProperties.js | 11 ++ 5 files changed, 217 insertions(+), 4 deletions(-) create mode 100644 website/src/components/controls/MotionConfigControl.js diff --git a/packages/funnel/src/PartLabel.js b/packages/funnel/src/PartLabel.js index 87d1a36c17..1f55d1f0a2 100644 --- a/packages/funnel/src/PartLabel.js +++ b/packages/funnel/src/PartLabel.js @@ -8,16 +8,18 @@ */ import React from 'react' import PropTypes from 'prop-types' -import { config, useSpring, animated } from 'react-spring' -import { useTheme } from '@nivo/core' +import { useSpring, animated } from 'react-spring' +import { useTheme, useMotionConfig } from '@nivo/core' export const PartLabel = ({ part }) => { const theme = useTheme() + const { animate, config: motionConfig } = useMotionConfig() const animatedProps = useSpring({ transform: `translate(${part.x}, ${part.y})`, color: part.labelColor, - config: config.wobbly, + config: motionConfig, + immediate: !animate, }) return ( diff --git a/website/src/components/controls/ControlsGroup.js b/website/src/components/controls/ControlsGroup.js index 9f0c26d0a5..8b7e8a9bd2 100644 --- a/website/src/components/controls/ControlsGroup.js +++ b/website/src/components/controls/ControlsGroup.js @@ -25,6 +25,7 @@ import BoxAnchorControl from './BoxAnchorControl' import MarginControl from './MarginControl' import OpacityControl from './OpacityControl' import LineWidthControl from './LineWidthControl' +import MotionConfigControl from './MotionConfigControl' import NumberArrayControl from './NumberArrayControl' import AngleControl from './AngleControl' import OrdinalColorsControl from './OrdinalColorsControl' @@ -242,6 +243,19 @@ const ControlSwitcher = memo( /> ) + case 'motionConfig': + return ( + + ) + case 'opacity': return ( ({ + value: presetId, + label: presetId, +})) + +const defaultConfig = { + mass: 1, + tension: 170, + friction: 26, + clamp: false, + precision: 0.01, + velocity: 0, +} + +const MotionConfigControl = memo(({ id, property, flavors, currentFlavor, value, onChange }) => { + const type = isString(value) ? 'preset' : 'custom' + const [preset, setPreset] = useState(type === 'preset' ? value : 'default') + const [customConfig, setCustomConfig] = useState(type === 'custom' ? value : defaultConfig) + + const handleTypeChange = useCallback( + event => { + const newType = event.target.value + if (newType === 'preset') { + onChange(preset) + } else { + onChange(customConfig) + } + }, + [onChange] + ) + + const handlePresetChange = useCallback( + option => { + setPreset(option.value) + onChange(option.value) + }, + [onChange] + ) + + const handleMassChange = event => { + const mass = Number(event.target.value) + const newCustomConfig = { + ...customConfig, + mass, + } + setCustomConfig(newCustomConfig) + onChange(newCustomConfig) + } + + const handleTensionChange = event => { + const tension = Number(event.target.value) + const newCustomConfig = { + ...customConfig, + tension, + } + setCustomConfig(newCustomConfig) + onChange(newCustomConfig) + } + + const handleFrictionChange = event => { + const friction = Number(event.target.value) + const newCustomConfig = { + ...customConfig, + friction, + } + setCustomConfig(newCustomConfig) + onChange(newCustomConfig) + } + + const handleClampChange = clamp => { + const newCustomConfig = { + ...customConfig, + clamp, + } + setCustomConfig(newCustomConfig) + onChange(newCustomConfig) + } + + return ( + + + + + {type === 'preset' && ( + + + + {value.tension} + + + + {value.friction} + + + + + + + )} + + {property.help} + + ) +}) + +export default MotionConfigControl diff --git a/website/src/components/controls/Radio.js b/website/src/components/controls/Radio.js index e4ea383179..d240914e6d 100644 --- a/website/src/components/controls/Radio.js +++ b/website/src/components/controls/Radio.js @@ -63,7 +63,7 @@ const Radio = memo(({ options, value, onChange }) => { ) }) -Radio.displayName = 'RadioControl' +Radio.displayName = 'Radio' Radio.propTypes = { value: PropTypes.string.isRequired, options: PropTypes.arrayOf( diff --git a/website/src/lib/componentProperties.js b/website/src/lib/componentProperties.js index 29e1c6e2bc..6db0680a02 100644 --- a/website/src/lib/componentProperties.js +++ b/website/src/lib/componentProperties.js @@ -89,6 +89,17 @@ export const motionProperties = (flavors, defaults, type = 'react-motion') => { max: 40, }, }) + } else if (type === 'react-spring') { + props.push({ + key: 'motionConfig', + flavors, + help: 'Motion config for react-spring, either a preset or a custom configuration.', + type: 'string | object', + required: false, + defaultValue: defaults.motionConfig, + controlType: 'motionConfig', + group: 'Motion', + }) } return props